概要
シングルサインオン(SSO)は、1つのIDとパスワードで複数のサービスにログインできる仕組みです。IdP(アイデンティティプロバイダー)にユーザー情報を集約し、各サービスはIdPが発行する認証情報を信頼してアクセスを許可します。これにより、ユーザーはサービスごとにパスワードを管理する必要がなくなり、管理者はIdP上でユーザーを無効化するだけで全サービスへのアクセスを一括で停止できます。
この記事では、オープンソースのIdPであるKeycloakをDockerでローカルに起動し、AWSマネジメントコンソールへのSAML SSOを構築します。今回はAWSとの連携のみを行いますが、同じ要領でKeycloakにSAMLクライアントを追加すれば、他のサービスにも同じIDでログインできるようになります。
複数のAWSアカウントへのSSOを一元管理する場合は、AWS IAM Identity Center(旧AWS SSO)の利用がベストプラクティスです。この記事では、SAML連携の仕組みを理解するためにIAMフェデレーションを使用します。
top-image: この記事全体の概要を掴める図解を挿入

この記事のメリット
- SAML連携の基本構成と認証フローを理解できる
- KeycloakとAWSのSAML SSO環境を実際に構築し、フェデレーションログインの仕組みを体験できる
- IAMアイデンティティプロバイダーとIAMロールの信頼関係の設定方法を理解できる
- SAML属性マッピング(RoleSessionName・Role)の設定を習得できる
技術解説
SAML連携の基本構成
SAML(Security Assertion Markup Language)2.0は、異なるドメイン間で認証情報を安全にやり取りするためのXMLベースの標準規格です。AWSとのSAML連携では、以下の3つの要素が関係します。
| 要素 | 説明 | 具体例 |
|---|---|---|
| アイデンティティプロバイダー(IdP) | ユーザーの認証を行い、SAMLアサーションを発行する | Active Directory Federation Services(AD FS)、Okta、Keycloakなど |
| サービスプロバイダー(SP) | IdPが発行したSAMLアサーションを受け取り、アクセスを許可する | AWS(IAM) |
| メタデータ | IdPとSPの間の信頼関係を定義するXMLドキュメント | 発行者名、有効期限、認証レスポンス検証用のX.509証明書などを含む |
メタデータの有効期限(IAMコンソール上の「Valid until」)は、メタデータドキュメント内のvalidUntil属性またはcacheDuration属性から算出されます。validUntilは絶対的な有効期限(タイムスタンプ)を、cacheDurationはメタデータ取得時点からの相対的なキャッシュ有効期間を表します。どちらの属性も存在しない場合、「Valid until」はX.509証明書の有効期限とは一致しません。なお、この有効期限はメタデータドキュメント自体の期限であり、メタデータに含まれるX.509署名証明書の有効期限とは別のものです。
SAML認証フローの概要
SAML連携によるAWSマネジメントコンソールへのログインは、以下のフローで行われます。
sequenceDiagram
participant Browser as ブラウザ
participant IdP as IdP<br>(Keycloak)
participant AWS as AWS<br>(IAM + STS)
Browser->>IdP: 1. 認証リクエスト(ID/パスワード)
IdP->>IdP: 2. ユーザー認証
IdP->>Browser: 3. SAMLアサーション(署名付き)をHTMLフォームで返却
Browser->>AWS: 4. ブラウザがAWSサインインエンドポイントにSAMLアサーションをPOST
AWS->>AWS: 5. 署名証明書でSAMLアサーションを検証
AWS->>AWS: 6. AssumeRoleWithSAMLで一時認証情報を発行
AWS->>Browser: 7. マネジメントコンソールにリダイレクト
ステップ5の署名検証では、AWSはIAMアイデンティティプロバイダーに登録されているメタデータ内の証明書を使用します。この証明書がIdP側の現在の署名証明書と一致しない場合、検証が失敗し、フェデレーションログインが拒否されます。
なお、AWSではフェデレーションの可用性向上のために、グローバルエンドポイント(https://signin.aws.amazon.com/saml)ではなくリージョナルエンドポイント(https://<region-code>.signin.aws.amazon.com/saml)の使用が推奨されています。
署名証明書の役割
IdPはSAMLアサーションに対してデジタル署名を付与します。この署名に使用されるのがIdPの署名証明書(X.509証明書)です。メタデータドキュメントに含まれるX.509証明書には、以下の要件があります。
- キーサイズが最小1024ビット以上であること
- 証明書の拡張(extension)に重複がないこと(各拡張は1回のみ記載可能)
署名の仕組みは以下の通りです。
- IdP側: 秘密鍵でSAMLアサーションに署名する
- AWS側: メタデータに含まれる公開鍵(証明書)で署名を検証する
この仕組みにより、SAMLアサーションが正規のIdPから発行されたものであり、改ざんされていないことを確認できます。
AWS公式ドキュメントでは、SAML V2.0 Metadata Interoperability Profileの定義に基づき、IAMはSAMLメタデータドキュメント内のX.509証明書の有効期限を自動的に評価・対応しないと明記されています。証明書の有効期限の監視とローテーションは、組織のガバナンスおよびセキュリティポリシーに従って実施する必要があります。
SAML暗号化(補足)
AWS IAMでは、SAMLアサーションの署名検証に加えて、SAMLアサーション自体の暗号化にも対応しています。暗号化を有効にする場合は、IAMアイデンティティプロバイダーに.pem形式の秘密鍵ファイルをアップロードします。暗号化キーのローテーションでは、プロバイダーごとに最大2つの秘密鍵ファイルを保存でき、IAMは追加日が新しいキーから順に復号を試みます。これは署名証明書の更新とは独立した仕組みであり、暗号化の秘密鍵はAWS側で管理するものです。
この記事ではSAML暗号化の詳細については割愛します。なお、IAM Identity CenterおよびAmazon CognitoはIAM SAMLアイデンティティプロバイダーからの暗号化SAMLアサーションに対応していません。
SAML属性マッピング
AWSのSAMLフェデレーションでは、SAMLアサーションに以下の属性を含める必要があります。
| 属性名 | 説明 | 設定値の例 |
|---|---|---|
https://aws.amazon.com/SAML/Attributes/RoleSessionName | AWSコンソールに表示されるセッション名 | ユーザー名 |
https://aws.amazon.com/SAML/Attributes/Role | 引き受けるIAMロールとプロバイダーのARNペア | arn:aws:iam::ACCOUNT_ID:role/KeycloakSSORole,arn:aws:iam::ACCOUNT_ID:saml-provider/Keycloak |
https://aws.amazon.com/SAML/Attributes/SessionDuration(任意) | セッションの有効期間(秒) | 3600 |
Role属性は「ロールARN,プロバイダーARN」の形式でカンマ区切りで指定します。
IAMロールの信頼ポリシー
SAML フェデレーション用のIAMロールには、以下の信頼ポリシーを設定します。IAMロールの信頼ポリシーで参照するSAMLプロバイダーは、そのロールと同じAWSアカウントに存在する必要があります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:saml-provider/Keycloak"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
}
Principal.Federated: IAMアイデンティティプロバイダーのARNAction:sts:AssumeRoleWithSAMLで、SAMLアサーションによるロール引き受けを許可Condition:SAML:aud(オーディエンス)がAWSサインインエンドポイントであることを条件に指定
実践
ここでは、KeycloakをDockerで起動してAWSとのSAML SSO環境を構築し、SSOログインが正常に動作することを確認します。
前提条件
- AWSアカウントを所有していること
- Dockerがインストール済みであること
作成するリソース一覧
| リソース種別 | リソース名 | 作成場所 | 用途 |
|---|---|---|---|
| Keycloakサーバー | ローカル(Docker) | ローカル環境 | IdP |
| SAMLクライアント | urn:amazon:webservices | Keycloak(masterレルム) | AWS向けSAML連携設定 |
| クライアントロール | IAMロールARN,プロバイダーARN | Keycloak | AWSロールとの対応付け |
| ユーザー | testuser | Keycloak | SSO検証用ユーザー |
| IAMアイデンティティプロバイダー | Keycloak | AWS(IAM) | SAMLプロバイダー登録 |
| IAMロール | KeycloakSSORole | AWS(IAM) | SSOログイン用ロール |
IAMアイデンティティプロバイダーとIAMロールはグローバルリソースのため、リージョンに依存しません。
手順1: KeycloakをDockerで起動する
以下のコマンドでKeycloakを開発モードで起動します。
docker run -d -p 8080:8080 \
-e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
-e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
--name keycloak \
quay.io/keycloak/keycloak:latest \
start-dev
起動後、ブラウザで http://localhost:8080 にアクセスし、Keycloakのトップページが表示されることを確認します。ユーザー名 admin、パスワード admin でログインします。

