Simple OAuth (OAuth2) & OpenID Connect
League OAuth2 Serverライブラリをベースに構築された、Drupal向けの包括的なOAuth 2.0認可フレームワークおよびOpenID Connect実装。
simple_oauth
インストール
composer require 'drupal/simple_oauth:^6.1'
概要
Simple OAuthは、Drupal向けの完全なOAuth 2.0認可フレームワークRFC実装を提供します。Bearerトークンを使用したセキュアなAPI認証を可能にし、サードパーティアプリケーションがユーザーの資格情報を公開することなく、ユーザーに代わってDrupalリソースにアクセスできるようにします。
このモジュールは、モダンなPHP OAuth実装のデファクトスタンダードであるThe League of Extraordinary Packages OAuth2 Serverの上に構築されています。Authorization Code(PKCEサポート付き)、Password Credentials、Client Credentials、Implicit、Refresh Tokenグラントを含むすべての主要なOAuth 2.0グラントタイプをサポートしています。
また、OAuth 2.0の上に標準化されたアイデンティティレイヤーを提供する完全なOpenID Connectサポートも含まれており、JWTベースのトークン、ユーザー情報エンドポイント、トークン検証用のJSON Web Key Set(JWKS)エンドポイントが完備されています。
OAuth2スコープはDrupalロールとして実装されており、柔軟で馴染みのあるパーミッションモデルを提供します。トークンはコンテンツエンティティとして保存され、管理インターフェースを通じて管理したり、cronで自動的にクリーンアップしたりできます。
Features
- Bearerトークン認証によるOAuth 2.0認可フレームワークRFC実装
- カスタマイズ可能なユーザークレームを持つOpenID Connectアイデンティティレイヤー(sub、name、email、preferred_username、locale、profile、updated_at、zoneinfo)
- 6種類のOAuth2グラントタイプ:Authorization Code、Password Credentials、Client Credentials、Implicit、Refresh Token、Code
- ネイティブアプリおよびシングルページアプリケーション向けのセキュアなPKCE(Proof Key for Code Exchange)サポート
- セキュアなトークン検証のためのRSA暗号化によるJWTベースのアクセストークン
- きめ細かなパーミッション制御のためのDrupalロールベースのOAuth2スコープ
- 設定可能なバッチサイズによるcronでの自動トークン有効期限切れとクリーンアップ
- カスタムフィールド(secret、リダイレクトURI、デフォルトユーザー、confidentialフラグ)を持つConsumersモジュールによるコンシューマー/クライアント管理
- トークン情報とパーミッションを検査するためのデバッグエンドポイント
- サードパーティのトークン検証用JSON Web Key Set(JWKS)エンドポイント
- OpenID Connectユーザー属性取得用のUserInfoエンドポイント
- RSA公開鍵/秘密鍵ペア作成のための組み込み鍵生成ツール
- すべてのDrupal RESTリソースと統合するグローバル認証プロバイダー
- ユーザーアカウントまたはクライアントアプリケーション更新時のトークン失効
Use Cases
モバイルアプリケーション認証
モバイルアプリケーション向けにPKCE付きAuthorization Codeグラントを使用します。カスタムリダイレクトURIスキームを持つ非機密クライアント(confidential=false、pkce=true)を設定します。モバイルアプリがOAuthフローを開始し、ユーザーがWebブラウザで認証し、アプリがリダイレクトURIを通じて認可コードを受け取り、それをトークンと交換します。
シングルページアプリケーション(SPA)認証
SPA向けにPKCE付きAuthorization Codeグラントを使用します。SPAのオリジンをリダイレクトURIとする非機密クライアントを作成します。SPAはcode_challengeとcode_verifierパラメータを使用して、ブラウザでクライアントシークレットを公開せずにセキュアにトークンを取得します。
サーバー間通信
Drupal APIにアクセスする必要があるバックエンドサービス向けにClient Credentialsグラントを使用します。強力なシークレットを持つ機密クライアントを作成し、サービスがアクセスできる内容を定義するロールを割り当てます。サービスはclient_idとclient_secretで認証してアクセストークンを受け取ります。
ファーストパーティアプリケーションでのユーザーログイン
クライアントとサーバーの両方を管理する信頼されたファーストパーティアプリケーション向けにPasswordグラントを使用します。ユーザーはアプリケーションでDrupal資格情報を入力し、それがトークンと交換されます。完全に信頼できるアプリケーションにのみ使用してください。
長期間セッション
短いアクセストークン有効期限(5分)と長いリフレッシュトークン有効期限(14日)を設定します。クライアントはRefresh Tokenグラントを使用して再認証なしで新しいアクセストークンを取得し、ユーザーセッションを維持しながらセキュリティを提供します。
OpenID Connectアイデンティティプロバイダー
Simple OAuthを他のアプリケーション向けのOpenID Connectプロバイダーとして使用します。サードパーティアプリケーションはDrupalサイトを通じてユーザーを認証し、/oauth/userinfoエンドポイントを通じて標準化されたユーザークレーム(name、emailなど)を受け取ることができます。
デカップルドDrupalアーキテクチャ
Simple OAuthを使用して、ヘッドレス/デカップルドDrupalインストールのAPIアクセスをセキュアにします。フロントエンドアプリケーション(React、Vue、Angular)はユーザーを認証し、Bearerトークンを使用してDrupalへの認可されたAPIリクエストを行います。
APIゲートウェイ統合
/oauth/jwksエンドポイントを使用してDrupal発行のJWTトークンを検証するように外部APIゲートウェイを設定します。ゲートウェイは各リクエストごとにDrupalに問い合わせることなくトークンを検証でき、パフォーマンスを向上させ負荷を軽減します。
Tips
- 本番環境では常にHTTPSを使用して転送中のトークンを保護する
- RSA鍵はwebroot外に保存し、ファイルパーミッションを制限する(600または400)
- セキュリティのため短いアクセストークン有効期間(5〜10分)と長いリフレッシュトークン有効期間を使用する
- 既存の管理者ロールを使用するのではなく、OAuth2スコープ用の特定のロールを作成する
- すべてのパブリッククライアント(モバイルアプリ、SPA)でPKCEを有効にする(必須でなくても)
- 可能な限りImplicitの代わりにAuthorization Codeグラントを使用する
- oauth2_tokenテーブルのサイズを監視し、適切なcronバッチサイズを設定する
- PostmanやOAuth 2.0 Playgroundなどのツールを使用してOAuth実装をテストする
- /admin/config/people/simple_oauth/oauth2_tokenの管理インターフェースを使用して定期的にトークンを確認する
- 開発中はデバッグエンドポイント(/oauth/debug)を使用してトークンのパーミッションを検証する
Technical Details
Admin Pages 5
/admin/config/people/simple_oauth
OAuth2トークンの有効期限、RSA鍵のパス、および一般的なOAuth2動作設定を構成します。これはSimple OAuthモジュールのメイン設定ページです。
/admin/config/people/simple_oauth/openid-connect
OpenID Connect設定を構成し、利用可能なクレームを表示します。クレームはサービスコンテナを通じて管理されます。
/admin/config/people/simple_oauth/oauth2_token
システムに保存されているすべてのOAuth2トークンを表示および管理します。アクセストークン、認可コード、リフレッシュトークンを一覧表示します。
/admin/config/people/simple_oauth/oauth2_token/{oauth2_token}
特定のOAuth2トークンの詳細を表示します。タイプ、関連ユーザー、クライアント、有効期限が含まれます。
/admin/config/people/simple_oauth/oauth2_token/{oauth2_token}/delete
特定のOAuth2トークンの削除を確認します。これによりトークンは即座に失効します。
権限 7
Hooks 2
hook_simple_oauth_private_claims_alter
変換前にJWTアクセストークンに含まれるプライベートクレームを変更します。
hook_simple_oauth_oidc_claims_alter
OpenID Connectレスポンスにカスタムクレームを注入できるようにします。サイト固有のユーザー属性をクレームに追加するために使用します。
Drush Commands 1
drush simple-oauth:generate-keys
OAuth2トークン暗号化用のRSA公開鍵と秘密鍵のペアを生成します。指定されたディレクトリにprivate.keyとpublic.keyの両方を作成します。
Troubleshooting 8
上流のOAuthライブラリはデフォルトで秘密鍵のパーミッションをチェックします。注入されたシークレットを持つコンテナ化された環境では、これが誤検知を引き起こす可能性があります。settings.phpに$settings['simple_oauth.key_permissions_check'] = FALSE;を追加してチェックを無効にします。
サーバー時刻が正しく同期されていることを確認してください。トークンの有効期限はサーバー時刻に基づいています。また、access_token_expiration設定が適切であることを確認してください(デフォルト300秒)。
Simple OAuthはスコープとして利用可能な少なくとも1つのロールを必要とします。クライアントを作成する前に、OAuth2スコープとして使用するカスタムDrupalロール(anonymous、authenticated、admin以外)を作成してください。
client_idがConsumerエンティティのUUIDと一致していることを確認してください。機密クライアントを使用している場合は、client_secretが正しいことを確認してください。クライアントがシークレットを検証するよう設定されているか(confidential=true)を確認してください。
認可コードは1回限りの使用です。トークンと交換すると、再利用できません。テスト中は、各トークン交換ごとに新しい認可コードをリクエストしてください。
cronが実行されていることを確認してください。token_cron_batch_size設定を確認してください - 0に設定されている場合、すべての期限切れトークンが削除されるはずです。大規模なサイトではタイムアウト問題を防ぐために特定のバッチサイズを設定してください。
設定でdisable_openid_connectがtrueに設定されていないか確認してください。/oauth/userinfoおよび/oauth/jwksエンドポイントは、OpenID Connectが無効になっている場合は無効化されます。
code_challengeがS256(code_verifierのSHA256ハッシュ、base64urlエンコード)を使用して正しく生成されていることを確認してください。code_verifierはcode_challengeの生成に使用したのと同じ値である必要があります。
Security Notes 8
- クライアントサイドコード(JavaScript、モバイルアプリ)にクライアントシークレットを保存しない。代わりにPKCEを使用する。
- Implicitグラントはセキュリティ上の懸念からデフォルトで無効になっている。リスクを理解している場合のみ有効にする。
- トークンはパスワードのように扱う - 適切に保護する。トークンをログに記録したりURLに公開したりしない。
- クライアントシークレットは強力でランダムな値にする必要がある。データベースにはハッシュ化されて保存される。
- ユーザーパスワード変更やアカウントステータス変更時のトークン失効を検討する(モジュールにより自動的に処理される)。
- Passwordグラントは、ファーストパーティの完全に信頼されたアプリケーションでのみ使用すべきである。
- 本番環境ではRSA鍵とクライアントシークレットを定期的にローテーションする。
- 'debug simple_oauth tokens'パーミッションは管理者のみに制限する。