📝

ウェブ ID フェデレーションとは

に公開
1

ウェブ ID フェデレーションの使用 - Amazon DynamoDB

多数のユーザーを対象とするアプリケーションを記述している場合、必要に応じて、ウェブ ID フェデレーションを使用して、認証と認可を実行できます。ウェブ ID フェデレーションは、個々の ユーザーを作成する必要性を排除します。代わりに、ユーザーは ID プロバイダーにサインインした後、一時的なセキュリティ資格情報を AWS Security Token Service (AWS STS) から取得できます。アプリケーションでは、この認証情報を使用して AWS サービスにアクセスできます。

IAM ユーザーを作成せずに一時的な認証情報で AWS にアクセスする方法です。

ID プロバイダーとフェデレーション

ID プロバイダーとフェデレーション - AWS Identity and Access Management

ベストプラクティスとして、AWS アカウント内に個別に IAM ユーザーを作成するのではなく、ID プロバイダーとのフェデレーションを使用して AWS リソースにアクセスするように人間のユーザーに求めることをお勧めします。ID プロバイダー (IdP) を使用すると、AWS の外部のユーザー ID を管理して、これらの外部ユーザー ID にアカウント内の AWS リソースに対するアクセス許可を与えることができます。これは、会社に既に企業ユーザーディレクトリなどの独自の ID システムがある場合に便利です。また、AWS リソースへのアクセスが必要なモバイルアプリやウェブアプリケーションを作成する場合にも便利です。

  • IAM ユーザーを作成しない方が安全
  • ID プロバイダーと連携して AWS にアクセスする方法が推奨されている
  • AWS 以外のユーザーに AWS へのアクセス許可を付与できる

ID プロバイダー

IdP | Identity Provider | アイディーピー – サポート − GMOトラスト・ログイン

IdPとは、Identity Provider (アイデンティティ プロバイダー) の略称である。大文字で「IDP」と表記される場合もある。

通常は、各種クラウドサービスがそれぞれ行う認証(例: ユーザーがID・パスワードを入力してログイン)を、クラウドサービスに代わって行い、認証情報をクラウドサービス側に提供する役割を果たす。

  • ユーザー情報を管理するサービスのひとつ
  • Amazon, Facebook, Google など多数存在する
  • ユーザーは ID プロバイダー側でログインし、ID プロバイダーは認証情報をクラウドサービスやアプリケーションなどに提供する

アプリケーションなどでも「Google でログイン」などを利用する機会があると思いますが、Google にログインすることでアプリケーションを利用できる仕組みも ID プロバイダーの仕組みのようです。

イメージとしては以下のドキュメントに記載されている図の通りです。
一般的なシナリオ - AWS Identity and Access Management

フェデレーション

フェデレーションとは - IT用語辞典 e-Words

  • 英語では連合、連盟などの意味を持つ単語
  • ログインなどの認証の文脈で使用されることが多い
  • ID プロバイダーなどの認証情報提供元と、AWS などの認証情報提供先での「連携」のような意味合い

AWS におけるフェデレーション方法

一般的なシナリオ - AWS Identity and Access Management

外部 ID プロバイダー (IdP) を使用して、AWS と外部 IdP 外のユーザー ID を管理できます。外部 IdP は、OpenID Connect (OIDC) または Security Assertion Markup Language (SAML) のいずれかを使用して ID 情報を AWS に提供できます。

  • AWS では OIDC と SAML というフェデレーション方法を利用できる
  • OIDC や SAML は認証プロトコルの種類
  • OIDC では JSON ベースの Web トークンである JWT を使用する
    • 認証プロトコルとしては SAML よりも新しい
  • SAML では XML を使用する

OIDC と SAML については本記事の本題から逸れるため詳細は割愛します。

AWS におけるウェブ ID フェデレーションとは

ウェブ ID フェデレーションの使用 - Amazon DynamoDB
ここまでの調査内容を踏まえて上記のドキュメントを平易に解釈してみました。

多数のユーザーを対象とするアプリケーションを記述している場合、必要に応じて、ウェブ ID フェデレーションを使用して、認証と認可を実行できます。

AWS の IAM などにはウェブ ID フェデレーションという仕組みがあります。
Amazon や Google にログインすることで AWS にもアクセスできる仕組みです。

ウェブ ID フェデレーションは、個々の ユーザーを作成する必要性を排除します。代わりに、ユーザーは ID プロバイダーにサインインした後、一時的なセキュリティ資格情報を AWS Security Token Service (AWS STS) から取得できます。

