OpenID Connect でアプリケーションとサービスをセキュアにする

Keycloak で OpenID Connect を使用してアプリケーションとサービスをセキュアにする

利用可能なエンドポイント

完全に準拠した OpenID Connect プロバイダー実装として、Keycloak は、アプリケーションとサービスがユーザーを認証および認可するために使用できる一連のエンドポイントを公開しています。

このセクションでは、アプリケーションとサービスが Keycloak と対話する際に使用する必要がある主要なエンドポイントのいくつかについて説明します。

エンドポイント

理解する上で最も重要なエンドポイントは、well-known 設定エンドポイントです。これは、Keycloak の OpenID Connect 実装に関連するエンドポイントとその他の構成オプションをリストします。エンドポイントは次のとおりです。

/realms/{realm-name}/.well-known/openid-configuration

完全な URL を取得するには、Keycloak のベース URL を追加し、{realm-name} をレルムの名前に置き換えます。例:

https://127.0.0.1:8080/realms/master/.well-known/openid-configuration

一部の RP ライブラリは、このエンドポイントから必要なすべてのエンドポイントを取得しますが、他のライブラリでは、エンドポイントを個別にリストする必要がある場合があります。

認証エンドポイント

/realms/{realm-name}/protocol/openid-connect/auth

認証エンドポイントは、エンドユーザーの認証を実行します。この認証は、ユーザーエージェントをこのエンドポイントにリダイレクトすることによって行われます。

詳細については、OpenID Connect 仕様の「Authorization Endpoint」セクションを参照してください。

トークンエンドポイント

/realms/{realm-name}/protocol/openid-connect/token

トークンエンドポイントは、トークンを取得するために使用されます。トークンは、認証コードを交換するか、使用されるフローに応じてクレデンシャルを直接提供することによって取得できます。トークンエンドポイントは、有効期限が切れたときに新しいアクセストークンを取得するためにも使用されます。

詳細については、OpenID Connect 仕様の「Token Endpoint」セクションを参照してください。

Userinfo エンドポイント

/realms/{realm-name}/protocol/openid-connect/userinfo

userinfo エンドポイントは、認証されたユーザーに関する標準クレームを返します。このエンドポイントは、ベアラートークンによって保護されています。

詳細については、OpenID Connect 仕様の「Userinfo Endpoint」セクションを参照してください。

ログアウトエンドポイント

/realms/{realm-name}/protocol/openid-connect/logout

ログアウトエンドポイントは、認証されたユーザーをログアウトします。

ユーザーエージェントをエンドポイントにリダイレクトできます。これにより、アクティブなユーザーセッションがログアウトされます。その後、ユーザーエージェントはアプリケーションにリダイレクトバックされます。

エンドポイントは、アプリケーションによって直接呼び出すこともできます。このエンドポイントを直接呼び出すには、クライアントを認証するために必要なクレデンシャルと同様に、リフレッシュトークンを含める必要があります。

証明書エンドポイント

/realms/{realm-name}/protocol/openid-connect/certs

証明書エンドポイントは、レルムによって有効にされた公開鍵を JSON Web Key(JWK)としてエンコードして返します。レルム設定に応じて、トークンを検証するために 1 つ以上のキーを有効にできます。詳細については、「サーバー管理ガイド」および「JSON Web Key specification」を参照してください。

イントロスペクションエンドポイント

/realms/{realm-name}/protocol/openid-connect/token/introspect

イントロスペクションエンドポイントは、トークンのアクティブな状態を取得するために使用されます。言い換えれば、アクセストークンまたはリフレッシュトークンを検証するために使用できます。このエンドポイントは、コンフィデンシャルクライアントのみが呼び出すことができます。

このエンドポイントの呼び出し方法の詳細については、「OAuth 2.0 Token Introspection specification」を参照してください。

application/jwt ヘッダーでトリガーされるイントロスペクションエンドポイント

