Amazon Cognito ユーザープールに対するセキュリティのベストプラクティス - Amazon Cognito

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Amazon Cognito ユーザープールに対するセキュリティのベストプラクティス

このページでは、一般的な脅威から保護する場合に実装できるセキュリティのベストプラクティスについて説明します。選択する設定は、各アプリケーションのユースケースによって異なります。管理オペレーションには、少なくとも最小特権を適用し、アプリケーションとユーザーのシークレットを保護する対策を講じることをお勧めします。もう 1 つの高度で効果的なステップは、 AWS WAF ウェブ ACLs を設定してユーザープールに適用することです。

ネットワークレベルでユーザープールを保護する

AWS WAF ウェブ ACLs は、Amazon Cognito で構築する認証メカニズムのパフォーマンスとコストを保護できます。ウェブ ACL を使用すると、API およびマネージドログインのリクエストの前にガードレールを実装できます。ウェブ ACL は、ネットワーク層とアプリケーション層のフィルターを作成し、独自に作成したルールに基づいてトラフィックをドロップしたり、CAPTCHA を要求したりできます。リクエストは、ウェブ ACL ルールの条件を満たすまで Amazon Cognito リソースに渡されません。詳細については、「AWS WAF ウェブ ACL」を参照してください。

SMS メッセージの不正使用から保護する

ユーザープールでパブリックサインアップを許可すると、Amazon Cognito が SMS テキストメッセージで送信するコードを使用して、アカウント検証を設定できます。SMS メッセージは、不要なアクティビティに関連付けられ、 AWS 請求額を増やすことができます。不正を伴うような SMS メッセージの送信に対して耐障害性のあるインフラストラクチャを設定してください。詳細については、 AWS ブログの以下の投稿を参照してください。

パブリック認証を理解する

Amazon Cognito ユーザープールには、カスタマーアイデンティティおよびアクセス管理 (CIAM) 機能があり、一般のユーザーがユーザーアカウントにサインアップしてアプリケーションにアクセスできるユースケースをサポートしています。ユーザープールでセルフサービスのサインアップを許可すると、パブリックインターネットからのユーザーアカウントへのリクエストが受け付けられます。セルフサービスリクエストは、SignUpInitiateAuth などの API オペレーションからと、マネージドログインを使用したユーザーインタラクションから送信されます。パブリックリクエストに伴う不正使用を軽減するか、パブリック認証オペレーションを完全に無効化するようにユーザープールを設定できます。

以下の設定は、ユーザープールとアプリケーションクライアントでパブリック認証リクエストと内部認証リクエストを管理する方法の例をいくつか示しています。

ユーザープールへのパブリックアクセスに影響するユーザープール設定の例
設定 利用可能なオプション 設定場所 パブリック認証への影響 コンソール設定 API オペレーションとパラメータ
セルフサービスのサインアップ アカウントへのサインアップや、管理者としてのユーザーアカウントの作成をユーザーに許可する ユーザープール パブリックサインアップを防止する [サインアップ][セルフサービスのサインアップ]

CreateUserPoolUpdateUserPool

AdminCreateUserConfigAllowAdminCreateUserOnly

管理者による確認 確認コードを新規ユーザーに送信するか、管理者に確認を求める ユーザープール 管理者のアクションなしでのサインアップの確認を防止する [サインアップ][Cognito アシスト型の検証および確認]

CreateUserPoolUpdateUserPool

AccountRecoverySettingsadmin_only

ユーザー開示 サインイン時およびパスワードリセット時に「ユーザーが見つかりません」というメッセージを送信するか、開示を防止する アプリケーションクライアント サインイン名、E メールアドレス、または電話番号の推測を防ぐ [アプリケーションクライアント][ユーザー存在エラーを防ぐ]

CreateUserPoolClientUpdateUserPoolClient

PreventUserExistenceErrors

クライアントシークレット サインアップ時、サインイン時、パスワードリセット時にシークレットハッシュを要求するかどうかを指定する アプリケーションクライアント 不正なソースからの認証リクエストを防ぐ [アプリケーションクライアント][クライアントシークレット]

CreateUserPoolClient

GenerateSecret

ウェブ ACL 認証リクエストのネットワークファイアウォールを有効化するかどうかを指定する ユーザープール 管理者が定義したリクエスト特性と IP アドレスルールに基づいてアクセスを制限または禁止する [AWS WAF] - [WAF 設定]

AssociateWebACL

ResourceArn