手順2: AWSのSAMLメタデータを取得する
AWSが公開しているSAMLメタデータをダウンロードします。このメタデータをKeycloakにインポートすることで、SAMLクライアントの設定が自動的に行われます。
curl -o saml-metadata.xml https://signin.aws.amazon.com/static/saml-metadata.xml

手順3: SAMLクライアントを作成する
AWSのメタデータをインポートしてSAMLクライアントを作成します。
- 左側ナビゲーションの「Clients」を選択し、「Import client」をクリックします。
- 「Browse…」をクリックし、手順2でダウンロードした
saml-metadata.xmlを選択します。 - Client IDに
urn:amazon:webservicesが自動的に入力されていることを確認します。 - 「Save」をクリックします。

手順4: SAMLクライアントの追加設定
作成されたクライアントの「Settings」タブで、以下の追加設定を行います。
- IDP-Initiated SSO URL name:
aws-saml
この値は任意の文字列ですが、SSOログイン時のURLの一部になります。
- 「Save」をクリックします。

手順5: デフォルトMapperを削除して再作成する
Mapper(マッパー)とは、Keycloak内部のユーザー情報(ユーザー名やロールなど)をSAMLレスポンスのどの属性にどのような形式で出力するかを定義する変換ルールです。
メタデータインポート時にデフォルトで作成されるMapperは、AWSが期待する属性名や形式と一致しないため、削除して再作成する必要があります。特にRole listMapperはデフォルトでロールごとに個別のSAML属性要素を生成しますが、AWSはすべてのロールを1つの属性要素にまとめた形式を期待します。
- クライアント画面の「Client scopes」タブを選択します。
urn:amazon:webservices-dedicatedをクリックします。- 一覧に表示されているMapper(
RoleSessionName、Roleなど)をすべて削除します。