HTTP ヘッダー Accept: application/json の代わりに Accept: application/jwt を使用して、イントロスペクションエンドポイントを呼び出すことができます。application/jwt の場合、レスポンスには追加のクレーム jwt が含まれる場合があります。これは、完全な JWT アクセストークンであり、イントロスペクションされるトークンが 軽量アクセストークン である場合に特に役立ちます。これには、クライアントの高度な設定で「Support JWT claim in Introspection Response」を有効にする必要があります。これにより、トークンのイントロスペクションがトリガーされます。

動的クライアント登録エンドポイント

/realms/{realm-name}/clients-registrations/openid-connect

動的クライアント登録エンドポイントは、クライアントを動的に登録するために使用されます。

詳細については、「<@links.securingapps id="client-registration" />」ガイドおよび「OpenID Connect Dynamic Client Registration specification」を参照してください。

トークン失効エンドポイント

/realms/{realm-name}/protocol/openid-connect/revoke

トークン失効エンドポイントは、トークンを失効させるために使用されます。リフレッシュトークンとアクセストークンの両方がこのエンドポイントでサポートされています。リフレッシュトークンを失効させると、対応するクライアントのユーザー同意も失効します。

このエンドポイントの呼び出し方法の詳細については、「OAuth 2.0 Token Revocation specification」を参照してください。

デバイス認証エンドポイント

/realms/{realm-name}/protocol/openid-connect/auth/device

デバイス認証エンドポイントは、デバイスコードとユーザーコードを取得するために使用されます。これは、コンフィデンシャルクライアントまたはパブリッククライアントによって呼び出すことができます。

このエンドポイントの呼び出し方法の詳細については、「OAuth 2.0 Device Authorization Grant specification」を参照してください。

バックチャネル認証エンドポイント

/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth

バックチャネル認証エンドポイントは、クライアントによって行われた認証リクエストを識別する auth_req_id を取得するために使用されます。これは、コンフィデンシャルクライアントのみが呼び出すことができます。

このエンドポイントの呼び出し方法の詳細については、「OpenID Connect Client Initiated Backchannel Authentication Flow specification」を参照してください。

Keycloak ドキュメントの他の場所(このガイドのクライアント開始バックチャネル認証許可セクションや、サーバー管理ガイドの「クライアント開始バックチャネル認証許可セクション」など)も参照してください。

サポートされている許可タイプ

このセクションでは、リレー当事者が利用できるさまざまな許可タイプについて説明します。

認証コード

認証コードフローは、ユーザーエージェントを Keycloak にリダイレクトします。ユーザーが Keycloak で正常に認証されると、認証コードが作成され、ユーザーエージェントはアプリケーションにリダイレクトバックされます。その後、アプリケーションは認証コードとクレデンシャルを使用して、Keycloak からアクセストークン、リフレッシュトークン、および ID トークンを取得します。

このフローは Web アプリケーションを対象としていますが、ユーザーエージェントを埋め込むことができるモバイルアプリケーションを含むネイティブアプリケーションにも推奨されます。

詳細については、OpenID Connect 仕様の「Authorization Code Flow」を参照してください。

暗黙的

暗黙的フローは、認証コードフローと同様に機能しますが、認証コードを返す代わりに、アクセストークンと ID トークンが返されます。このアプローチにより、認証コードをアクセストークンと交換するための追加の呼び出しの必要性が軽減されます。ただし、リフレッシュトークンは含まれていません。これにより、有効期限の長いアクセストークンを許可する必要があります。ただし、これらのトークンを無効にすることが非常に難しいため、そのアプローチは実用的ではありません。または、最初のアクセストークンが期限切れになったら、新しいアクセストークンを取得するために新しいリダイレクトを要求できます。暗黙的フローは、アプリケーションがユーザーを認証するだけで、ログアウト自体を処理する場合に役立ちます。

代わりに、アクセストークンと認証コードの両方が返されるハイブリッドフローを使用できます。