外部 IdP サードパーティ IdP、ユーザープールディレクトリ、または両方のユーザーによるサインインを許可する アプリケーションクライアント サインアップとサインインからローカルユーザーまたはフェデレーションユーザーを除外する [アプリケーションクライアント][ID プロバイダー]

CreateUserPoolClientUpdateUserPoolClient

SupportedIdentityProviders

認可サーバー 認証用のパブリックウェブページをホストするかどうかを指定する ユーザープール パブリックウェブページをオフにし、SDK ベースの認証のみを許可する [ドメイン]

CreateUserPoolDomain

任意のユーザープールドメインを作成すると、パブリックウェブページが使用可能になります。

脅威保護 悪意のあるアクティビティや安全でないパスワードの兆候に関するモニタリングを有効または無効にする ユーザープールまたはアプリケーションクライアント ユーザーが侵害の兆候を示した場合、自動的にサインインをブロックするか、MFA を要求することができる [脅威保護][保護設定]

SetRiskConfiguration

SetRiskConfiguration のパラメータは、脅威保護の設定を定義します。

秘密クライアントをクライアントシークレットで保護する

クライアントシークレットは、アプリケーションクライアントに関連付けられたオプションの文字列です。クライアントシークレットを持つアプリケーションクライアントへのすべての認証リクエストには、ユーザー名、クライアント ID、およびクライアントシークレットから生成されたシークレットハッシュを含める必要があります。クライアントシークレットを知らないユーザーは、最初からアプリケーションからシャットアウトされます。

ただし、クライアントシークレットには制限があります。クライアントシークレットをパブリッククライアントソフトウェアに埋め込むと、クライアントシークレットは閲覧可能になります。これにより、ユーザーの作成、パスワードリセットリクエストの送信、アプリケーションクライアントでの他のオペレーションの実行が可能になります。クライアントシークレットは、シークレットにアクセスできる唯一のエンティティがアプリケーションである場合にのみ実装する必要があります。通常、これが可能なのは、サーバー側の秘密クライアントアプリケーションです。これは、クライアントシークレットが必須である M2M アプリケーションにも当てはまります。暗号化されたローカルストレージまたは にクライアントシークレットを保存します AWS Secrets Manager。クライアントシークレットをパブリックインターネットに公開することは絶対に避けてください。

その他のシークレットを保護する

Amazon Cognito ユーザープールの認証システムでは、個人データ、パスワード、 AWS 認証情報を扱う場合があります。アプリケーションでアクセスする可能性があるシークレットを扱うためのベストプラクティスを以下に示します。

パスワード

ユーザーは、アプリケーションへのサインイン時にパスワードを入力する場合があります。Amazon Cognito には、更新トークンがあり、これをアプリケーションで使用することで、期限切れのユーザーセッションを新しいパスワードの入力を求めることなく継続できます。パスワードやパスワードハッシュは、ローカルストレージに保存しないようにします。パスワードを不透明なものとして扱い、ユーザープールにのみ渡すようにアプリケーションを設計します。

ベストプラクティスとしては、WebAuthn パスキーを使用してパスワードなしの認証を実装します。パスワードを実装する必要がある場合は、セキュアリモートパスワード (SRP) 認証フロー多要素認証 (MFA) を使用します。

AWS 認証情報

管理認証とユーザープール管理オペレーションには、 AWS 認証情報を使用した認証が必要です。これらのオペレーションをアプリケーションに実装するには、一時的な AWS 認証情報への安全なアクセスを許可します。認証情報へのアクセスは、管理するサーバーコンポーネントで実行するアプリケーションにのみ許可します。 AWS 認証情報を持つアプリケーションを GitHub などのパブリックバージョン管理システムに配置しないでください。パブリッククライアント側のアプリケーションで AWS 認証情報をエンコードしないでください。

PKCE コード検証子

Proof Key for Code Exchange (PKCE) は、ユーザープール認可サーバーでの OpenID Connect (OIDC) 認証コード付与に使用します。アプリケーションは、認証コードをリクエストするときに、コード検証シークレットをユーザープールと共有します。認証コードをトークンと交換するには、クライアントがコード検証子を認識していることを再確認する必要があります。これにより、傍受された認証コードでトークンが発行されないようにします。

クライアントは、認可リクエストごとに新しいランダムなコード検証子を生成する必要があります。静的または予測可能なコード検証子を使用すると、攻撃者はハードコードされた検証子と認証コードを傍受するだけで済みます。コード検証子の値がユーザーに公開されないようにアプリケーションを設計します。

ユーザープール管理の最小特権