以下の2つのMapperを新規作成します。
Mapper 1: Session Name(RoleSessionName)
- 「Configure a new mapper」→「User Property」を選択します。
- 以下を設定します。
- Name:
Session Name - Property:
username - SAML Attribute Name:
https://aws.amazon.com/SAML/Attributes/RoleSessionName - SAML Attribute NameFormat:
Basic
- Name:
- 「Save」をクリックします。

Mapper 2: Session Role(Role)
- 「Add mapper」→「By configuration」→「Role list」を選択します。
- 以下を設定します。
- Name:
Session Role - Role attribute name:
https://aws.amazon.com/SAML/Attributes/Role - SAML Attribute NameFormat:
Basic - Single Role Attribute:
ON
- Name:
- 「Save」をクリックします。

「Single Role Attribute」は必ず
ONにしてください。OFFの場合、ロールごとに別のSAML属性が生成され、AWSがパースできずにエラーになります。

手順6: Client ScopeとScopeの設定
- クライアント画面の「Client scopes」タブに戻ります。
- 「Assigned default client scopes」に
role_listやsaml_organizationが含まれている場合は、選択して「Remove」をクリックし除外します。

role_listsaml_organizationを除外しないと、Keycloakがデフォルトのロール情報をSAMLレスポンスに含めてしまい、AWS側でパースエラーが発生します。
urn:amazon:webservices-dedicatedをクリックし、「Scope」タブを選択します。- 「Full Scope Allowed」を
OFFにします。