注意すべき点の 1 つは、暗黙的フローとハイブリッドフローの両方に、アクセストークンが Web サーバーログやブラウザー履歴を通じてリークされる可能性があるという潜在的なセキュリティリスクがあることです。アクセストークンの有効期限を短くすることで、この問題をある程度軽減できます。

詳細については、OpenID Connect 仕様の「Implicit Flow」を参照してください。

現在の「OAuth 2.0 Security Best Current Practice」では、このフローを使用しないでください。このフローは、将来の「OAuth 2.1 specification」から削除されます。

リソースオーナーパスワードクレデンシャル

Keycloak でダイレクトグラントと呼ばれるリソースオーナーパスワードクレデンシャルは、ユーザークレデンシャルをトークンと交換することを許可します。現在の「OAuth 2.0 Security Best Practices」では、このフローを使用しないでください。代わりに、「デバイス認証許可」や「認証コード」などの代替方法を推奨しています。

このフローを使用する制限事項には、次のものがあります。

  • ユーザークレデンシャルがアプリケーションに公開される

  • アプリケーションにログインページが必要

  • アプリケーションが認証スキームを認識している必要がある

  • 認証フローの変更にはアプリケーションの変更が必要

  • アイデンティティブローカリングまたはソーシャルログインのサポートなし

  • フローはサポートされていません(ユーザーの自己登録、必須アクションなど)。

このフローに関するセキュリティ上の懸念事項には、次のものがあります。

  • クレデンシャルの処理に Keycloak 以外も関与する

  • クレデンシャルリークが発生する可能性のある脆弱な表面積の増加

  • ユーザーがクレデンシャルを入力するために Keycloak ではなく別のアプリケーションを信頼するエコシステムの作成

クライアントがリソースオーナーパスワードクレデンシャル許可を使用することを許可するには、クライアントで「ダイレクトアクセス許可を有効にする」オプションを有効にする必要があります。

このフローは OpenID Connect には含まれていませんが、OAuth 2.0 仕様の一部です。これは、将来の「OAuth 2.1 specification」から削除されます。

詳細については、OAuth 2.0 仕様の「Resource Owner Password Credentials Grant」の章を参照してください。

CURL を使用した例

次の例は、レルム master のユーザー名 user とパスワード password を持つユーザーのアクセストークンを取得する方法を示しています。この例では、コンフィデンシャルクライアント myclient を使用しています。

curl \
  -d "client_id=myclient" \
  -d "client_secret=40cc097b-2a57-4c17-b36a-8fdf3fc2d578" \
  -d "username=user" \
  -d "password=password" \
  -d "grant_type=password" \
  "https://127.0.0.1:8080/realms/master/protocol/openid-connect/token"

クライアントクレデンシャル

クライアントクレデンシャルは、クライアント(アプリケーションとサービス)がユーザーに代わってではなく、自分自身に代わってアクセスを取得したい場合に使用されます。たとえば、これらのクレデンシャルは、特定のユーザーではなく、システム全体に変更を適用するバックグラウンドサービスに役立ちます。

Keycloak は、シークレットまたは公開/秘密鍵のいずれかで認証するためのクライアントのサポートを提供します。

このフローは OpenID Connect には含まれていませんが、OAuth 2.0 仕様の一部です。

詳細については、OAuth 2.0 仕様の「Client Credentials Grant」の章を参照してください。

デバイス認証許可

デバイス認証許可は、入力機能が制限されているか、適切なブラウザーがないインターネット接続デバイスで実行されているクライアントによって使用されます。

  1. アプリケーションは、Keycloak にデバイスコードとユーザーコードを提供するように要求します。

  2. Keycloak は、デバイスコードとユーザーコードを作成します。

  3. Keycloak は、デバイスコードとユーザーコードを含むレスポンスをアプリケーションに返します。

  4. アプリケーションは、ユーザーにユーザーコードと検証 URI を提供します。ユーザーは、別のブラウザーを使用して認証される検証 URI にアクセスします。

  5. アプリケーションは、Keycloak がユーザー認証を完了するまで Keycloak を繰り返しポーリングします。

  6. ユーザー認証が完了すると、アプリケーションはデバイスコードを取得します。

  7. アプリケーションは、デバイスコードとクレデンシャルを使用して、Keycloak からアクセストークン、リフレッシュトークン、および ID トークンを取得します。

