Open14

AWS Cognito * Keycloak saml認証

mm

手順イメージ

  1. Keycloak ローカルセットアップ
  2. AWS Cognito作成
  3. Keycloak , Cognito連携

TODO: 順次修正

mm

Keycloakセットアップ

環境
Windows11 WSL v2.x, Ubuntu22.04

https://www.keycloak.org/downloads

上記、公式のDownloadsページのServer一覧から、Container imageのQueryをクリック

Keycloak Container image Usageに書かれている
docker run quay.io/keycloak/keycloak start-dev で簡単に開発モードでkeycloakを起動できるみたい

mm

ポート等の設定と、keycloak管理画面へのログインユーザー設定を含めて docker run を叩きたい

docker run -d -p 8080:8080 -p 8443:8443 -p 9000:9000 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak start-dev
パラメータ 説明
KEYCLOAK_ADMIN 管理者名
KEYCLOAK_ADMIN_PASSWORD 管理者パスワード

start-dev は開発者モードで起動する
参考: https://www.keycloak.org/server/containers > Trying Keycloak in development mode

mm

dockerがbackgroundで立ち上がったら http://localhost:8080 に接続してみるとKeycloak管理画面へのログイン画面が表示される

ここで先ほどの管理者名、管理者パスワードを使ってログインすることができる

mm
Keycloak用語集
単語 説明
Realm レルム。Keycloakの管理単位、ユーザー等の情報はレルム単位で管理される
Realm Role 権限を定義する単位。Roleはユーザーがシステム内でどのような操作を行えるかを決定する。 Realm Role: レルム全体に適用されるロール Client Role: 特定のクライアントに限定されるロール
User Keycloakで管理される個々のユーザー
Client Keycloakが保護するアプリケーションやサービスです。クライアントにはWebアプリケーション、モバイルアプリ、APIなどが含まれます。クライアントは認証を行い、ユーザーに代わってアクセスをリクエストします
Client Scope クライアントに関連するロールやプロトコルマッパーのセットです。クライアントスコープを使用することで、特定のクライアントに対してアクセス権を柔軟に設定できます
Group ユーザーを整理するための単位です。グループにユーザーを追加することで、そのグループに設定されたロールや属性をユーザーに一括適用できます
Client Login設定

Access Settings の各項目

Root URL クライアントアプリケーションのルートURL。(例)http://localhost:3000
Home URL ユーザーがログイン後にリダイレクトされるホームページのURL。(例)http://localhost:3000/home
Valid redirect URIs 認証後にリダイレクトが許可されるURIのリスト。複数のURIをカンマで区切って指定できる。(例)http://localhost:3000/callback, http://localhost:3000/redirect
Valid post logout redirect URIs ログアウト後にリダイレクトが許可されるURIのリストです。これも複数のURIをカンマで区切って指定できます。ユーザーがログアウトした後、指定されたURLにリダイレクトされます。(例)https://your-app.com/logout-callback, https://another-app.com/logout
Clients > Keysタブ > Client signature requried OFFとクライアント署名を不要にしたが、必要なケース、不要なケースが知りたい

必要なケース

  • SPA (Single Page Application)

    • SPAは一般的にパブリッククライアントとして動作し、ブラウザ上で直接実行されます。このため、クライアント署名は通常必要ありません。代わりに、OAuth 2.0のImplicitフローやAuthorization Code Flow with PKCEを使用します。
      • 例: React、Angular、Vue.jsなどで作成されたアプリケーション
  • パブリッククライアント

    • パブリッククライアントは、クライアントシークレットを安全に保管できないクライアントです。ブラウザやモバイルアプリなどがこれに該当します。これらの場合、クライアント署名は通常使用されません
      • 例: モバイルアプリケーション(iOS、Android)、CLIアプリケーション