IAM ポリシーは、Amazon Cognito ユーザープールの管理および管理認証オペレーションに対してプリンシパルが持つアクセスレベルを定義できます。例えば、次のようになります。

  • ウェブサーバーに対しては、管理 API オペレーションによる認証のためのアクセス許可を付与します。

  • でユーザープールを管理する AWS IAM Identity Center ユーザーに AWS アカウント、ユーザープールのメンテナンスとレポートのためのアクセス許可を付与します。

Amazon Cognito でのリソースの詳細度は、IAM ポリシーの目的においては、ユーザープールとアイデンティティプールの 2 つのリソースタイプに制限されています。個々のアプリケーションクライアントを管理するためのアクセス許可は適用できないことに注意してください。付与したアクセス許可はすべてのアプリケーションクライアントに有効であることを念頭にユーザープールを設定してください。組織に複数のアプリケーションテナントがあり、セキュリティモデルでテナント間の管理責任を分離する必要がある場合は、ユーザープールごとのテナントを 1 つとするマルチテナンシーを実装します。

ユーザー認証オペレーション (InitiateAuth など) のためのアクセス許可を持つ IAM ポリシーを作成することはできますが、これらのアクセス許可は効果がありません。パブリック API オペレーションとトークンで認可された API オペレーションは、IAM アクセス許可の対象ではありません。使用可能なユーザープール認証オペレーションのうち、アクセス許可を付与できるのは、管理サーバー側のオペレーション (AdminInitiateAuth など) に対してのみです。

最小特権 Action リストを使用して、ユーザープールの管理レベルを制限できます。次のポリシー例で対象としている管理者は、IdP、リソースサーバー、アプリケーションクライアント、ユーザープールドメインは管理できますが、ユーザーやユーザープールは管理できません。

