【サーバーレスなユーザ管理基盤】Amazon Cognito ユーザープールにOpenID Connectを使ってLINEアカウントを連携させてみる
どうも!大阪オフィスの西村祐二です。
みなさんCognitoは使ってますか?
少し前になりますが、5月17日頃にAmazon Cognito ユーザープールにOpenID Connect(以降OIDC) プロバイダーを追加できるようになりました。
いままでは、Google,、Facebook、AmazonEC、SAMLだけだったのですが、このアップデートにより、OpenID Connectに準拠していれば、そのアカウントをAmazon Cognito ユーザープールに紐づけることが可能になります。
※Cognito Federated Identitiesとは別の話になります。
そこで今回は、LINEアカウントを使ってAmazon Cognito ユーザープールと連携してみたいと思います。
ゴール
- ログイン画面にあるソーシャルリンクをクリックするとLINEアカウントのアクセス要求の確認画面が表示
- 同意ボタンをクリックするとAmazon Cognito ユーザープールにLINEアカウントのユーザ情報が追加
- サイトにログイン可能に(ホームのページはログイン済のみアクセス可能なパスです)
というのを作っていきます。
さっそくやっていきましょう!
作業概要
大まかな作業として下記があります。
- Amazon Cognito ユーザープールを作成する
- Amazon Cognito ユーザープールを設定する
- LINEアカウントのID連携を設定する
- Amazon Cognito ユーザープールにLINEアカウントのIDプロバイダを設定
- Angularでソーシャルログインできるログインサイトを作成
Amazon Cognito ユーザープールを作成する
マネージメントコンソールから作成していきます。
ユーザプール名は今回「test-oidc」としています。また、今回はデフォルトのまま作成します。
※ハマりポイントとして、デフォルト設定ではユーザ登録時にemail属性が必須になっているため、OIDCプロバイダによってはemailが取得できない場合はエラーとなってしまいます。その場合、emailにチェックをはずしてユーザプールを作成してください。
Amazon Cognito ユーザープールを設定する
アプリクライアントを作成
アプリクライアント名を「test-oidc-app」としています。クライアントシークレットを生成のチェックを外して「アプリクライアントの作成」ボタンをクリックし作成します。
アプリクライアント作成後、アプリクライアントIDが生成されるので、メモしておきます。
ドメインを設定する
Amazon Cognitoはデフォルトでサインアップおよびサインインするページを自動的に作成してくれます。そのページにアクセスするためのドメインを設定します。
LINEアカウントのID連携を設定する
まずは、LINEデベロッパーコンソールのページを開きます。 まだデベロッパーアカウントを持っていない場合は、ユーザ登録してログインします。
https://developers.line.me/ja/
▼「LINEログインをはじめる」ボタンをクリックします。
はじめてここに来た時には、プロバイダを作成していない状態のため、まずはプロバイダーを作成しておきます。
▼プロバイダーを作成したら「LINEログイン」をクリックし、新規channelを作成します。
▼Channelを作成したら、「Channel ID」、「Channel Secret」が生成されるのでメモしておきます。
あと、下にあるユーザにメールアドレスの取得を要求できるように申請をしておいてください。「申請済み」となっていれば大丈夫です。
▼次にアプリ設定でCallback URLを指定します。OIDC IdP がユーザー認証したときに、このURLにauthorization codeをかえします。
https://<ドメイン名>.auth.<リージョン>.amazoncognito.com/oauth2/idpresponse
このURLは指定されたものになります。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-pools-oidc-idp.html
これで、LINE側の設定は完了です。
Amazon Cognito ユーザープールにLINEのIDプロバイダを設定する
IDプロバイダーを作成する
マネージメントコンソールにもどり、さきほど生成された「Channel ID」と「Channel Secret」を設定していきます。
「IDプロバイダ」を選択し、LINEは、OpenID Connectに準拠しているため、ここでは「OpenID Connect」を選択します。
▼IDプロバイダの設定欄をうめていきます。
エンドポイントについてはLINEのドキュメントを参考に設定していきます。
https://developers.line.me/ja/docs/line-login/web/integrate-line-login/
プロバイダ名:任意(ここでは、LINE)とします。
- クライアントID:さきほどメモした「Channel ID」を入力します。
- クライアントのシークレット(オプション):さきほどメモした「Channel Secret」を入力します。
- 属性のリクエストメソッド:POST
- 承認スコープ:profile email openid
- 発行者:https://access.line.me
ここで、上記を入力して「検出の実行」ボタンを押下しても失敗してしまいます。
そこで、さらに以下を入力します。
- 認証エンドポイント:https://access.line.me/oauth2/v2.1/authorize
- トークンエンドポイント:https://api.line.me/oauth2/v2.1/token
- ユーザ情報エンドポイント:https://api.line.me/v2/profile
- Jwks uri:https://api.line.me/oauth2/v2.1/verify
設定したら「プロバイダーの作成」をクリックします。
属性マッピングを設定する
ここではLINEアカウントをユーザプールに登録する際に付与する情報を設定します。どんな情報がとれるかIDプロバイダ(LINE)のドキュメントを確認しましょう。
※IDプロバイダーによってはドキュメントに記載があるけど、Cognitoで情報取得ができない場合があります。
https://developers.line.me/ja/docs/line-login/web/integrate-line-login/
今回、ユーザ登録時にemail属性が必須なのでemailをマッピングします。
アプリクライアントにIDプロバイダを設定する
設定したLINEのIDプロバイダーをアプリクライアントに設定します。
今回、動作検証が目的なので、コールバックURLはhttp://localhost:4200/idpresponse
としています。
このURLにOIDC IdP がユーザー認証したときに生成される、authorization code
がQueryParamsとして返ってきます。
Angularでソーシャルログインできるログインサイトを作成する
ログインサイト、コールバックURL先のサイトをAngularで作っていきます。
ソーシャルログインのところに絞って記載させていただきます。
通常のログイン部分は下記サイトを参考にさせていただきました。
https://qiita.com/daikiojm/items/18f718df07c28965b7b3
環境
Angular6
- Angular CLI: 6.0.5
- Node: 9.9.0
- OS: darwin x64
- Angular: 6.0.3
主なライブラリ
- aws-amplify: 0.4.1
- amazon-cognito-auth-js: 1.2.2
amazon-cognito-auth-jsはaws-amplifyに内包されていますが直接使用したかったため別途インストールしています。
また、amazon-cognito-auth-jsは型定義ファイルをインストールしておく必要があります。
npm install @type/amazon-cognito-auth-js
環境を設定する
. . . export const openid_connect = { ClientId: 'xxxxxxxxxxxxxxxx', AppWebDomain: 'xxxxxxxxx.auth.ap-northeast-1.amazoncognito.com', TokenScopesArray: [ 'profile', 'email', 'openid', 'aws.cognito.signin.user.admin', 'phone' ], RedirectUriSignIn: 'http://localhost:4200/idpresponse', RedirectUriSignOut: 'http://localhost:4200' . . .
ソーシャルアカウントと連携させるロジックを作る
ここではamazon-cognito-auth-js
を使います。
this.auth.parseCognitoWebResponse(this.router.url)
とすることで、
/oauth2/token エンドポイントにリクエストをしてくれて、ユーザーのトークンを取得してくれます。
this.router.url
にはIDプロバイダーより渡されたauthorization code
を含まれており、URLを引数に与えることで内部的にパースしてくれます。
トークンエンドポイントについてはドキュメントを参照ください。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/token-endpoint.html
. . import { CognitoAuth } from 'amazon-cognito-auth-js'; import { openid_connect } from './../../environments/environment'; . . @Injectable({ providedIn: 'root' }) export class FederateService { public auth: CognitoAuth; constructor(private router: Router) { this.auth = new CognitoAuth(openid_connect); this.handler(); } public federatedSignIn() { this.auth.useCodeGrantFlow(); this.auth.parseCognitoWebResponse(this.router.url); } public handler() { this.auth.userhandler = { onSuccess: session => console.log(session), onFailure: () => alert('Error!') }; } }
コールバックURL用のコンポーネントを作成する
federate.service.ts
を読み込んで、関数を利用します。
. . import { FederateService } from './../federate.service'; import { Component, OnInit } from '@angular/core'; . . export class IdpcallbackComponent implements OnInit { private readonly auth: CognitoAuth; constructor(private fedrated: FederateService) { this.fedrated.federatedSignIn(); } . . .
ルーティングを設定する
URLと作成したコンポーネントを紐づけします。
. . . const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, { path: 'signup', component: SignupComponent }, { path: 'idpresponse', component: IdpcallbackComponent } ]; . . .
ソーシャルログインのリンクを作成
適時自分の環境の値へ変更してください。
<a href="https://<ドメイン>.auth.<リージョン>.amazoncognito.com/login?response_type=code&client_id=<アプリクライアント ID>&redirect_uri=http://localhost:4200/idpresponse">ソーシャルログイン</a>
動作確認
▼ログイン画面の「ソーシャルログイン」のリンクをクリックすると、下記画面に移動します。
▼ボタンをクリックするとLINEアカウントの選択と、同意画面に移動します。そこで「同意する」をクリックします。
▼コールバックURL先でトークン取得の処理実行されるので、そのタイミングでユーザプールにユーザが登録されます。
ユーザ名の接頭語にIDプロバイダーの名前が設定されます。今回の場合はLINEが設定されます。
▼登録されたユーザ情報をみると属性マッピングで指定したメールアドレスも設定されています。
さいごに
いかがだったでしょうか。
Amazon Cognito ユーザープールにOpenID Connectを使ってLINEアカウントを連携させてみました。
今回はLINEアカウントを利用しましたが、OpenID Connectに準拠していれば、他のアカウントでもAmazon Cognito ユーザープールと紐づけることが可能です。
OpenID Connectをサポートしたことによって多くのアカウントと連携できるようになり、とても幅の広がる機能追加だと思います。
誰かのお役にたてれば幸いです。