不要なケース

  • 機密クライアント (Confidential Client)
    • 機密クライアントは、クライアントシークレットや証明書を安全に保管できるサーバーサイドアプリケーションです。これらのクライアントは、クライアント署名を使用してセキュリティを強化することが推奨されます。
      • 例: サーバーサイドのウェブアプリケーション(Java、Node.js、Pythonなど)。
  • SAML 2.0を使用するクライアント
    • SAMLアサーションの署名が必要な場合、クライアント署名が使用されます。これにより、SAMLメッセージの信頼性と整合性が保証されます。
      • 例: エンタープライズアプリケーション統合。
  • OAuth 2.0 JWTベアラートークンを使用するクライアント
    • JWTベアラートークンを使用する場合、トークンの署名が必要です。これにより、トークンの発行元と内容の信頼性を確認できます。
      • 例: APIゲートウェイと連携するマイクロサービス
  • 高セキュリティ要件がある場合
    • 金融機関やヘルスケアなど、高度なセキュリティが要求される環境では、クライアント署名が使用されます。これにより、リクエストの改ざん防止や発信元の検証が強化されます。
      • 例: オンラインバンキングシステム、医療情報管理システム。
mm

Cognito, Keycloak を使ったsaml認証を作成する

https://qiita.com/kame_10/items/b202868846757d5048e6

大体これでできる

mm

細かいところを深堀してく

Cognitoの設定

Cognitoユーザープールサインインオプションで `ユーザー名、Email、電話` の3つのうちどれを(複数選択可)選択するか?

ユーザー名とEmailの2つを選択した場合、ログイン時に「ユーザー名またはEmail、とパスワード」を入力してください

という表示になる

ただ、注意なのが Keycloak 側でもEmailでのログイン可にしておく必要がある。ということ

画面でいうとこちら

Email settings で設定できる項目一覧

Email as username メールアドレスをユーザー名として使用できるようにするかどうかを設定する
Login with email ユーザーがメアドでログインできるようにするかどうかを設定する
Duplicate emails 同じメアドを複数のユーザーが使用できるようにするかどうかを設定する
Verify email ユーザーが登録時にメアドを確認する必要があるかどうかを設定する
Cognito SAMLで使うエンドポイント
エンドポイント 説明 今回のケース
https://ユーザープールのドメイン/login 認可エンドポイント keycloak画面でのログイン時にkeycloak -> Cognitoにリクエストされる
https://ユーザープールのドメイン/logout ログアウトエンドポイント サインアウト時に呼ばれる。ブラウザ -> keycloak -> cognito順に処理される
https://ユーザープールのドメイン/oauth2/authorize ユーザーをホストされたUIにリダイレクトするか、Idpでサインインするようにリダイレクト ログイン画面から「keycloackでログイン」をクリックするとブラウザ -> cognitoと呼ばれるAPI。cognitoはこの後idpに対してリダイレクトさせてログインを表示される
https://ユーザープールドメイン/saml2/idpresponse Cognitoがsaml2.0のIdpからの認証応答
クライアントシークレットの生成はしない
  • セキュリティのリスク
    • クライアントシークレットが公開されると、悪意のあるユーザーがそのシークレットを使用して不正なリクエストを行うことができます。
  • ブラウザに保存される可能性
    • シングルページアプリケーションはクライアントサイドで実行されるため、クライアントシークレットを安全に保持する方法がありません。
      SPAの場合はアプリケーションのコードがクライアントのブラウザで実行されるので、クライアントシークレットを使用するのは安全ではないので生成はしない
mm
暗号化キーと証明書

暗号化キー

KeycloackのRealm settings > Endpoints > Saml 2.0 identity Provider Metadataから取得できるMetadataファイルはIdp設定情報が含まれています。

含まれている具体的な情報

  • Entity ID
  • SSO Endpoint
  • 証明書(公開鍵)
    • 署名証明書(signing key): saml レスポンスの署名を検証するために使用する
    • 暗号化証明書(encryption key): saml アサーションを暗号化するために使用する(cognitoが復号に使用する)

これらの情報は Samlレスポンスの検証や暗号化されたデータの復号に必要です

証明書

Keycloakのクライアント設定で指定する証明書(Encryption keys config)は、samlアサーションを暗号化するための公開鍵を提供する

この公開鍵を利用して Cognitoが暗号化されたアサーションを復号します

mm

暗号化エラーが起きたので解決した

keycloack -> cognito でSAMLリクエストを復号化するときにエラーが起きていたので一旦やめた

暗号化、署名をOFFにする

keycloak側をOFFにする

Clientsからクライアントを選択して、Keys画面で両方をOFFにする(今回は悔しいが暗号化は見送る、、)

Cognito側をOFFにする

SAML署名と暗号化の部分を両方OFFにする

mm
OpenID Connectのスコープを変更する

OpenID Connectのスコープが元々 aws.cognito.signin.user.admin, Email, OpenIDだったが Email, OpenID, プロファイル に修正した

