ドットをつなぐ:OIDCリソースとJWTアクセストークンの詳細な探求
このブログ投稿では、OIDCリソースインジケーターとアクセストークンの取得におけるその役割との関係性について明らかにすることを目指しています。
背景
過去のセッションでは、OpenID Connect(OIDC)プロトコル、リフレッシュトークン、アクセストークン、IDトークンについての紹介を行いました。これらは、アプリケーションで堅牢な認証を構築するための重要な要素です。しかしながら、コミュニティ内にはまだ疑問が残っており、繰り返し問い合わせられるのが「なぜ私のアクセストークンはJWTではないのか?」です。
コンセプトが新しく、またはリフレッシャーが必要な人々のために、このブログ投稿では、OIDCリソースインジケーターとアクセストークンの取得におけるその役割との関係性について明らかにすることを目指しています。
OIDCリソースの理解
もしOAuth 2.0プロトコルに精通しているなら、「リソース」という用語は聞き覚えがあるはずです。OIDCはOAuth 2.0に基づいているため、この概念を継承しています。
"リソース"または"保護されたリソース"は、クライアントアプリケーションが認証されたユーザーの代わりにアクセスしたいエンティティの表現です。これはユーザー情報であったり、サーバーAPI、あるいはサーバーによって許可された他のデータでもよいです。
プロトコルによると、リソースは認証サーバーへのリクエストのパラメータです。これは絶対URIとして表現された値であり、例えば https://my-company.com/api
のようなものです。これはリソースの識別子として機能し、ネットワークアドレス可能な位置またはユニークながらも架空のURIに対応する可能性があります。
Logtoでは、「Admin Console → APIリソース」ページから「APIリソース」を作成することができます。詳細については、このドキュメンテーション を参照してください。
JWTアクセストークン
JWT(JSON web token)形式のアクセストークンは、アクセストークンリクエスト中に「リソース」パラメータが指定された場合のみ発行され、クレームのセットを携行します。これにより、例えば、トークンの完全性やユーザーの許可を確認するために、あなたはクレームを復号化して検証することができます。
この「リソース」は、JWT内でトークンの「aud」クレームの一つとなり、トークンの意図された受取人を示します。RFC-7519を参照してください。
つまり、関係性ははっきりしています。
- JWTトークンのリクエスト時にリソースインジケータを指定します。
- リソースインジケータは、「aud」トークンクレームと整列します。
- APIリクエストを行う際には、JWTアクセストークンをベアラートークンヘッダーとして含める必要があります。APIサーバーは、「aud」クレームと他の許可関連のクレームを復号化および検証することで、APIリクエストを保護すべきです。
- 各アクセストークンは単一のリソースに対応します。もし異なるURIで登録された複数のAPIリソースを持っている場合は、それぞれのリソースで異なるアクセストークンをリクエストしてください。
🤔 でも、クライアントがアクセストークンのリクエスト時にリソースを指定しなかったらどうなるのでしょうか?
オペークアクセストークン
Logtoの場合、アクセストークンのリクエスト時にリソースインジケータが指定されていない場合、認証サーバーはそれがOIDC /userinfo
エンドポイント用であると仮定し、クライアントが後でOIDCユーザー情報エンドポイントからユーザープロフィール(ユーザーID、名前、メール、など)をリクエストできるようにオペークアクセストークンを発行します。
ログのSDKでは、getAccessToken()
を呼び出したり、resource
パラメータを指定せずに直接OIDCトークンエンドポイントにリクエストすると、このようなトークンを取得できます。
なお、このオペークアクセストークンは、OIDCサーバーにリクエストせずに検証する方法はないため、自分自身のAPIリソースリクエストには適していません。
まとめ
OIDCリソースは、クライアントアプリケーションがユーザーの代わりにアクセスしたい特定のデータやサービスを定義し、JWTアクセストークンはそのアクセスのための安全な手段として機能します。JWTアクセストークンの「aud」クレームはリソースインジケータと整合し、クライアントリクエスト時にサーバー が許可を検証するのを助けます。
Logtoでは、オペークアクセストークンはOIDCユーザー情報エンドポイントからユーザープロフィール情報を取得するためだけのもので、クライアントは特定のリソースごとに複数のアクセストークンをリクエストできます。
このブログ投稿が皆さんの疑問を解消し、ドットをつなぐ手助けになれば幸いです。お気軽に意見をお聞かせください。