Cognitoで複数のIDP認証を単一ユーザー認証として扱うベストプラクティスを考えてみました🤔

Cognitoで複数のIDP認証を単一ユーザー認証として扱うベストプラクティスを考えてみました🤔

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

こんにちは!

認証基盤を自作構築する・・なんてことは最近全くしなくなりました。

近年では、Auth0 や Cognito をはじめとした認証基盤を使用することが多いはずです。認証機能構築はアプリケーション開発にそれなりに複雑さをもたらすので、可能限りアプリケーション層とは疎結合に作りたいところです。

今回 Cognito へ登録された複数ユーザーを単一ユーザーとして扱う方法のベストプラクティスを紹介したいと思います。

想定する読者

  • Cognito でユーザー管理を行っている方
  • Cognito で複数ユーザーを単一ユーザーとして扱いたい方

はじめに

Cognito のユーザープールサインインで、以下のようなユーザー認証情報をユーザプールへ蓄えることを想定します。

  • メールアドレスサインイン
  • Amazon サインイン
  • Facebook サインイン

認証方法は別だけど、単一ユーザーとして扱いたいシーンは多いはずです。

例えば、メールアドレスで登録したユーザーのマイページに「Facebook 認証」ボタンがあるとします。Facebook 認証をクリックすると、当然 Facebook 認証情報が現在のログイン中のユーザーに紐づくわけですが、ユーザープールの認証情報は別物として扱われますよね。

このようなケースに対して、方法として大きく分けて2つ実現方法があります。

パターン1:Cognito ID Pool を使用した ID の結合を行う

Cognito IDプールでは、複数のIDプロバイダーのユーザーの ID の結合し、一意な ID (IdentityId) を発行することが可能です。

User Pool から発行される ID Token と、 Facebook 等から発行されるアクセストークンを Logins として設定することで ID の結合が行われます。

Javascriptの実装参考はこちら

1度 ID の結合が行われると、結合を行った ID プロバイダーから発行された有効なトークンを1つ指定するのみで、再度結合した一意な ID を取得することが可能となります。

この一意な ID をベースに、直接 AWS サービスへアクセスを行う構成や、アプリケーションを使用する構成の検討が可能です。

この案の注意点としては、 Cognito ID Pool が対応している ID プロバイダーには限りがあります…。

パターン2:User Pool ユーザー同士のマッピングテーブルを用意する

User Pool ユーザーの sub に対して、連携したいIDプロバイダーのユーザーを識別可能な ID とのマッピングテーブルを作成する方法です。

例として Facebook の場合には、 Facebook のアクセストークンを検証する機能等を用いて、 Facebook の内部ユーザー ID と User Pool ユーザーのsub値を保存するような形となります。

1と2どちらがいいのか?

  • 1の方はプログラミングコストが低い(半自動的に構築可能)
  • 2の方が自分で定義した様々な IDP と連携が可能である

どちらも一長一短ですね。私としては、まだ仕様が固まっていない状況であれば、2の方を推奨します。(仕様が定まっていない状態で認証 ID プロバイダーを Cognito 依存で決めてしまうのは危険ですので)

まとめ

認証基盤開発の成功の秘訣は、認証したいIDPは何なのか、また認証をどのようにしたいのかを事前にしっかり決めることです。(MFA 必須なのか、認証状態の生存時間はどの程度の時間幅にするのか)

私たちが普段開発支援を行う際は、新規事業などの仕様が決まってないアジャイル開発が多数ですので、パターン2の方を採用して認証基盤の開発を行っています。

逆に業務アプリなどの場合は SNS 認証などはまず行わないので、メールアドレスなどの通常のユーザープールサインインを用いて開発を行いますので、パターン2のようなマッピングテーブルの開発は不要ですね。

企業様によっては LDAP 認証などを必要とするケースがありますが、その場合は別途認証用のエンドポイントを提供いただければ問題なく開発は可能です。(認証基板が AWS 外になった場合、AWS 上での認可の仕組みの提供が複雑になりますが…)

サーバーレス開発については、お気軽にお問い合わせください。