LINE Loginを利用したWebアプリを ASP.NET Core + OpenID Connectで実装する(その2:メールアドレスを取得する)

この記事は、以下のエントリの続きとなります。

pierre3.hatenablog.com

今回は、LINEでログイン時にユーザーのメールアドレスを取得する方法について述べます。

メールアドレスの取得権限を取得する

LINE Loginでメールアドレスを取得するには、LINE Loginアカウントの設定画面から申請して取得権限を付与してもらう必要があります。

f:id:pierre3:20180331212033p:plain:w600

LINE Developers コンソール でLINE Loginアカウントを選択して、Channel基本設定画面を開きます。
OpenID Connect - メールアドレス」の「申請」をクリックすると以下のような申請画面が表示されます。

f:id:pierre3:20180331212045p:plain:w600

この画面から申請を行うのですが、

本サービスで、メールアドレスの取得/利用目的について、ユーザに通知、明示、または同意取得している部分のスクリーンショットをアップロードしてください。

と記載されている通り、申請するには上記のようなスクリーンショットをアップロードする必要があります。

メールの取得/利用目的を明示したログイン画面を作る

前回までのアプリケーションでは、未ログイン時にトップページへアクセスするとLINEのログイン画面が直接表示されるようになっていましたが、以下のようなログイン画面を挟むように修正します。

f:id:pierre3:20180331223950p:plain:w600

この画面のスクリーンショットを取って、申請に使用することとします。

View とControllerを修正する

・Views/AccountフォルダにLogin.cshtmlを作成します。

<-- Login.cshtml -->

@{
    ViewData["Title"] = "Login";
}

<div class="jumbotron">
    <div class="panel panel-info center-block">
        <div class="panel-heading">ログインしてください</div>
        <div class="panel-body">
            LINEアカウントを利用してログインを行います。<br />
            <hr />
            本Webサービスでは、ログイン時の認証画面にて許可を頂いた場合のみ、あなたのLINEアカウントに登録されているメールアドレスを取得します。<br />
            取得したメールアドレスは、以下の目的以外では使用いたしません。また、法令に定められた場合を除き、第三者への提供はいたしません。
            <ul>
                <li>ユーザーIDとしてアカウントの管理に利用</li>
                <li>パスワード再発行時の本人確認に利用</li>
            </ul>
            <hr/>
        </div>
        <p class="text-center"><a asp-area="" asp-controller="Account" asp-action="LineLogin">
            <img src="~/images/btn_login_base.png"/>
        </a>
        </p>
    </div>
</div>

・Viewに対応するメソッドをAccountControllerに追加します。

public class AccountController : Controller
{
    //ログイン画面(/Account/Login)
    public IActionResult Login()
    {
        return View();
    }

    //ログイン画面の「LINE Log in」ボタンのアクション
    public IActionResult LineLogin()
    {
        return Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectDefaults.AuthenticationScheme);
    }

    public IActionResult Logout()
    {
        return SignOut(new AuthenticationProperties { RedirectUri = "/" }, CookieAuthenticationDefaults.AuthenticationScheme);
    }
}

これでパーツは揃いました。あとはControllerで[Authorize]属性を付けたページにアクセスした際に、ログインページ(/Acount/Login)にリダイレクトするように設定するだけです。

現在LIENのログイン画面にリダイレクトされているのは、StartupクラスのConfigurationService() に記述した以下の設定があるためです。

options.DefaultChallengeScheme = OpenIdConnectDefault.AuthenticationScheme;

この1行を削除するだけで、既定のログインページ「/Account/Login」へリダイレクトされるようになります。

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.Configure<LineSettings>(Configuration.GetSection("LineSettings"));

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        
        //この設定により、未ログイン時はLINEのログイン画面へリダイレクトされる。
        //options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(o =>
    {
        //...
    });
}

ログイン画面のスクリーンショットを取ったら、先ほどの申請画面にアップロードします。

f:id:pierre3:20180401081819p:plain:w600

同意する項目のチェックボックスにチェックを入れて「申請」をクリックします。
申請が受理されると以下の様に「申請済み」と表示され、メールアドレスの取得ができるようになります。

( 私が試したところ、「申請」クリック後即座に「申請済み」となりメールアドレスの取得も可能となりました。(画像認識で自動判定とかしているのかしら?))

f:id:pierre3:20180401082656p:plain:w600

OpenID Connectでメールアドレスを取得するように設定する

メールアドレスの取得権限が付与されたら、あとは認証時のスコープに"email"を追加するだけです。

//Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.Configure<LineSettings>(Configuration.GetSection("LineSettings"));

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(o =>
    {
        o.ClientId = Configuration["LineSettings:LoginClientId"];
        o.ClientSecret = Configuration["LineSettings:LoginClientSecret"];
        o.ResponseType = OpenIdConnectResponseType.Code;
        o.UseTokenLifetime = true;
        o.SaveTokens = true;
        //スコープにemailを追加
        o.Scope.Add("email");
                
        o.Configuration = new OpenIdConnectConfiguration
        {
            Issuer = "https://access.line.me",
            AuthorizationEndpoint = "https://access.line.me/oauth2/v2.1/authorize?bot_prompt=aggressive",
            TokenEndpoint = "https://api.line.me/oauth2/v2.1/token"
        };
        o.TokenValidationParameters = new TokenValidationParameters
        {
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(o.ClientSecret)),
            NameClaimType = "name",
            ValidAudience = o.ClientId
        };
    });
}

取得したメールアドレスを確認する

トップページに取得したメールアドレスを表示するようにHome/IndexのViewを書き換えます。
メールアドレスの取得にはClaimTypes.Emailを使用します。

@{
    ViewData["Title"] = "Home Page";
}
@using System.Security.Claims;

<div class="jumbotron">
    <div class="panel panel-default center-block">
        <div class="panel panel-heading">
            <div class="row">
                <div class="col-md-10 col-sm-10 col-xs-8">
                    <p>
                        <img src="@User.FindFirst("picture")?.Value" width="32" height="32" alt="User Image" />
                        @User.Identity.Name (@User.FindFirst(ClaimTypes.Email)?.Value)
                    </p>
                </div>
                <div class="col-md-2 col-sm-2 col-xs-4">
                    <a class="btn btn-default" role="button" asp-area="" asp-controller="Account" asp-action="Logout">Logout</a>
                </div>
            </div>
        </div>
        <div class="panel panel-body">
            <h2>プッシュメッセージ送信テスト</h2>
            <form role="form" asp-area="" asp-controller="Home" asp-action="PushMessage" method="post">
                <input type="text" name="pushMessage" class="form-control" placeholder="プッシュするメッセージを入力してください">
                <button type="submit" class="btn btn-default">送信</button>
            </form>
        </div>
    </div>
</div>

これで準備完了です。確認してみましょう。

・ログイン時の認可画面で取得項目にメールアドレスが追加されています。

f:id:pierre3:20180401085958p:plain:w500

・メールアドレスの取得を許可してログイン。取得したメールアドレスが表示されました!

f:id:pierre3:20180401090041p:plain:w600