Full Scope AllowedがONのままだと、ユーザーに割り当てられたすべてのレルムロールがSAMLレスポンスに含まれてしまい、AWSが期待するARNペア形式と一致しなくなります。
手順7: AWSでIAMアイデンティティプロバイダーを作成する
先にAWS側のリソースを作成します。後の手順でKeycloak側にAWSのARNを設定する必要があるためです。
まず、KeycloakのSAMLメタデータを取得します。
curl -o keycloak-metadata.xml \
http://localhost:8080/realms/master/protocol/saml/descriptor

- AWSマネジメントコンソールにログインし、上部の検索バーに
IAMと入力し、表示された「IAM」を選択します。 - 左側ナビゲーションの「アクセス管理」→「IDプロバイダー」を選択します。
- 右上のボタン「プロバイダを追加」をクリックします。
- 「プロバイダの設定」画面で以下を入力します。
- プロバイダのタイプ:
SAMLを選択します - プロバイダ名:
Keycloak - メタデータドキュメント: 「ファイルを選択」をクリックし、
keycloak-metadata.xmlを選択します - その他の項目はデフォルトのままにします
- プロバイダのタイプ:
- 「プロバイダを追加」をクリックします。

- 「アイデンティティプロバイダー」の一覧画面に
Keycloakが表示されていることを確認します。プロバイダーのARN(arn:aws:iam::<ACCOUNT_ID>:saml-provider/Keycloak)を控えておきます。