JSON
{ "Version":"2012-10-17", "Statement": [ { "Sid": "UserPoolClientAdministrator", "Action": [ "cognito-idp:CreateIdentityProvider", "cognito-idp:CreateManagedLoginBranding", "cognito-idp:CreateResourceServer", "cognito-idp:CreateUserPoolDomain", "cognito-idp:DeleteIdentityProvider", "cognito-idp:DeleteResourceServer", "cognito-idp:DeleteUserPoolDomain", "cognito-idp:DescribeIdentityProvider", "cognito-idp:DescribeManagedLoginBranding", "cognito-idp:DescribeManagedLoginBrandingByClient", "cognito-idp:DescribeResourceServer", "cognito-idp:DescribeUserPool", "cognito-idp:DescribeUserPoolClient", "cognito-idp:DescribeUserPoolDomain", "cognito-idp:GetIdentityProviderByIdentifier", "cognito-idp:GetUICustomization", "cognito-idp:ListIdentityProviders", "cognito-idp:ListResourceServers", "cognito-idp:ListUserPoolClients", "cognito-idp:ListUserPools", "cognito-idp:SetUICustomization", "cognito-idp:UpdateIdentityProvider", "cognito-idp:UpdateManagedLoginBranding", "cognito-idp:UpdateResourceServer", "cognito-idp:UpdateUserPoolClient", "cognito-idp:UpdateUserPoolDomain" ], "Effect": "Allow", "Resource": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_EXAMPLE" } ] }

次のポリシー例では、サーバー側のアプリケーションに対して、ユーザーやグループの管理と認証を許可します。

JSON
{ "Version":"2012-10-17", "Statement": [ { "Sid": "UserAdminAuthN", "Action": [ "cognito-idp:AdminAddUserToGroup", "cognito-idp:AdminConfirmSignUp", "cognito-idp:AdminCreateUser", "cognito-idp:AdminDeleteUser", "cognito-idp:AdminDeleteUserAttributes", "cognito-idp:AdminDisableProviderForUser", "cognito-idp:AdminDisableUser", "cognito-idp:AdminEnableUser", "cognito-idp:AdminForgetDevice", "cognito-idp:AdminGetDevice", "cognito-idp:AdminGetUser", "cognito-idp:AdminInitiateAuth", "cognito-idp:AdminLinkProviderForUser", "cognito-idp:AdminListDevices", "cognito-idp:AdminListGroupsForUser", "cognito-idp:AdminListUserAuthEvents", "cognito-idp:AdminRemoveUserFromGroup", "cognito-idp:AdminResetUserPassword", "cognito-idp:AdminRespondToAuthChallenge", "cognito-idp:AdminSetUserMFAPreference", "cognito-idp:AdminSetUserPassword", "cognito-idp:AdminSetUserSettings", "cognito-idp:AdminUpdateAuthEventFeedback", "cognito-idp:AdminUpdateDeviceStatus", "cognito-idp:AdminUpdateUserAttributes", "cognito-idp:AdminUserGlobalSignOut", "cognito-idp:AssociateSoftwareToken", "cognito-idp:ListGroups", "cognito-idp:ListUsers", "cognito-idp:ListUsersInGroup", "cognito-idp:RevokeToken", "cognito-idp:UpdateGroup", "cognito-idp:VerifySoftwareToken" ], "Effect": "Allow", "Resource": "arn:aws:cognito-idp:us-west-2:123456789012:userpool/us-west-2_EXAMPLE" } ] }

トークンの保護と検証

トークンには、エンドユーザーに開示したくないグループメンバーシップやユーザー属性への内部参照が含まれている場合があります。ID トークンとアクセストークンは、ローカルストレージに保存しないでください。更新トークンは、ユーザープールのみがアクセスできるキーで暗号化され、ユーザーやアプリケーションからは不透明になります。ユーザーがサインアウトした場合や、セキュリティ上の理由でユーザーのセッションの保持が望ましくないと判断した場合は、更新トークンの取り消しを行います。

アクセストークンを使用すると、トークンが有効で期限切れでないことを独立して検証するシステムにのみ、アクセスを許可できます。検証リソースについては、「JSON ウェブトークンの検証」を参照してください。

信頼する ID プロバイダーを決定する

SAML または OIDC ID プロバイダー (IdP) を使用してユーザープールを設定すると、IdP は新しいユーザーを作成して、ユーザー属性を設定し、アプリケーションリソースにアクセスできます。SAML プロバイダーと OIDC プロバイダーは通常、企業間取引 (B2B) やエンタープライズのシナリオで使用され、お客様やお客様の直接の顧客がプロバイダーのメンバーシップと設定を管理します。

ソーシャルプロバイダーは、インターネット上の誰にでもユーザーアカウントを提供するため、エンタープライズプロバイダーと比べてお客様による管理が行き届きません。アプリケーションクライアントでソーシャル IdP を有効にするのは、一般ユーザーによるアプリケーションへのサインインとリソースへのアクセスを許可する準備が整った場合のみとします。

ユーザープロファイルへのアクセスに対するスコープの影響を理解する

ユーザープール認可サーバーへの認証リクエストで、アクセスコントロールのスコープをリクエストできます。これらのスコープは、外部リソースへのアクセスをユーザーに許可し、ユーザーが自身のユーザープロファイルを表示および変更するためのアクセスを許可できます。アプリケーションのオペレーションに必要な最小限のスコープをサポートするように、アプリケーションクライアントを設定します。

aws.cognito.signin.user.admin スコープは、InitiateAuth などのオペレーションで SDK 認証が発行するすべてのアクセストークンに存在します。スコープは、アプリケーションでのユーザープロファイルのセルフサービスオペレーション用に指定されています。このスコープは、認可サーバーに対してリクエストすることもできます。スコープは、UpdateUserAttributesGetUser など、トークンで認可されたオペレーションに必須です。これらのオペレーションの影響は、アプリケーションクライアントの読み取りおよび書き込みアクセス許可によって制限されます。

openidprofileemailphone の各スコープは、ユーザープール認可サーバーの userInfo エンドポイントへのリクエストを承認します。各スコープは、エンドポイントが返すことができる属性を定義します。openid スコープは、他のスコープを追加せずにリクエストすると、使用可能なすべての属性を返します。他のスコープを追加してリクエストすると、レスポンスは追加のスコープが示す属性に絞り込まれます。openid スコープは ID トークンのリクエストも示します。このスコープを認可エンドポイントへのリクエストから省略すると、Amazon Cognito はアクセストークンと、該当する場合は更新トークンのみを発行します。詳細については、「アプリクライアントの用語」の「OpenID Connect のスコープ」を参照してください。

ユーザー属性の入力をサニタイズする

配信方法やユーザー名となる可能性があるユーザー属性 (email など) には、形式制限があります。その他の属性には、文字列、ブール値、または数値データ型を含めることができます。文字列属性値は、さまざまな入力をサポートします。ユーザーディレクトリや、Amazon Cognito からユーザーに配信するメッセージに不要なデータを書き込む試みを防ぐようにアプリケーションを設定します。ユーザーが送信した文字列属性値は、アプリケーションにおいてクライアント側で検証してから Amazon Cognito に送信します。

ユーザープールは、指定した属性マッピングに基づいて、IdP からユーザープールに属性をマッピングします。安全で予測可能な IdP 属性のみをユーザープールの文字列属性にマッピングします。