【サーバーレスなユーザ管理基盤】Amazon Cognito ユーザープールにOpenID Connectを使ってLINEアカウントを連携させてみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どうも!大阪オフィスの西村祐二です。

みなさんCognitoは使ってますか?

少し前になりますが、5月17日頃にAmazon Cognito ユーザープールにOpenID Connect(以降OIDC) プロバイダーを追加できるようになりました。

https://aws.amazon.com/jp/about-aws/whats-new/2018/05/amazon-cognito-now-supports-the-capability-to-add-custom-oidc-providers/

いままでは、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

主なライブラリ

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をサポートしたことによって多くのアカウントと連携できるようになり、とても幅の広がる機能追加だと思います。

誰かのお役にたてれば幸いです。