ユーザーは AWS にログインする代わりに Amazon などにログインします。
Amazon などはログインした情報を AWS に提供する役割を持っています。
ユーザー情報は Amazon などの IP プロバイダーが管理しているので AWS 側で IAM ユーザーを作成する必要がなく安全です。

アプリケーションでは、この認証情報を使用して AWS サービスにアクセスできます。

Amazon などの ID プロバイダーから提供されたユーザー情報に IAM ロールを紐づけて一時的なアクセス権をユーザーに付与します。
大規模な Web アプリケーション向けに大量の IAM ユーザーを作成する方法は非現実的な一方で、フェデレーションを使用すれば IAM ユーザーを作成する必要がないので、大規模な Web アプリケーションにも対応可能です。

試してみた

Google ログイン後に AWS の IAM ロールを使用していることを確認する方法で試してみました。

01. Google Cloud の設定

Google Cloud 側で認証情報を設定するため、まずは以下の URL にアクセスします。
https://console.cloud.google.com/

プロジェクトがない場合には新規にプロジェクトを作成してください。
私の環境では My First Project というプロジェクトを作成済みなのでこのプロジェクトを使用します。

画面左側のナビゲーションメニューから API とサービス > 認証情報をクリックします。

画面上部に以下のメッセージが表示されている場合、「同意画面を構成」をクリックしてください。

必ず、アプリケーションに関する情報を使用して OAuth 同意画面を構成してください。

プロジェクトを構成ページが表示された場合には以下のように入力します。

  • アプリ名: Web Identity Test
  • ユーザーサポートメール: 自分のメールアドレス
  • 対象: 外部
  • 連絡先情報: 自分のメールアドレス

OAuth の概要ページで「OAuth クライアントを作成」をクリックします。

以下の設定で OAuth クライアント ID を作成します。

  • アプリケーションの種類: ウェブアプリケーション
  • 名前: ウェブクライアント 1
  • 承認済みの JavaScript 生成元: http://localhost:8000
    • 後ほど置換します
  • 承認済みのリダイレクト URI: http://localhost:8000
    • 後ほど置換します

クライアント作成後に OAuth クライアントの情報が記載された JSON ファイルをダウンロードしてください。

02. AWS IAM で ID プロバイダーを作成

AWS の IAM コンソールから「ID プロバイダ」をクリックします。

「プロバイダを追加」をクリックします。

以下の設定で ID プロバイダーを作成します。

  • プロバイダのタイプ: OpenID Connect
  • プロバイダの URL: https://accounts.google.com
  • 対象者: 手順 01 でダウンロードした JSON ファイル内の client_id の値

03. IAM ロールの作成

IAM コンソールから「ロール」をクリックします。

「ロールを作成」をクリックします。

以下の設定でロールを作成します。

  • 信頼されたエンティティタイプ: ウェブアイデンティティ
  • アイデンティティプロバイダー: Google
  • Audience: 手順 01 でダウンロードした JSON ファイル内の client_id の値
  • 許可ポリシー: AdministratorAccess
  • ロール名: WebIdentityTestRole



04. html ファイルの作成