詳細については、「OAuth 2.0 Device Authorization Grant specification」を参照してください。

クライアント開始バックチャネル認証許可

クライアント開始バックチャネル認証許可は、OAuth 2.0 の認証コード許可のように、ユーザーのブラウザーを介したリダイレクトなしで、OpenID プロバイダーと直接通信して認証フローを開始したいクライアントによって使用されます。

クライアントは、クライアントによって行われた認証リクエストを識別する auth_req_id を Keycloak にリクエストします。Keycloak は auth_req_id を作成します。

この auth_req_id を受信した後、このクライアントは、ユーザーが認証されるまで、auth_req_id の代わりにアクセストークン、リフレッシュトークン、および ID トークンを取得するために Keycloak を繰り返しポーリングする必要があります。

クライアントが ping モードを使用している場合、トークンエンドポイントを繰り返しポーリングする必要はありませんが、Keycloak によって指定されたクライアント通知エンドポイントに送信された通知を待つことができます。クライアント通知エンドポイントは、Keycloak 管理コンソールで構成できます。クライアント通知エンドポイントの契約の詳細は、CIBA 仕様に記載されています。

詳細については、「OpenID Connect Client Initiated Backchannel Authentication Flow specification」を参照してください。

Keycloak ドキュメントの他の場所(このガイドのバックチャネル認証エンドポイントや、サーバー管理ガイドの「クライアント開始バックチャネル認証許可セクション」など)も参照してください。FAPI CIBA コンプライアンスの詳細については、「このガイドの FAPI セクション」を参照してください。

Keycloak 固有のエラー

Keycloak サーバーは、OIDC 認証レスポンスで、パラメーター error=temporarily_unavailable および error_description=authentication_expired を持つエラーをクライアントアプリケーションに送信できます。Keycloak は、ユーザーが認証され、SSO セッションを持っているが、現在のブラウザータブで認証セッションが期限切れになった場合にこのエラーを送信します。したがって、Keycloak サーバーはユーザーの SSO 再認証を自動的に実行して、成功レスポンスでクライアントにリダイレクトバックできません。クライアントアプリケーションがこのタイプのエラーを受信した場合、すぐに認証を再試行し、Keycloak サーバーに新しい OIDC 認証リクエストを送信することが理想的です。これにより、通常は SSO セッションのためにユーザーが常に認証され、リダイレクトバックされるはずです。詳細については、「サーバー管理ガイド」を参照してください。

Financial-grade API (FAPI) のサポート

Keycloak を使用すると、管理者はクライアントがこれらの仕様に準拠していることをより簡単に確認できます。

このコンプライアンスは、Keycloak サーバーが仕様に記載されている認証サーバーの要件を検証することを意味します。Keycloak アダプターは FAPI の特定のサポートがないため、クライアント(アプリケーション)側で必要な検証は、手動または他のサードパーティソリューションを通じて行う必要がある場合があります。

FAPI クライアントプロファイル

クライアントが FAPI に準拠していることを確認するために、「サーバー管理ガイド」で説明されているように、レルムでクライアントポリシーを構成し、FAPI サポートのグローバルクライアントプロファイルにリンクできます。これらは各レルムで自動的に利用できます。クライアントに準拠させる必要がある FAPI プロファイルに基づいて、fapi-1-baseline プロファイルまたは fapi-1-advanced プロファイルを使用できます。FAPI 2 ドラフト仕様に準拠するために、fapi-2-security-profile プロファイルまたは fapi-2-message-signing プロファイルも使用できます。