上記に応じて、下記も修正

NEXT_PUBLIC_SCOPE=profile email openid
mm

調査方法まとめ

Keycloakログ

今回はDockerで立ててるので docker logs コマンドで確認する

docker logs [docker container id]
実際にログファイルがある場所

とりあえずdocker に接続してみて調べる

$ docker exec -it 12b /bin/bash
bash-5.1$ find / -name "*.log"
/var/log/hawkey.log
find: ‘/proc/tty/driver’: Permission denied

/path/to/your/keycloak/log/file.logにあるらしいのだが、自分の場合見つからなかった、、
どこにあるのかわからんので、とりあえずdocker logsで対応した

mm

エラーまとめ

Invalid query param signature

エラー内容

2024-07-23 17:43:37,816 ERROR [org.keycloak.protocol.saml.SamlService] (executor-thread-311) request validation failed: org.keycloak.common.VerificationException: org.keycloak.common.VerificationException: Invalid query param signature

未解決、、、今回は暗号化を見送る、、

ChatGPTに投げた結果

エラーメッセージ Invalid query param signature は、KeycloakがCognitoからのSAMLリクエストの署名を検証できなかったことを示しています。このエラーが発生する主な原因として、CognitoとKeycloakの間で使用されている署名に関する設定が一致していない可能性があります。

検証と修正手順

1. KeycloakのSAML設定

  1. Keycloak管理コンソールにログインします。

  2. 左側のメニューからClientsを選択し、Cognito用のクライアントを選択します。

  3. Settingsタブを開き、次の設定を確認します。

    • Sign documents がオンになっていること。
    • Sign assertions がオンになっていること。
    • Signature algorithmRSA_SHA256 になっていること。
  4. SAML Keys セクションで、正しい証明書が設定されていることを確認します。

2. Keycloakの公開鍵のエクスポート

  1. Keycloak管理コンソールで、Clientsを選択し、Cognito用のクライアントを選択します。
  2. Keysタブを開きます。
  3. Certificateセクションから、公開鍵をエクスポートします。

3. Cognitoの設定確認

  1. AWS管理コンソールにログインします。
  2. Cognitoサービスを選択し、設定したユーザープールを選択します。
  3. 左側のメニューからIdentity Providersを選択し、SAML IdPの設定を編集します。
  4. Keycloakの公開鍵が正しく設定されていることを確認します。

4. リクエストURLの確認

以下のURLが正しく構成されていることを確認します。特に、クエリパラメータが正しくエンコードされていることを確認します。

詳細な手順

Keycloakでの設定確認

  1. Keycloak管理コンソールにログイン
  2. 左側のメニューからClientsを選択し、Cognito用のクライアントを選択。
  3. Settingsタブを開く。
  4. Signature and Encryptionセクションで、次の設定を確認:
    • Sign documents がオン。
    • Sign assertions をオンに切り替える。
    • Signature algorithmRSA_SHA256 になっている。
    • SAML signature key name を適切なキーに設定する。

Keycloakの公開鍵のエクスポート

  1. Keycloak管理コンソールで、Clientsを選択し、Cognito用のクライアントを選択。
  2. Keysタブを開く。
  3. Certificateセクションから、公開鍵をエクスポートする。

エクスポート例(公開鍵の形式を確認):

-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----

Cognitoの設定確認

  1. AWS管理コンソールにログイン
  2. Cognito > 該当ユーザープール > Identity Providers で、SAML IdPの設定を編集。
  3. Keycloakの公開鍵が正しく設定されていることを確認。

ログの再確認

KeycloakとCognitoのログを再度確認し、具体的なエラーメッセージを探します。

Keycloakのログ確認

  1. コンテナ内にシェルアクセス

    docker exec -it xxxxxx /bin/bash
    
  2. ログファイルの場所を検索

    find / -name "*.log"
    
  3. ログファイルの内容を表示

    tail -f /path/to/your/keycloak/log/file.log
    

まとめ

  • Sign assertions をオンにする。
  • SAML signature key name を適切なキーに設定する。
  • Keycloakの公開鍵がCognitoに正しく設定されていることを確認する。
  • Keycloakのログを再確認し、具体的なエラーメッセージを探す。

これらの設定を確認および修正した後、再度認証フローを試してみてください。問題が解決するはずです。