re:Invent 2024: AWS SaaS Factoryが語るマルチテナントでのFederated identity
はじめに
海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!
📖 AWS re:Invent 2024 - Supporting federated identity in multi-tenant environments (SAS307)
この動画では、マルチテナントSaaS環境におけるFederated identityサポートの実装について、AWS SaaS Factoryの専門家が詳しく解説しています。Amazon Cognitoを活用したFederationの実装方法や、テナントの企業IDPとの統合方法、そしてUser Poolの設計やLambda Triggerを使用したカスタマイズについて具体的に説明しています。特に、テナントオンボーディングにおけるFederation設定の自動化や、複数のIdentity Providerが存在する場合の動的な解決方法など、実装上の重要なポイントが示されています。また、Federation実装時の課題であるユーザー数の制限やコスト面についても言及されており、SaaSプロバイダーがFederationを導入する際に必要な知識を包括的にカバーしています。
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。
re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!
本編
SaaS環境におけるFederated Identityサポートの概要
こんにちは。本日はご参加いただき、ありがとうございます。皆様にお集まりいただき、大変うれしく思います。スライドにもありますように、本日は非常に具体的なトピックについて掘り下げていきます。マルチテナントSaaS環境におけるFederated identityサポートの追加についてです。私はDhammika Sriyanandaと申します。そして、本日は同僚のToby Buckleyも登壇いたします。私たちは両者ともAWSのSenior Architectsです。AWS SaaS Factoryというチームに所属しており、お客様やパートナー様がAWS上でマルチテナントソリューションの構築、移行、モダナイズを行う際のサポートを行っています。
お客様からSaaSソリューションの構築支援のご相談をいただく際、最初に議論するポイントの一つが、ユーザーとそのアイデンティティの管理方法、そしてSaaSアプリケーションでのアイデンティティ運用の実現方法です。多くの場合、私たちは標準的なSaaSアイデンティティワークフローの実装をサポートしています。これは、テナント、テナントユーザー、およびアイデンティティを一元的に管理する方式です。このアプローチにより、SaaSプロバイダーはSaaSアプリ内でのアイデンティティ管理だけでなく、エンドユーザーへの認証・認可などのアイデンティティ運用を効果的に提供することができます。
本日は、さらに一歩進んで、SaaSアプリケーションにFederated identityを追加する方法について見ていきます。これにより、SaaSプロバイダーである皆様は、テナントが独自のIDPを使用してSaaSアプリケーションにシングルサインオンできるように設定することが可能になります。これはLevel 300の内容となりますので、コーディングやデモを行う時間はないかもしれませんが、設計原則、アーキテクチャパターン、そしてSaaSアプリケーションへのFederation追加に関する実装の詳細について深く掘り下げていきます。Amazon Cognitoを例に取り上げながら、さまざまなFederationプロトコルの実装方法を見ていきましょう。
標準的なSaaSアイデンティティパターンとその実装
Federationの話に入る前に、標準的なSaaSアイデンティティパターンと基本原則について時間をかけて掘り下げたいと思います。なぜなら、これらはFederationのストーリーにおいても有効で重要な要素となるからです。 大まかに見ると、SaaSアプリケーションは2つの主要なコンポーネントで構成されています。ビジネスロジック、マイクロサービス、データベースを含むアプリケーションプレーンと、 SaaSプロバイダーがSaaSアプリケーションを効率的に運用するための共有サービスを提供するSaaS Control Planeです。 SaaS Control Planeの主要な機能の一つは、シームレスなテナントオンボーディング機能を提供することです。これにより、テナントをオンボードし、SaaSアプリケーション内でユーザーを作成するよう依頼することができます。
SaaS IDP内でプロファイルを作成する際にテナントユーザーから必要なデータセットを見てみると、主に2つのデータタイプがあります。一般的に、ユーザー名、パスワード、その他のアイデンティティ詳細といったユーザー属性の提供を依頼します。 SaaS IDP内でプロファイルを作成する際、テナントIDとテナントコンテキストも同時に注入する必要があります。つまり、SaaS IDPで作成するテナントユーザーには、ユーザーアイデンティティとテナントアイデンティティの両方が含まれることになります。これをSaaSアイデンティティと呼んでおり、アプリケーション内でユーザーを一意に識別するのに役立ちます。
この設計の主な目的は、テナントユーザーが認証に成功した際に、SaaSアプリケーションと効率的にやり取りできるよう、このSaaSアイデンティティをユーザーに渡せるようにすることです。 実装方法は複数ありますが、SaaS IDPがトークンベースのアイデンティティ操作をサポートしている場合、JSON Web Tokenを使ってユーザーのアイデンティティを表現し、それをユーザーに発行するという方法が簡単に実現できます。これらのトークンは通常、SaaS IDPによって完全に管理され、デフォルトでセキュリティが組み込まれています。例えば、暗号化されており、TTLを持ち、一定時間後に失効するといった具合です。このようなトークンベースのアイデンティティ実装により、テナントユーザーとSaaSアプリケーション間の下流のコミュニケーションを自動化することが大きく促進されます。
具体例を見てみましょう。ここでは、SaaS IDPとしてAmazon Cognitoを使用したSaaSアプリケーションがあり、すでに1つのテナントがオンボードされています。Johnはそのテナントのユーザーの1人で、すでにAmazon Cognitoにプロファイルが作成されています。 Johnが SaaSアプリケーションにアクセスしようとした時、有効なセッションが存在しない場合、SaaSアプリはCognitoにJohnの認証を依頼します。 低レベルでは、CognitoのOAuth2/authorizeエンドポイントを呼び出してこれを実行します。CognitoはOAuth2仕様の上に構築されたOpenID Connect実装なので、アイデンティティ操作のためにCognitoと連携する際は、OAuth2エンドポイントを使用することになります。
この段階で、Cognitoはログインページを表示します。 ここでは、テナントユーザーの認証用のCognito管理のフロントエンドインターフェースであるCognito Hosted UIを活用しています。Johnは作成したユーザー名とパスワードを入力し、Cognitoが認証を実行します。認証が成功すると、 CognitoはSaaSアプリケーションに認可コードを返します。SaaSアプリは、この認可コードを使ってOAuth2/authorizeの標準エンドポイントを通じてトークンを要求できます。 CognitoはJohnに関連付けられたSaaSアイデンティティをトークンに変換し、標準的なIDトークン、アクセストークン、リフレッシュトークンをSaaSアプリケーションに返します。
アプリケーションの開発方法に基づいて、 JohnのアイデンティティはIDトークンまたはアクセストークンのいずれかで表現できます。この例では、 JohnのSaaSアイデンティティを表現するためにIDトークンを活用しており、カスタム属性としてユーザー詳細やテナント詳細を確認できます。これをHTTPヘッダーとして、 Johnが行うSaaSアプリケーションとの下流通信におけるすべてのAPIコールに簡単に含めることができます。これにより、すべてのマイクロサービスがデフォルトでそのトークンを取得でき、デコードしてJohnのユーザー詳細、テナントID、およびすべてのテナント操作に必要なテナント詳細にアクセスできます。このように、トークンベースの認証により、これらの下流のワークフローを自動化することができます。
この段階でのCognito設計を見ると、 SaaSプロバイダーにはいくつかの責任があります。1つはユーザースキーマの定義で、これにはSaaS IDPで作成されるユーザーに必要な属性の決定、CognitoでのOAuth2属性へのマッピング、SaaSアイデンティティを表現するために必要なカスタム属性の作成が含まれます。これに基づいて、テナントユーザーがオンボードされる際にCognitoがユーザーを作成します。さらに、1つまたは複数のApp Clientを作成します。 これらは、認証などのアイデンティティ操作のためにテナントユーザーがUser Poolに接続するためのエントリーポイントとして機能します。また、Cognito Domainもあり、これはHosted UIとOAuth2エンドポイントを有効にするUser Poolに提供される一意のURLです。これら以外にも、 特定のSaaSユースケースに基づいて、User Pool内でSaaSプロバイダーが利用できる多くの設定があります。
Federationの導入と課題
標準的なSaaSのアイデンティティモデルをご覧いただくと、SaaSプロバイダーがSaaSアプリケーション内でユーザーとそのアイデンティティを一元管理していることがわかります。これによりアイデンティティ操作の制御が向上し、下流のコミュニケーションにおけるトークンベースの自動化が可能になります。しかし、テナントがSaaSプロバイダーに従業員のアイデンティティを管理させたくない場合はどうでしょうか?セキュリティ上の懸念や脆弱性、社内ポリシーなどの理由から、従業員が第三者のアプリケーションにサインアップしてプロフィールを作成し、ユーザー名とパスワードを提供することを推奨しないテナントもあります。そのかわりに、組織内の企業IDPを活用して、すべての企業アプリケーションにシングルサインオン機能を提供することを好みます。
組織内の従業員のアイデンティティを企業Identity Provider(IDP)で一元管理することは、すべての企業アプリケーションにとって効果的なアプローチです。例えば、従業員のJohnが退職した場合、ITチームはIDPから無効化するだけで、Johnはすべての企業アプリケーションへのアクセスを失うことになります。しかし、もしJohnが個別にSaaSアプリケーションにサインアップしていた場合、ITチームはそれらのアクセス権を削除するために多くの追加作業が必要になります。これはセキュリティのベストプラクティスとは言えません。
これらのテナントや組織からSaaSプロバイダーへの主要な要望の1つは、標準的なアイデンティティフローを避けることでした。その代わりに、企業IDPをSaaSアプリケーションと統合して、従業員が直接シングルサインオンでSaaSアプリを利用できるようにすることを望んでいます。これがSaaSアプリケーションにFederatedアイデンティティサポートを追加する主な動機です。Federationでは、Control Planeを持つSaaSアプリケーションがあり、Tenant 1や2のような企業IDPを持つテナントがオンボーディングされます。引き続きスムーズなオンボーディングを提供する必要がありますが、オンボーディング後は以前のようにSaaSアプリケーションやSaaS IDPにユーザーを作成することはありません。代わりに、企業IDPで認証を行い、それに応じてSaaSアプリケーションを利用することになります。
この場合でも、Federationの詳細とワークフローを管理するためにSaaS IDP(この場合はAmazon Cognito)は必要です。ここで疑問が生じます。Federationだけで成功するSaaSビジネスを構築できるでしょうか?おそらくそれは難しいでしょう。なぜなら、現時点でFederationや企業IDPを持っていない、あるいはシングルサインオン機能を必要としないテナントも存在するからです。そういったテナントは依然として標準的なIDPワークフローを使用する必要があります。SaaSプロバイダーはFederationをSaaSアプリケーションのプレミアム機能として位置づけ、上位層のテナントのみが利用可能とし、Basic、Free、Premiumなどの下位層のテナントは基本的なアイデンティティワークフローを使用する必要があります。
Federationを伴うテナントオンボーディングの実装
SaaSアプリケーションでFederationがシングルサインオンとどのように連携するのか、例を見てみましょう。ここでは、SaaS IDPとしてAmazon Cognitoを使用するSaaSアプリケーションと、独自の企業IDPを持つTenant 1があります。Tenant 1はFederationサポート付きでオンボーディングされています。Tenant 1のユーザーがSaaSアプリケーションにアクセスしようとすると、有効なセッションが存在しない場合、Cognitoは認証を試みますが、これらのユーザーがCognitoに作成されていないことを認識します。代わりに、Federationされるべきという設定があり、これを処理するために必要なすべての設定がCognitoに用意されています。
これらのリクエストは、クライアントサイドでそれぞれの企業のIDPへリダイレクトされます。 ユーザーは、普段から使い慣れている企業IDPのログインページを目にすることになります。そこで、ドメインのユーザー名とパスワードを入力することができます。 認証が成功すると、企業IDPはクライアントサイドのリダイレクトを通じて、リクエストをCognitoに送り返します。 Cognitoは認証と認可が成功したかを検証し、その後ユーザーはSaaSアプリケーションにアクセスできるようになります。
ご覧の通り、SaaS IDPと企業IDPという2つの信頼エンティティを非同期的な方法で接続しています。これは全体的な流れを示したものですが、この仕組みを実現するためのSaaS Control Planeの実装の詳細についても見ていきましょう。ここで、Cognito内部で何が起きているのかを理解することは、先ほどの標準的なIdentityワークフローと比較する上で興味深いポイントです。Federationを導入した場合のCognitoには、主に2つの違いがあります。先ほど触れたように、Federationを利用するテナントはSaaS IDPにユーザーを作成せず、代わりに自社のIDPで認証を行います。
ただし、Federationのワークフローの一環として、これらのユーザーはAmazon CognitoつまりSaaS IDPに自動的に作成され、これらをProxy Userと呼んでいます。Proxy Userにはユーザーの詳細情報のみが含まれます。これらのユーザー詳細は、それぞれの企業IDPによって完全に管理されます。言い換えれば、SaaSプロバイダーはこれらのユーザー詳細に関与する必要がありません。自動的に作成されるからです。
2つ目の違いは、User Pool内にFederation詳細を管理するためのエンティティが必要になることです。そのために、Federated Identity Providersというプール機能を使用します。ここでは、Federationを必要とする各テナントのプロトコル固有の設定を行うことができます。User Pool内に専用のFederated IDPを設置し、Federation関連の設定を保持することで、Federation作業を実行できるようになります。
この段階で、SaaSプロバイダーとしてFederationを実現するための非同期ワークフローを管理するという課題があることがわかりました。それ以外にも考慮すべき課題があります。その1つは、先ほど述べたように、ほとんどの場合、FederationとStandard Identityのワークフローはアプリケーション内で共存する必要があり、理想的にはSaaS IDPが両方をサポートする必要があるということです。さらに、複数の異なるIdentityプロトコルが存在し、SaaSプロバイダーとしては、テナントがどのプロトコルを使用するかについて全くコントロールできません。なぜなら、それはテナント側のドメイン主導の判断だからです。
先ほどSaaS identityの概念について触れましたが、 SaaS IDPで作成するユーザーには必ずSaaS identityが必要で、これによってダウンストリームのワークフローを自動化できます。しかし、Federatedユーザーはユーザーidentityしか持っていないため、SaaSアプリケーションで同様の自動化を実現するには、テナントIDとテナントコンテキストを注入する方法を見つける必要があります。コンプライアンスと規制は、特にSaaSアプリケーションが複数の国や地域にまたがる場合、Federationを実装する際の重要な考慮事項となります。データレジデンシー規制がある場合は、それらの国々に対応するCognitoインスタンスを用意する必要があるかもしれません。
集中管理されたSaaS Control Planeを維持しながら、ユーザーは境界を越えることなく、それぞれのCognitoインスタンスにFederationすることができます。これらの設計に関する議論は、Federation実装の前に行う必要があります。また、通常すべてのIDPはidentity操作に関して異なるクォータとコストを持っているため、コストとクォータも興味深い検討事項となります。最後に、テナントとそのユーザーにシームレスな体験を提供するため、このプロセス全体を自動化することも課題の一つとなります。
さて、複数のFederationプロトコルがあることを説明しましたが、今日はそのいくつかを見ていきましょう。先ほど簡単に触れたOpenID Connectは、OAuth 2.0の上に構築されたidentityレイヤーで、Cognitoはその一例です。Oktaのようなパートナーソリューションの多くがOIDCをサポートしています。そして、かなり以前から存在するSAML 2.0は、XMLアサーションを使用してユーザー認証を簡素化するもので、Active Directoryがその例です。Cognito マネジメントコンソールを見ると、ソーシャルプロバイダーも作成できることがわかります。これはCognitoが提供する一種の抽象化レイヤーで、ソーシャルidentityを簡単に作成できます。つまり、テナントがソーシャルidentityをサポートしている場合、ソーシャルプロバイダーを使用してSaaSアプリケーションでFederated identityとして統合できます。また、非同期ワークフローも高レベルでの課題となります。
では、実装の部分に入っていきましょう。実装に関しては、Federationを伴うテナントオンボーディングの扱い方と、シングルサインオンをサポートするために必要な追加の実装という2つの主要な領域があります。
Amazon CognitoによるFederated Identity管理
まずオンボーディングから始めましょう。例として、SaaS IDPとしてAmazon Cognitoを使用するSaaSアプリケーションがあり、テナント1は独自のIDPを持っており、これをSaaSアプリケーションとFederationで統合する必要があるとします。最初に行う必要があるのは、テナント1のIDPに「統合アプリ」と呼ばれるものを作成することです。この統合アプリは、テナント1からFederationのためにやってくるユーザーをCognitoに転送するためのエントリーポイントにすぎません。統合アプリを正常に作成するには、テナント1のIDPのプロトコルに基づいて、コールバックURLまたはSSO URLが必要になります。
Cognitoは、テナント1が適切にSaaSアプリケーションにオンボーディングされた後でなければ、これらのURLを提供することができません。これは、テナントの性質に基づいています。例えば、テナント1がPremiumティアのテナントである場合、異なるコールバックURLを持つ新しいUser Poolを作成する必要があるかもしれません。そのため、この複雑さのために、事前にURLを提供することができないのです。最初のステップとして、テナント1はSaaSアプリケーションにオンボーディングされている必要がありますが、テナント1を正常にオンボーディングするためには、Cognitoは統合アプリの設定情報を必要とします。
ご覧の通り、ここには循環依存関係が存在します。これがSaaSプロバイダーとして直面している課題であり、この依存関係を管理して、Federationを使用してオンボーディングするテナントにシームレスな体験を提供する方法を考える必要があります。いくつかの異なるワークフローを紹介しますが、これらが問題を解決する唯一の方法というわけではなく、テナントのFederationオンボーディングにシームレスな体験を提供するための視点を得るためのものです。最初のワークフローでは、OIDC IDPを持つテナント1を例に取ります。このフローはSAMLでも完全に機能しますが、ここではOIDCを例として使用しています。
SaaSの観点からは、Federationを使用するテナントを含むすべてのテナントのオンボーディングに対応するティア戦略を備えた標準的なパブリックランディングページがあります。この例では、このフローにおいて、テナント1はテナントのオンボーディングが行われる前に統合アプリを作成していないと想定しています。そのため、Federation設定は後から行えると考えて、通常のテナントとしてオンボーディングを試みることになります。
SaaSの観点からは、コントロールプレーンにこのリクエストと詳細を受け付けるための登録マイクロサービスがあります。通常のテナントオンボーディングリクエストと同様に、管理者の詳細と企業の詳細を取得します。最初に新しいテナントのテナントIDを作成し、その後、Amazon Cognitoと連携してテナントに必要なコンポーネントを作成するユーザー管理マイクロサービスを使用します。テナント1がPremiumティアであると仮定して、新しいUser Poolを作成し、テナント1用に設定を行います。その後、テナント1の管理者、つまりテナント1をオンボーディングしたユーザーを、SaaSアプリケーションでもそのテナントの管理者として設定します。
ここまでは全くFederationは関係なく、完全に非Federation型の通常のテナントオンボーディングワークフローです。この段階で、Cognitoドメインが分かっているため、コールバックURLを導き出し、テナント管理者URLと共にテナント1に通知として渡すことができます。このテナント管理者URLは、アプリケーションで提供している一般的なテナント管理パネルを指し、テナント管理者が管理操作を実行できるようにします。この段階で、テナント1はコールバックURIが渡されているため、OpenID Connect統合アプリを作成し、その側の設定を完了して、Cognitoが必要とする設定情報(アプリクライアントID、クライアントシークレット、発行者URL)を抽出することができます。そして、テナント1の管理者は実際にそのテナントの管理者であるため、テナント管理パネルにログインしてそのURLを入力することができます。これにより、Cognitoで完全なワークフローを完了させ、OpenID Connect Providerを作成することができます。
テナントのオンボーディングにおいて、テナントにシームレスな体験を提供する2段階のプロセスがあります。これにより、SaaS プロバイダーはFederationをサポートしたテナントのオンボーディングフローを自動化することができます。この段階で、テナント1のユーザーがSaaSアプリケーションにアクセスしようとすると、CognitoはOpenID Connect プロバイダーの存在により、Federationが必要であることを認識し、OpenID Connectプロトコルを介してテナント1のIDPに誘導され、そこからFederationが実行されます。
ここでOpenID Connect プロバイダーを見ると、テナント1の管理者が提供した設定の詳細が含まれています。これらはテナント1のユーザーのFederationを処理するために必要なすべての詳細です。フロー2では、テナント2の例としてSAMLを使用しています。違いは、テナント2が事前にSAML統合を作成し、この段階では不明な設定項目にはプレースホルダー値を使用している点です。その後、オンボーディングリクエストの一部として、Cognitoが完全なFederationフローを作成するために必要な設定の詳細を送信します。SAMLプロトコルの場合、Cognitoが必要とするのは、テナント2のSAML統合から提供されるメタデータURLのみです。
SaaS マイクロサービスからのリクエストを受け取ったら、テナントIDを作成します。次に、ユーザー管理マイクロサービスでユーザープールを作成して設定します。この段階でSAMLメタデータURLが分かっているため、管理者ユーザーを作成する必要はなく、直接SAMLプロバイダーを作成してこのテナントをIDPに紐付けることができます。これがSaaSアプリケーション側からの設定のすべてです。そして、URLとSP エンティティIDを導き出すことができます。これらは、テナント2がSAML統合のアプリ設定を完了するために必要な2つの設定パラメータなので、通知として送信し、テナント2側で設定を完了できるようにします。
ご覧の通り、これらは循環依存関係に対処することで、シームレスなオンボーディング体験を提供できる2つの例示的なワークフローです。推奨されるのは、Federationを使用する場合でもシームレスで摩擦のないオンボーディング体験を提供できるよう、SaaSの本質的な価値提案を損なうことなく、これらのワークフローのいずれかを選択することです。この段階で、Cognitoを見て、Federation設定におけるCognitoの実装のマルチテナント的な側面について確認することが重要です。この点についてより詳しく説明するため、Tobyを壇上にお招きしたいと思います。
Cognitoを活用したFederation実装の詳細と課題
Dhammikaが言及したように、Federationの仕組みについて詳しく説明する前に、アーキテクチャに関連するCognitoの設計について少しお話ししたいと思います。SaaS Factoryのコンテンツをお読みになったことがある方は、テナントリソースを説明する際の「プール型」と「サイロ型」という用語をご存知かもしれません。プール型の場合、リソースをすべてのテナント間で共有し、サイロ型の場合は、それらのテナントに専用のリソースを割り当てます。どちらを選択するかを決定する要因は、主にビジネス面から来ています。サイロ型の場合、より高い分離性が得られますが運用が難しくなる可能性があり、プール型の場合はよりシンプルですが分離性が低くなる可能性があります。テナントごとに別々のDynamoDBを持つか、DynamoDB内でテナントを混在させるかを検討する場合と同じルールが、ここでも適用されます。この講演では主にプールモデルに焦点を当てるので、これから見ていく内容の多くはプール型リソースに焦点を当てています。とはいえ、サイロ型についても後ほど見ていきますが、大きな違いはありません。
設計の観点から見ると、すべてのテナント向けに1つのUser Poolを用意することになります。まずはApp Clientから始めましょう。 App Clientは、アクセスを保護する対象であり、私たちが守ろうとしているものです。この場合、それはSaaSアプリケーションです。OAuthやOIDCを使用する際に、Client IDというものに気付いたことがあると思いますが、これが私たちが保護しているものです。今回のケースでは、SaaSアプリケーションは1つだけです。テナントごとに複数のデプロイメントを持つと管理が難しくなるため、これは一般的に良い方法だと考えています。
オンボーディングプロセスの一環として、Federated IDPを作成します。この場合、 青いボックスの設定で示されているように、OIDCのIDPを作成しています。テナント1のユーザーがこのフェデレーションを通じてアクセスすると、 Cognitoは自動的にそれらのユーザーをグループ内に作成します。このグループにより、必要に応じてテナント固有のIAMポリシーを適用することができます。User Pool内のユーザーは単なるフラットなリストではなく、グループ化されているのです。
同様に、2番目のケースでは、 テナント2がソーシャルプロバイダーであるFacebookを使用しています。FacebookのIDP固有の設定を使用してアクセスし、同じApp Clientを通じて、別のグループにユーザーが保存されます。興味深いのは、設定の観点から見ると、Webアプリケーション内のClient IDや発行者URL、認証局は全てこのApp Clientを指していますが、2つの異なるテナントがアクセスしているという点です。これは興味深い課題を提示します:ログイン時にFederated IDPをどのように解決するのか?これについては、しばらく考えてみてください。
これは基本的なケースで使用できますが、テナントごとにUser Poolを用意するような、より高度なことをしたい場合もあります。 例えば、テナントが他のテナントと同じUser Poolを共有することを望まない場合や、User Poolレベルで設定される異なるMFAや復旧要件が必要な場合です。Cognitoの観点からは、すべて同じように動作します。主な違いは、2つの異なるApp Clientがあることで、これは2つの異なる設定が必要になることを意味します。単一のWebアプリケーションを使用している場合は、実行時にこれらの設定項目を解決する必要があります。
では、フローがどのようになっているか見てみましょう。これが OIDCフローです。以前にも見たことがありますが、今回はユーザーフェデレーション認証を行っています。セッション(Cookieや認証情報)を持っていないテナントユーザーが認証を必要とする場合、Cognitoにアクセスします。 Cognitoの中核となるOAuth2認可エンドポイントにアクセスすると、CognitoはClient IDを確認し、フェデレーション認証が必要だと判断します。
この時点で、John Doeは IDPのログイン画面を見ています。彼がログインすると、OIDCを使用しているため、別のAuthorizeエンドポイントが呼び出されます。認証チャレンジをパスすると、OIDCはCognitoにリダイレクトして、このIDPレスポンスを返します。 OAuth2レスポンスを受け取り、この時点でCognitoは認証が完了したと判断します。 Cognitoは、Proxyユーザーまたはシャドウユーザーと呼ばれるものを作成します。これは実際のユーザーのエコーのようなものです。信頼できる情報源は依然としてサードパーティのIDPにありますが、CognitoはUser Pool内にそのユーザーのバージョンを作成します。
その後、通常の302リダイレクトが行われ、そのコードをトークンと交換し、元の状態に戻りますが、今度はフェデレーション化されています。SAMLの観点からも、非常によく似たプロセスです。
アプリケーションの観点からOAuth2のAuthorizeエンドポイントを実装する際、OAuth2のAuthorizeについてだけ知っていれば十分で、SAMLやその他のプロトコルについて知る必要はありません。CognitoはClient IDを確認し、SAML認証を実行する必要があると判断します。このプロセスは、OIDCやAuthorizeエンドポイントとは異なり、XMLベースで証明書を使用するSAMLを扱うことになります。良いニュースは、Cognitoがすべてを処理してくれるため、アプリケーション側でこれらの詳細を気にする必要がないということです。
Johnがサイトにログインすると、認証チャレンジをパスし、SAMLアサーションを受け取り、User Poolにユーザーを作成し、その後は以前と同じようにトークンを処理します。 Cognitoを1年ほど使用して気づいた重要な洞察は、Cognitoが本当の意味でFederation Hubとして機能するということです。これは他の人には明白だったかもしれませんが、私にはすぐには分かりませんでした。アプリケーションはOIDCとOAuthだけを扱えばよく、より複雑なプロトコルを扱う必要は一切ありません。これは特に有益です。なぜなら、OIDCとOAuthはWebアプリケーション分野でよくサポートされ理解されているのに対し、SAMLライブラリは多くのWebアプリで簡単に利用できないかもしれないからです。
これらのグループがどのように見えるかを見てみると、Proxyユーザーを作成した後、このコンソールのスクリーンショットでBobとSallyがOcta OIDCプロバイダーを通じて来ているのが分かります。「Octa OIDC」という名前は私が単に選んだだけで、この文字列に特別な意味はないことを指摘しておく必要があります。Cognitoはフェデレーションを通じて来るこれらのユーザーに「OctaOIDC_」という形式で名前を付け、その後に何らかの文字列が続きます。また、User Pool IDとフェデレーションの両方に関連するグループにこれらのユーザーを配置します。SAMLフェデレーションユーザー用に作成した「Octa SAML」という別のグループも確認できます。
Dhammikaが指摘した課題の1つは、テナントやカスタマーが自分たちのユーザーのライフサイクルを管理したいということでした。Federationでそれは対応できますが、別の課題に直面します:外部のFederation(ユーザーに関する信頼できる情報源)を、私たちの内部の信頼できる情報源にどのようにマッピングするかということです。例えば、OktaにBob Smithというユーザーがいて、first nameとsurnameのフィールドがありますが、last nameが必要な場合、これらの違いをどのように解決するのでしょうか? これはマッピングによって実現され、両側で行われます。Okta側では、Integration Appを作成する際、ほとんどのIDPが自分たちのバージョンの実態を標準フォーマット(この場合はOIDC)にマッピングできます。
Cognito側では、これらの標準的なOIDC属性を私たちのユーザー属性にマッピングし、彼らのバージョンを私たちのバージョンに正規化することができます。 この同じ原則はSAMLにも適用されますが、SAMLはXMLベースのスキーマを使用します。しかし、Dhammikaが言及したもう1つの課題があります:テナントIDが必要ですが、テナントは自分たちのテナントIDを知る必要すらないはずです - それは私たちが内部で管理する情報なのです。
クラウドでコードが必要なほとんどのシナリオと同様に、AWS Lambdaを使用できます。CognitoはLambda Triggerを提供しており、これはCognitoワークフロー内の基本的なライフサイクルイベントです。 Post-confirmation Lambda Triggerの使用をお勧めします。これはユーザーが作成されたときにのみ呼び出されるからです。一部のお客様はPre-token Generation Triggerの使用について質問されますが、Federation時にユーザーに付加するテナントIDを単に検索するだけなら、テナントIDはめったに変更されないため、毎回実行する必要はありません。
もっと特殊なことが必要な場合や、より頻繁に呼び出す必要がある場合は、それも可能です。これらのTriggerをすべて見てみると、それぞれをクリックすることで、いつ、なぜ使用すべきかが分かります。ワークフローの観点で見ると、かなり豊富な機能が実現可能です。
カスタム認証フローを見てみると - 実は、この講演のためにAmazon Cognitoコンソールを確認したところ、これらの多くが既に組み込まれています。これらはより一級の機能になりつつありますが、パスワードレス認証やPasskeysはすべてCognitoのTriggerで処理できます。ぜひ確認してみてください。では、それがどのようなものか見てみましょう。これは私たちが何度も見てきた単純な例です - Federationが必要だと気付き、ユーザーを作成する準備ができたところで作成しますが、今度はUser Poolにトリガーが接続されています。 そのTriggerは型付きイベントで呼び出されます。そのコードのサンプルをすぐに見てみましょう。
この例では、受信データを取得してAmazon DynamoDBで検索し、Tenant IDを見つけるという処理を呼び出しています。そのIDを使ってSDKを呼び出してTenantを更新し、その後トークンの発行に戻り、そのIDをカスタムクレームとしてトークンに含めます。ここで強調しておきたいのは、先ほどUser Schemaの使用について話した際に触れたことですが、これらの属性を追跡したい場合は、User Poolでユーザーを作成する際に必ずSchemaに含めておく必要があります。もし含めていなければ、この処理は失敗します。データを格納する場所がなければ、うまく機能しないのです。
これがそのTriggerの一例です。もちろん本番用のコードではありませんが、基本的な実装例です。先ほど述べたように、強く型付けされているので、Post-confirmation Trigger Eventを使用しています。これはTypeScriptで書かれています。このTrigger Eventには、先ほど説明したSDK呼び出しに必要なほとんどの情報が含まれていますが、Tenant IDは例外です。では、それをどのように取得するのでしょうか?ご覧のように、画面外にメソッドがあり、おそらくメールアドレスからドメインを抽出し、そのドメインに基づいてTenant IDを検索しているのだと思われます。
さて、冒頭で提起した問題について話しましょう。1つのApp Clientに複数のIdentity Providerが接続されている場合、実行時にそれをどのように解決できるでしょうか?何も対策を講じないと、このような画面が表示されますが、これは望ましくありません。ユーザーにこのような画面を見せたくないはずです。これはCognitoコンソールのアプリクライアント画面の、先週の状態を示すスクリーンショットです。App ClientがCognito User Pool認証、SAML Federation、そしてOIDC Federationに接続されているのが分かります。
これは理想的ではありません。特に100個のFederated Identityがある場合、画面がどのように表示されるのか想像もつきません。おそらく見た目は良くないでしょう。できればこれをバイパスしたいところですが、幸いにもそれは可能です。では、どのように実現するのでしょうか?この画面をもう一度見てみましょう。今回はFederationを行う際に、Authorize呼び出しに新しい属性を追加します:IDP_identifierです。そこに何らかのトークンを渡します。具体的な内容はすぐに見ていきます。これによってCognitoはProviderを見つけることができます。渡されたトークンに基づいて検索を行います。この例ではAzure ADを使用しており、おそらくSAMLを使用することになります。
このようにProviderを動的に選択し、そのProviderのプロトコルに基づいて動的に認証を行います。そしてトークンが返ってきて、めでたしめでたしです。このQRコードはドキュメントへのリンクになっています。そこには他のパラメータについても説明があります。先ほどIDP identifierについて触れましたが、上の画像はFederated Identity Providerのスクリーンショットです。User Pool内でProviderを作成する際、そのProvider内にIdentifiersというフィールドがあります。文字列を設定し、その文字列をAuthorize呼び出し時に渡すと、Cognitoが自動的にそれを選択してくれます。これは便利な機能です。あるいは、Providerの名前を渡すこともできます。先ほどの例でOkta OIDCやOkta SAMLという名前のProviderがありましたが、ここではSaaSCompany-SAMLという名前になっています。identity_providerとして名前を渡せば、CognitoはそのProviderを選択します。どちらか一方を渡せばよく、両方を渡す必要はありません。
おまけの情報として、両方のパラメータを渡す必要はありません。login_hintという別のパラメータがあり、そこにメールアドレスを指定すると、User Pool認証の場合、そのユーザーをUser Poolまたはログイン名に自動入力します。これはOIDCやGoogle認証の場合も同様に機能します。SAMLやその他のSocial Providersを使用している場合は、少し複雑で単純ではないため、ドキュメントを確認する必要があります。
Federationについて、SaaS提供者がCognitoトリガーを使用する際に直面する可能性のある課題について考えてみましょう。私たちが気づいたことの1つは、100万人のユーザーを持つIdP SaaSがあり、そのユーザーがFederationを通じてアクセスしようとした場合、それを制限する仕組みがないということです。Cognitoは制限なく、すべてのユーザーをUser Poolにマッピングしてしまいます。しかし、SaaS提供者としては、エンタイトルメントや利用階層で制御したい場合があります。これはトリガーで処理できる課題の一つです。
このスライドは以前も見ましたが、ユーザーを作成する代わりにFederationを行います。ここでPre-authentication triggerを呼び出し、必要に応じてオプションを提供します。このテナントのエンタイトルメントをチェックして、ユーザー数が100未満か、あるいは何らかの閾値を超えていないかを確認できます。そのLambda関数内のビジネスロジックをパスすれば、トークンの発行に進みます。また、エンタイトルメントを超過している場合やサポートへの連絡が必要な場合は、アクセスを拒否することもできます。重要なのはエンタイトルメントの処理だけではありません。Cognitoとこれらのトリガーを使用すれば、SaaS提供者として直面するどのようなシナリオでも対応できる強力なツールだということです。
Cognitoでのフェデレーションに関する考慮事項をいくつか挙げます:私自身、CognitoをOAuth 2.0とOIDCの観点から理解したとき、多くのことが明確になりました。ドキュメントには改善の余地がありますが、同様の課題に直面している場合は、OAuth 2.0とOIDCの視点から考えてみることをお勧めします。また、リソースクォータとレート制限の両方が適用されるため、アーキテクチャの設計時にはこれらを考慮する必要があります。ドキュメントには、リージョンごとのUser Pool数やUser Poolあたりのアプリクライアント数の制限など、これらのクォータへの直接のリンクが記載されています。
Federationの価格は若干高くなります。最後に確認した時点では(これは変更される可能性があります)、非フェデレーションユーザーの場合は月間アクティブユーザーあたり約0.5セント、フェデレーションユーザーの場合は約1.5セントでした。それでも、ドル単位ではなくセント単位の価格であり、Cognitoは他の多くの選択肢と比べてコスト効率が良いと言えます。また、User Poolsがこの体験の中心となります。Identity Poolsは関係ありません。User Poolsはユーザー登録とライフサイクル管理に関するもので、Identity Poolsは S3アクセスなどのための短期的な認証情報に焦点を当てています。
結論とフィードバックの依頼
結論に近づいてきました。Federationにはより多くの動く部分があることは明らかですが、これまで避けてきた方も、今一度検討してみる価値があります。先ほど見たように、CognitoとLambdaを使えば十分に管理可能で自動化できます。CognitoはFederationのハブとして機能し、カスタマイズのためのトリガーは非常に役立ちます。これらの機能をLambdaと組み合わせることで、大きな可能性が広がります。マッピングを使ってユーザーとその信頼できるソースとの違いを調整する方法を見てきましたし、面倒な画面を回避するために、Federated IdPを自動的に選択することもできます。最後に、Federationを使用するかどうかに関わらず、オンボーディングプロセスをできるだけスムーズにすることが重要です。これにより、ユーザーが素早く価値を得られるようになります。
アンケートにご協力いただければ幸いです。これは来年の講演内容を決める上で重要な情報となります。特に気に入った点や気に入らなかった点、あるいは今後見たい内容がありましたら、アンケートにご記入ください。私たちは来年のセッションを計画する際に、このフィードバックを慎重に検討しますので、非常に貴重な情報となります。
※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。













































































































Discussion