プッシュ認証リクエスト(PAR)を使用する場合は、クライアントが fapi-1-baseline プロファイルと fapi-1-advanced プロファイルの両方を PAR リクエストに使用することをお勧めします。具体的には、fapi-1-baseline プロファイルには pkce-enforcer エグゼキュータが含まれており、クライアントがセキュアな S256 アルゴリズムで PKCE を使用するようにします。これは、PAR リクエストを使用しない限り、FAPI Advanced クライアントには必要ありません。

CIBA を FAPI 準拠の方法で使用する場合は、クライアントが fapi-1-advanced クライアントプロファイルと fapi-ciba クライアントプロファイルの両方を使用していることを確認してください。fapi-ciba プロファイルには CIBA 固有のエグゼキュータのみが含まれているため、fapi-1-advanced プロファイル、またはリクエストされたエグゼキュータを含む他のクライアントプロファイルを使用する必要があります。FAPI CIBA 仕様の要件を適用する場合、コンフィデンシャルクライアントまたは証明書バインドアクセストークンの適用など、より多くの要件が必要です。

Open Finance Brasil Financial-grade API Security Profile

Keycloak は、「Open Finance Brasil Financial-grade API Security Profile 1.0 Implementers Draft 3」に準拠しています。これは、「FAPI 1 Advanced」仕様よりも一部の要件が厳しいため、一部の要件を適用するためにより厳格な方法で「クライアントポリシー」を構成する必要がある場合があります。特に

  • クライアントが PAR を使用しない場合は、暗号化された OIDC リクエストオブジェクトを使用していることを確認してください。これは、「Encryption Required」を有効にして構成された secure-request-object エグゼキュータを持つクライアントプロファイルを使用することで実現できます。

  • JWS の場合、クライアントが PS256 アルゴリズムを使用していることを確認してください。JWE の場合、クライアントは RSA-OAEPA256GCM を使用する必要があります。これは、これらのアルゴリズムが適用可能なすべての「クライアント設定」で設定する必要がある場合があります。

オーストラリア消費者データ権利(CDR)セキュリティプロファイル

Keycloak は、「Australia Consumer Data Right Security Profile」に準拠しています。

オーストラリア CDR セキュリティプロファイルを適用する場合は、オーストラリア CDR セキュリティプロファイルが FAPI 1.0 Advanced セキュリティプロファイルに基づいているため、fapi-1-advanced プロファイルを使用する必要があります。クライアントが PAR も適用する場合は、オーストラリア CDR セキュリティプロファイルでは PAR を適用するときに PKCE を適用する必要があるため、クライアントが RFC 7637 Proof Key for Code Exchange(PKCE)を適用していることを確認してください。これは、pkce-enforcer エグゼキュータを持つクライアントプロファイルを使用することで実現できます。

TLS の考慮事項

機密情報が交換されるため、すべてのインタラクションは TLS(HTTPS)で暗号化する必要があります。さらに、FAPI 仕様には、使用される暗号スイートと TLS プロトコルバージョンのいくつかの要件があります。これらの要件を満たすために、許可された暗号を構成することを検討できます。この構成は、https-protocols オプションと https-cipher-suites オプションを設定することで実行できます。Keycloak はデフォルトで TLSv1.3 を使用するため、デフォルト設定を変更する必要はない可能性があります。ただし、何らかの理由で以前の TLS バージョンにフォールバックする必要がある場合は、暗号を調整する必要がある場合があります。詳細については、「TLS の構成」ガイドを参照してください。

OAuth 2.1 のサポート

Keycloak を使用すると、管理者はクライアントがこれらの仕様に準拠していることをより簡単に確認できます。

このコンプライアンスは、Keycloak サーバーが仕様に記載されている認証サーバーの要件を検証することを意味します。Keycloak アダプターは OAuth 2.1 の特定のサポートがないため、クライアント(アプリケーション)側で必要な検証は、手動または他のサードパーティソリューションを通じて行う必要がある場合があります。

OAuth 2.1 クライアントプロファイル