手順8: IAMロールを作成する
SSOログイン時に引き受けるIAMロールを作成します。
- 左側ナビゲーションの「アクセス管理」→「ロール」を選択します。
- 「ロールを作成」をクリックします。
- 「信頼されたエンティティタイプ」で「SAML 2.0 フェデレーション」を選択します。
- 以下を設定します。
- SAML 2.0 ベースのプロバイダー:
Keycloakを選択します - 「AWS マネジメントコンソールへのアクセスを許可する」を選択します
- 条件(Condition)はデフォルトのままにします(
SAML:audがhttps://signin.aws.amazon.com/samlに自動設定されます)
- SAML 2.0 ベースのプロバイダー:
- 「次へ」をクリックします。

- 「許可ポリシー」画面で
AdministratorAccessを検索して選択します(検証用のため)。 - 「次へ」をクリックします。
- 「ロール名」に
KeycloakSSORoleと入力します。 - 「ロールを作成」をクリックします。
- ロール一覧画面で
KeycloakSSORoleが作成されたことを確認し、ロールのARN(arn:aws:iam::<ACCOUNT_ID>:role/KeycloakSSORole)を控えておきます。

手順9: Keycloakにクライアントロールを作成する
AWSのIAMロールARNとプロバイダーARNのペアを、Keycloakのクライアントロールとして登録します。
- Keycloak管理コンソールに戻り、「Clients」→
urn:amazon:webservicesを選択します。 - 「Roles」タブを選択し、「Create role」をクリックします。
- 「Role name」に以下の形式で入力します。
arn:aws:iam::<ACCOUNT_ID>:role/KeycloakSSORole,arn:aws:iam::<ACCOUNT_ID>:saml-provider/Keycloak
<ACCOUNT_ID>は実際のAWSアカウントIDに置き換えてください。このロール名がSAMLアサーションのRole属性値としてそのまま送信されます。カンマの前後にスペースを入れないでください。
- 「Save」をクリックします。

手順10: Keycloakにユーザーを作成してロールを割り当てる
- 左側ナビゲーションの「Users」を選択し、「Add user」をクリックします。
- 以下を入力します。
- Username:
testuser - Email:
testuser@example.com - Email verified:
Off - First name:
Test - Last name:
User
- Username:
- 「Create」をクリックします。
- 作成されたユーザーの「Credentials」タブを選択し、「Set password」をクリックします。
- パスワードを設定し、「Temporary」を
OFFにして「Save」をクリックします。

- 「Role mapping」タブを選択します。
- デフォルトで
default-roles-masterが割り当てられています。これを選択し、「Unassign」をクリックして削除します。
default-roles-masterに含まれるレルムロール(offline_access、uma_authorizationなど)がSAMLレスポンスのRole属性に混入すると、AWSがARNペア形式としてパースできずエラーになります。
- 「Assign role」> 「Client roles」をクリックします。
urn:amazon:webservicesのロール(arn:aws:iam::...)を選択し、「Assign」をクリックします。


手順11: SSOログインを確認する
SSOログインの確認は、Keycloakの管理者(admin)とは別のブラウザまたはシークレットウィンドウで行ってください。adminユーザーにはAWSロールが割り当てられていないため、そのままではエラーになります。
ブラウザで以下のIdP-initiated SSO URLにアクセスします。
http://localhost:8080/realms/master/protocol/saml/clients/aws-saml
http://localhost:8080/realms/master/protocol/saml/clients/aws-saml
- Keycloakのログイン画面が表示されます。手順10で作成したユーザー(
testuser/ 設定したパスワード)でログインします。

- 認証が成功すると、AWSマネジメントコンソールにリダイレクトされます。
- 右上のユーザー情報に
KeycloakSSORole/testuserのように表示されていれば、SAMLフェデレーションによるSSOログインが成功しています。

トラブルシューティング
SSOログインが失敗する場合は、ブラウザの開発者ツール(Network タブ)で signin.aws.amazon.com へのPOSTリクエストから SAMLResponse を取得し、Base64デコードしてSAMLレスポンスの内容を確認してください。
echo '<SAMLResponseの値>' | base64 -d| エラーメッセージ | 原因 | 対処 |
|---|---|---|
client_not_found(Keycloakログに出力) | IDP-Initiated SSO URL nameが未設定 | クライアントのSettingsで aws-saml を設定する |
Your request included an invalid SAML response(Role属性が空) | Mapperが正しく設定されていない | 手順5のMapper設定を再確認する |
Your request included an invalid SAML response(Role属性にARN以外の値が混入) | role_listが除外されていない、またはFull Scope AllowedがON | 手順6の設定を再確認する |
Not authorized to perform sts:AssumeRoleWithSAML | ユーザーにdefault-roles-masterのレルムロールが残っており、Role属性にARN以外の値が混入 | 手順10でdefault-roles-masterを削除する |
| adminでログインするとエラー | adminにはクライアントロールが割り当てられていない | 別のタブでadminにログインしているとそのユーザでログインしていることになってしまします。ログアウトするかシークレットウィンドウで testuser でログインする |
まとめ
KeycloakとAWSのSAML SSO環境構築では、以下のリソースを作成・連携します。
| 作成場所 | リソース | 役割 |
|---|---|---|
| Keycloak | SAMLクライアント urn:amazon:webservices | AWSのSAMLメタデータをインポートして作成。属性マッピングでRole・RoleSessionNameを設定 |
| Keycloak | クライアントロール(ARNペア) | IAMロールARNとプロバイダーARNの対応付け |
| AWS(IAM) | アイデンティティプロバイダー Keycloak | Keycloakのメタデータ(署名証明書)を登録 |
| AWS(IAM) | ロール KeycloakSSORole | SSOログイン時に引き受けるロール(信頼ポリシーでSAMLプロバイダーを指定) |
Keycloakに別のSAMLクライアントを追加すれば、同じユーザーIDで他のサービスにもSSOログインできるようになります。これがSSOの「1つのIDで複数のサービスにログインできる」というメリットです。