index.html というファイル名で以下のコードでファイルを作成します。
以下の点は置換してください。

  • YOUR_GOOGLE_CLIENT_ID: 手順 01 でダウンロードした JSON ファイル内の client_id の値
  • YOUR_ROLE_ARN: 手順 03 で作成した IAM ロールの ARN に置換
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ウェブIDフェデレーション テスト</title>
    <script src="https://accounts.google.com/gsi/client" async defer></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.1000.0.min.js"></script>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
        .section { margin: 20px 0; padding: 20px; border: 1px solid #ddd; border-radius: 5px; }
        button { padding: 10px 20px; margin: 10px 0; cursor: pointer; }
        .result { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 3px; }
    </style>
</head>
<body>
    <h1>ウェブIDフェデレーション デモ</h1>
    
    <div class="section">
        <h2>ステップ1: Googleでログイン</h2>
        <div id="g_id_onload" data-client_id="YOUR_GOOGLE_CLIENT_ID" data-callback="handleCredentialResponse"></div>
        <div class="g_id_signin" data-type="standard"></div>
        <div id="login-status" class="result">ログインしていません</div>
    </div>

    <div class="section">
        <h2>ステップ2: AWSの一時認証情報を取得</h2>
        <button id="get-credentials" disabled>AWS認証情報を取得</button>
        <div id="credentials-status" class="result">まだ取得していません</div>
    </div>

    <div class="section">
        <h2>ステップ3: GetCallerIdentity を実行</h2>
        <button id="get-identity" disabled>自分のIDを確認</button>
        <div id="identity-result" class="result">まだ取得していません</div>
    </div>

    <script>
        const CONFIG = {
            googleClientId: 'YOUR_GOOGLE_CLIENT_ID',
            awsRegion: 'ap-northeast-1',
            roleArn: 'YOUR_ROLE_ARN'
        };

        let googleIdToken = null;
        let awsCredentials = null;

        function handleCredentialResponse(response) {
            googleIdToken = response.credential;
            document.getElementById('login-status').innerHTML = 'Googleログイン成功!<br>IDトークンを取得しました';
            document.getElementById('get-credentials').disabled = false;
        }

        document.getElementById('get-credentials').addEventListener('click', async () => {
            AWS.config.region = CONFIG.awsRegion;
            const sts = new AWS.STS();
            const data = await sts.assumeRoleWithWebIdentity({
                RoleArn: CONFIG.roleArn,
                RoleSessionName: 'WebIdentityTest',
                WebIdentityToken: googleIdToken
            }).promise();
            awsCredentials = data.Credentials;
            document.getElementById('credentials-status').innerHTML = 'AWS一時認証情報を取得しました!<br>アクセスキーID: ' + awsCredentials.AccessKeyId.substring(0, 20) + '...';
            document.getElementById('get-identity').disabled = false;
        });

        document.getElementById('get-identity').addEventListener('click', async () => {
            AWS.config.update({
                accessKeyId: awsCredentials.AccessKeyId,
                secretAccessKey: awsCredentials.SecretAccessKey,
                sessionToken: awsCredentials.SessionToken,
                region: CONFIG.awsRegion
            });
            const data = await new AWS.STS().getCallerIdentity().promise();
            document.getElementById('identity-result').innerHTML = `GetCallerIdentity 成功!<br><br><strong>あなたのAWS ID情報:</strong><br><strong>UserId:</strong> ${data.UserId}<br><strong>Account:</strong> ${data.Account}<br><strong>Arn:</strong> ${data.Arn}<br>`;
        });
    </script>
</body>
</html>

作成した index.html を zip ファイル化します。

05. Amplify アプリの作成

手順 04 で作成した zip ファイルを Amplify にデプロイします。
Amplify コンソールから「アプリケーションをデプロイ」をクリックします。

Git なしでデプロイを選択します。

手順 04 で作成した zip ファイルをアップロードしてデプロイします。

06. Google Cloud の設定変更

手順 01 で設定した URI を置換します。

  • 承認済みの JavaScript 生成元: 手順 05 で作成した Amplify ドメイン
  • 承認済みのリダイレクト URI: 手順 05 で作成した Amplify ドメイン

Amplify ドメインは Amplify アプリのコンソールから確認可能です。

URI 末尾にはスラッシュを除いた Amplify ドメインを記載して保存します。

07. 動作確認

Amplify アプリのドメインにアクセスします。
Google でログインをクリックして、手順 01 で指定したメールアドレスのアカウントで Google にログインします。

Google へのログインが成功すると以下のメッセージが表示されます。

Googleログイン成功!
IDトークンを取得しました

次に「AWS 認証情報を取得」をクリックします。
一時認証情報を取得できれば以下のメッセージが表示されます。

AWS一時認証情報を取得しました!
アクセスキーID: xxx...

最後に「自分の ID を確認」をクリックします。
以下のメッセージが表示されれば成功です。

GetCallerIdentity 成功!

あなたのAWS ID情報:
UserId: xxx:WebIdentityTest
Account: 012345678901
Arn: arn:aws:sts::012345678901:assumed-role/WebIdentityTestRole/WebIdentityTest

GetCallerIdentity は現在使用中の IAM ユーザーやロールの情報を取得する AWS の API です。
GetCallerIdentity - AWS Security Token Service

GetCallerIdentity で取得した情報が手順 03 で作成した IAM ロールの情報であれば AWS へのアクセスが成功しています。
つまり、ログインは Google で行い、Google の認証情報を利用して AWS の一時認証情報を取得できているという状況です。

以上がウェブ ID フェデレーションの挙動紹介です。

まとめ

今回はウェブ ID フェデレーションについて紹介しました。
どなたかの参考になれば幸いです。

参考資料

Discussion

volibearvolibear

とても分かりやすかったです!勉強になりました!