👻

Amazon Cognitoで共通認証基盤を作った話

2023/08/04に公開

はじめに

これは私が経験したCognitoを利用した開発の話です。具体的なプロダクトや実装内容は伏せつつも、学習手順や調査の進め方などを重点的に書き留めておきます。

ユースケース

自社が管理していたいくつかのコンテンツを一つのアカウントでログインできるようにする。
また、ログイン状態も共有できる。

  • IDプラットフォームの提供
    • メールアドレスによる登録・認証機能
    • パスワード管理機能
    • 退会機能(コンテンツを先に退会していることを前提とする)
  • 各コンテンツへのアクセス認可機能の提供

認証・認可の世界

起点として、およそAmazon Cognitoの利用が決まっていたので、こちらのドキュメントを読み漁りました。ちなみにPDFでダウンロードができるので、こちらをローカルに保持しておくと網羅的に読めます。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-dg.pdf

そもそも認証・認可は似通った単語ですが、 意味が異なります。
こちらの違いをはっきりさせることが初手でした。

  • 認証(authentication): 利用者の本人確認
  • 認可(authorization): 権限を与えて良いか否かの判断

英語表記も非常に似ているので、コード上でも auth と略すのはやめました。

OIDC(OpenID Connect)

https://www.openid.or.jp/document/

「認証と認可のためのオープンスタンダードプロトコル」と説明されましたが、要は 認証・認可に用いられる作法 で、フローや各リソースの呼称が定義されています。「アクセストークン」「リフレッシュトークン」みたいな認証に関わる用語を端的に聞いたことがあるかもしれませんが、こちらで定義されています。

JWT(JSON Web Token)

認証トークンの規格で、Cognitoでもこちらを利用しているため実コーディングで頻繁に定義を確認します。エンコードされた値がやり取りされるため、以下のサイトを利用して復号検証をおこなっていました。

https://jwt.io/

Auth0が提供しているとのことで信頼して利用していました。
(とはいえ、本番環境のトークンは貼り付けないほうが良いと思います)

Cognitoに辿り着かない…

Cognitoの記事を書き始めたのになかなか触れられません。ですが、実際にドキュメントを読む際には前述した知識が前提となるので、認証・認可に初めて触れる方はこの手順を通らなければならないと思います。

とはいえ、先も長いので多くを割愛しながらも次の岐路に向かいます。

ベストプラクティス

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/multi-tenant-application-best-practices.html

いくつかのプラクティスがこちらのドキュメントで紹介されています。ドキュメントを読み進める順序としては、プラクティスの中からもっとも要件と近しいユースケースを見つけ出し、その実装について深く学ぶのが効率的です。

この中で、アプリケーションクライアントベースのマルチテナンシー というのが今回の要件に対してドンピシャだったので、これらの手順に則り作業を始めることにしました。

ユーザープール・IDプール

WEBのコンソールがこの2つから始まっているので、まずは知っておくのが良いかと思います。

  • ユーザープール: ユーザー認証とアカウント管理のためのユーザーディレクトリです。ユーザー情報を保持・管理する機能を有します。
  • IDプール: 外部認証を用いてユーザープールのユーザーの認証に用いたり、S3等のリソースへの一時的な認可を与えることができます。外部認証との連携が不要なら利用しません。

ユーザープールについて

今回の要件ではIDプールの利用が必須でありませんでした。
なので、ユーザープールの特徴などについて、少し深掘りしておこうと思います。

フィールドについて

ユーザープールのど真ん中の機能は、ユーザー情報の管理になります。そのため、プール作成後はユーザーを一覧した管理画面を閲覧することができます。

ユーザープールでは以下のようなフィールドが利用できます。

  • sub: ユーザーIDとしてユニークなハッシュが付与されます。OIDCに準拠したフィールドです。テナント側にあるユーザー情報を紐つける際にユニークなIDとして利用してました。
  • Username / email / phone_number: ログイン時のキーとして利用できるフィールドです。email、phone_number は認証にも利用されます。ログインのキーとして利用しなければユニークになりません。(2つのアカウントをひとつのアドレスで認証できる)
  • カスタム属性: 50個まで独自の属性を付与できますが、一度作ると名称を変えることができないので注意。
  • その他にも、こちらに一覧があります。

アプリケーションクライアント

こちらがマルチテナントにおける「テナント」側の設定になります。ユーザープールに対し、複数のアプリケーションクライアントを設定することができ、個々にクライアントIDが発行されます。

クライアントIDごとに、トークンの有効時間やユーザープールに対する書き換え権限などを設定することができます。

手っ取り早く動作を試せる「ホストされたUI」

「アプリケーションの統合」のカテゴリにある「ホストされたUI」を有効にすると、認証ページが自動生成されます。こちらを利用することで、ログイン機能を迅速に試すことができます。

ただし、こちらのページは日本語対応や細かなデザイン調整がおこなえず、現場ではフルスクラッチによる開発をおこないました。

社内ツールや開発支援での利用に適していると思われます。


参考資料

かなり駆け足で要点だけを書きましたが、ざっと情報収集の過程をまとめました。

この開発規模になると、ネット上で事例や記事を探すのが非常に困難でした。
そんな中で以下の2つの資料、特に 「AWS Black Belt Online Seminar」 のスライドは非常に具体的な知識を得ることができました。正直、このふたつを読んでおけば万全です。

https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-dg.pdf

https://d1.awsstatic.com/webinars/jp/pdf/services/20200630_AWS_BlackBelt_Amazon Cognito.pdf

総括

Amazon Cognitoというサービスはリソースの提供以上に要件の提示が強く、当然ながら仕様理解に多く時間を割きました。プロダクトを開発するにあたり、要件ばかりはブラックボックス化ができないので、Cognitoの理解=認証・認可の理解という座組を知ることが出発点かと思いました。

Discussion