クライアントが OAuth 2.1 に準拠していることを確認するために、「サーバー管理ガイド」で説明されているように、レルムでクライアントポリシーを構成し、OAuth 2.1 サポートのグローバルクライアントプロファイルにリンクできます。これらは各レルムで自動的に利用できます。コンフィデンシャルクライアントには oauth-2-1-for-confidential-client プロファイルを、パブリッククライアントには oauth-2-1-for-public-client プロファイルを使用できます。

OAuth 2.1 仕様はまだドラフトであり、将来変更される可能性があります。したがって、Keycloak の組み込み OAuth 2.1 クライアントプロファイルも変更される可能性があります。
パブリッククライアントに OAuth 2.1 プロファイルを使用する場合、「サーバー管理ガイド」で説明されているように、DPoP プレビュー機能を使用することをお勧めします。DPoP は、アクセストークンとリフレッシュトークンをクライアントのキーペアの公開部分と結び付けます。このバインディングにより、攻撃者が盗まれたトークンを使用することを防ぎます。

推奨事項

このセクションでは、Keycloak でアプリケーションをセキュアにする際の推奨事項について説明します。

アクセストークンの検証

Keycloak によって発行されたアクセストークンを手動で検証する必要がある場合は、「イントロスペクションエンドポイント」を呼び出すことができます。このアプローチの欠点は、Keycloak サーバーへのネットワーク呼び出しを行う必要があることです。これは、同時に多くの検証リクエストが発生している場合、遅くなる可能性があり、サーバーに過負荷をかける可能性があります。Keycloak が発行したアクセストークンは、「JSON Web Tokens (JWT)」であり、「JSON Web Signature (JWS)」を使用してデジタル署名およびエンコードされています。これらはこの方法でエンコードされているため、発行レルムの公開鍵を使用してアクセストークンをローカルで検証できます。レルムの公開鍵を検証コードにハードコードするか、「証明書エンドポイント」と JWS 内に埋め込まれた Key ID (KID) を使用して公開鍵をルックアップしてキャッシュできます。コーディングする言語に応じて、多くのサードパーティライブラリが存在し、JWS 検証に役立ちます。

リダイレクト URI

リダイレクトベースのフローを使用する場合は、クライアントに有効なリダイレクト URI を使用してください。リダイレクト URI は、できるだけ具体的にする必要があります。これは、クライアント側(パブリッククライアント)アプリケーションに特に当てはまります。そうしないと、次の結果になる可能性があります。

  • オープンリダイレクト - これにより、攻撃者はドメインから送信されているように見えるスプーフィングリンクを作成できます。

  • 不正なエントリ - ユーザーが Keycloak で既に認証されている場合、攻撃者はリダイレクト URI が正しく構成されていないパブリッククライアントを使用して、ユーザーの知識なしにユーザーをリダイレクトしてアクセス権を取得できます。

Web アプリケーションの運用環境では、常にすべてのリダイレクト URI に https を使用してください。http へのリダイレクトは許可しないでください。

いくつかの特別なリダイレクト URI も存在します。

http://127.0.0.1

このリダイレクト URI はネイティブアプリケーションに役立ち、ネイティブアプリケーションが認証コードを取得するために使用できるランダムポートで Web サーバーを作成できるようにします。このリダイレクト URI は任意のポートを許可します。「OAuth 2.0 for Native Apps」によると、localhost の使用は推奨されていません。代わりに IP リテラル 127.0.0.1 を使用する必要があります。

urn:ietf:wg:oauth:2.0:oob

クライアントで Web サーバーを起動できない場合(またはブラウザーが利用できない場合)、特別な urn:ietf:wg:oauth:2.0:oob リダイレクト URI を使用できます。このリダイレクト URI を使用すると、Keycloak は、タイトルとページのボックスにコードを含むページを表示します。アプリケーションは、ブラウザーのタイトルが変更されたことを検出するか、ユーザーがコードを手動でコピーしてアプリケーションに貼り付けることができます。このリダイレクト URI を使用すると、ユーザーは別のデバイスを使用してコードを取得し、アプリケーションに貼り付けることができます。

このページで