# (OpenID Connect Core 1.0) 16.11. Token Substitution - 17. Privacy Considerations
###### tags: `oauth2/oidc`
担当::@hijiki51:
[toc maxlevel=5]
## 16.11 Token Substitution
Token Substitution Attack (トークン置換攻撃) は悪意あるユーザーが様々なトークン(Access Token, Authorization Codeなど)をすり替えることで不正にリソースにアクセスする攻撃のことである。
OAuth 2.0 の Implicit Flow はこのリスクへの対策がなされていない。そのため、Section 10.16 では、認証の一形態として認可プロセスを使用する場合、クライアントが ID Token, Access Token がその使用のために発行されたかどうかを判断できるようにする追加のセキュリティメカニズムを採用せずに Implicit Flow を使用してはならない(**MUST NOT**)としている。
OpenID Connectでは、IDトークンを介して提供されるメカニズムにより、この問題が緩和されます。ID トークンは署名されたセキュリティトークンで、`iss` (発行者)、`sub` (サブジェクト)、`aud` (オーディエンス)、`at_hash` (アクセストークンハッシュ)、`c_hash` (コードハッシュ) などのクレームを提供します。ID トークンを使用することで、クライアントはトークン置換攻撃を検知することができます。
```mermaid
sequenceDiagram
participant c as Client
participant at as Attacker
participant as as Authentication/Resource Server
c ->> as: Authentication Request[implicit]
as ->> at : Access token(User's)(1)
at ->> at : Token Substitution
at ->> c : Access token(Attacker's)(2)
c ->> as : Resource Request
```
- Clientは不正なもの
- (2)に事前に広いscopeを付与して許可しておく
- →(1)で許可した範囲より広い範囲に不正にアクセスできてしまう
---
- (1)でID Tokenも一緒に返される
- ID Tokenの`at_hash` と (2)のAccess Tokenのhashは一致しないので検知可能?
- でもClientが不正ならそもそも意味ないんじゃ
- Clientが仮に正式なものとすると、攻撃者はどうやって情報を取得する?
## 16.12 Timing Attack
タイミング攻撃は、復号化に成功した場合と失敗した場合、あるいはメッセージの署名検証に成功した場合と失敗した場合のコードパスの経過時間差を通じて、攻撃者が不必要に大量の情報を得ることを可能にする。これは、使用する暗号の有効鍵長を短くするために使用できる。
実装は、エラーが見つかった瞬間に検証処理を終了すべきではなく(**SHOULD NOT**)、この攻撃を避けるために、すべてのオクテットが処理されるまで処理を継続すべきである。
- これ現状実装するとライブラリに依存することになるから大変そう:@hijiki51:
## 16.13 Other Crypto Related Attacks
暗号化と署名/完全性チェックに使用される方法によって、さまざまな暗号関連の攻撃が可能である。実装者は、JWT仕様のためのセキュリティ上の考慮事項と、これらの仕様で特定された脆弱性を回避するために、JWT仕様が参照する仕様を参照する必要がある。
## 16.14 Signing and Encryption Order
暗号化されたテキストに対する署名は、多くの法域で有効とはみなされない。したがって、完全性と否認防止のために、本仕様では署名が実行される際に、プレーンテキストの JSON Claims に署名することを要求する。署名と暗号化の両方が必要な場合は、JWTで規定されているように、署名されたClaimsを含むJWSに対して実行され、その結果はネストされたJWTとなる。すべてのJWE暗号化アルゴリズムが完全性保護を提供するので、暗号化されたコンテンツに個別に署名する必要はないことに注意。
## 16.15 Issuer Identifier
OpenID Connectは、ホストとポートの組み合わせごとに複数の発行者をサポートします。ディスカバリーによって返される発行者は、ID Token の`iss`の値と正確に一致しなければなりません(**MUST**)。
OpenID Connectは、発行者URIのパスコンポーネントを発行者識別子の一部として扱います。例えば、発行者識別子が "https://example.com "のサブジェクト "1234"は、発行者識別子が "https://example.com/sales"のサブジェクト "1234"と等価ではない。
ホストごとに単一の発行者のみを使用することが推奨される(**RECOMMENDED**)。しかし、1つのホストが複数のテナントをサポートする場合、そのホストに対して複数のIssuerが必要になることがある。
- マルチテナントだるそう:@hijiki51:
## 16.16 Implicit Flow Threats
Implicit Flow では、Access TokenはHTTPSを介してクライアントの`redirect_uri`のfragment コンポーネントで返されるため、OPとユーザーエージェントの間、およびユーザーエージェントとRPの間で保護される。アクセス・トークンが捕捉される可能性があるのは、TLSセッションが終了するユーザーエージェントだけである。
## 16.17 TLS Requirements
実装はTLSをサポートしなければならない(**MUST**)。どのバージョンを実装すべきかは、時とともに変化し、実装時に広まっている展開と既知のセキュリティ脆弱性に依存する。実装はBCP195[RFC8996] [RFC9325]のガイダンスに従うべきである(**SHOULD**)。このガイダンスは、 TLSを使用する配備済みサービスのセキュリティを改善するための推奨事項と要件を提供する。
情報の漏洩と改ざんから保護するために、機密性と完全性の保護を提供する暗号スイートを使用したTLSを使用して機密性保護を適用しなければならない(**MUST**)。
TLSを使用するときは常に、RFC 6125に従って、TLSサーバー証明書のチェックを実行しなけれ ばならない(**MUST**)。
## 16.18 Lifetimes of Access Tokens and Refresh Tokens
アクセストークンは認証サーバによって取り消せないかもしれない。したがって、アクセストークンの寿命は一回限り、または非常に短い寿命に保たれるべきである(**SHOULD**)。
UserInfoエンドポイントまたは他の保護されたリソースへの継続的なアクセスが必要な場合、 Refresh Tokenを使用することができる。その後、クライアントはトークン・エンドポイントにおいてリフレッシュ・トークンを、リソースにアクセスするために使用できる新しい短寿命のアクセス・トークンと交換することができる。
認可サーバは、認可中にユーザへの長期的なグラントを明確に識別すべきである(**SHOULD**)。認証サーバは、エンドユーザがクライアントに付与されたアクセストークンおよびリフレッシュトークンを失効させるメカニズムを提供するべきである(**SHOULD**)。
- これをクライアントに通知する仕組みが Shared Signal Framework(SSF)
## 16.19 Symmetric Key Entropy
セクション10.1とセクション10.2では、鍵は`client_secret`値から生成される。したがって、対称署名または暗号化操作で使用する場合、`client_secret`値には、 暗号的に強力な鍵を生成するのに十分なエントロピーを含まなければならない(**MUST**)。また、`client_secret`値は、使用される特定のアルゴリズムのMAC鍵に必要な最小オクテット数も含まなければならない(**MUST**)。したがって、例えばHS256の場合、`client_secret`値は少なくとも32オクテットを 含まなければならない(**MUST**)`client_secret`値は制限されたアルファベットを使用する可能性が 高いので、ほぼ間違いなくもっと含むべきである(**SHOULD**)。
## 16.20 Need for Signed Requests
状況によっては、クライアントは、希望するリクエストパラメータが改ざんされずに OPに配送されることを保証するために、署名されたリクエストを使用する必要があるかもしれない。例えば、`max_age`と`acr_value`は、署名されたリクエストで配送されたときに、 実行された認証の性質についてより確実な保証を提供する。
## 16.21 Need for Encrypted Requests
状況によっては、OpenID Connectリクエストの内容を知ること自体が、エンドユーザーに関する機密情報を明らかにする可能性があります。例えば、クライアントが特定のClaimを要求していることや、特定の認証方法の使用を要求していることを知ることで、エンドユーザーに関する機密情報が明らかになる可能性があります。OpenID Connectでは、リクエストを暗号化してOpenIDプロバイダに送信することで、そのような潜在的な機密情報の漏洩を防ぐことができます。
## 16.22 HTTP 307 Redirects
HTTP 307 リダイレクトはリダイレクト先に、前のリクエストのフォームデータをすべて含む POST リクエストを送ります。これはOpenIDプロバイダが意図したクレデンシャルを RP に漏らす可能性がある。したがって、HTTP 307リダイレクトはリダイレクトURIにリダイレクトするときに使用してはならない**MUST NOT**。同様に、HTTP 302リダイレクトは通常このようなことをしないように実装されているが、HTTP 303リダイレクトはこのようなことをしないように定義されているので、HTTP 303リダイレクトの使用が望ましい。
## 16.23 Custom URI Schemes on iOS
iOSでは、複数のアプリケーションがカスタムURIスキームのハンドラとして登録できるため、呼び出し元のアプリケーションがSelf-Issued OpenID ProviderからAuthentication Replyを受け取ることは確定的ではないことに注意してください。クレームされた URI を使用することは、`openid:` カスタム URI スキームを使用することの代替手段です。
カスタムURIスキームにハンドラを割り当てることは可能であり、オペレーティングシステムがエンドユーザーが正しいハンドラを選択する手助けをすることも可能ですが、与えられたカスタムURIスキームのハンドラが、その後にインストールされたネイティブアプリケーションによって置き換えられていないことを保証することはできません。この記事を書いている時点では、この脆弱性に対する確実な緩和策はないようだ。
- Apple 君さあ・・・:@hijiki51:
## 17 Privacy Considerations
### 17.1 Personally Identifiable Information
UserInfoレスポンスには通常、個人を特定できる情報(PII, Personally Identifiable Information)が含まれる。そのため、指定された目的のための情報公開について、エンドユーザーの同意を、関連する規則に従って、認可時または認可前に得るべきである。利用目的は、通常、`redirect_uris` と関連付けて登録される。
必要なUserInfoデータのみがクライアントに保存されるべきであり、クライアントは受信したデータを利用目的の記述と関連付けるべきである(**SHOULD**)。
### 17.2 Data Access Monitoring
リソースサーバーは、エンドユーザーが自分のデータに誰がアクセスしたかを監視できるように、エンドユーザーのUserInfoアクセスログを利用できるようにすべきである(**SHOULD**)。
### 17.3 Correlation
クライアント間の相関の可能性からエンドユーザーを保護するために`sub`(サブジェクト) としてPairwise Pseudonymous Identifier (PPID)の使用を考慮すべきである(**SHOULD**)。
### 17.4 Offline Access
オフラインアクセスは、ユーザがその場にいないときにクレームにアクセスすることを可能にし、ユーザがその場にいるときにクレームを転送するよりも大きなプライバシーリスクをもたらします。したがって、リソースへのオフラインアクセスには明示的な同意を得ることが賢明である。本仕様では、リクエストが各法域のリクエスト処理条件に適合していることが既にわ かっている場合を除き、同意を得るために`prompt`パラメータを使用することを義務付ける。
- そうだっけ? :@hijiki51:
Implicit FlowまたはHybrid Flowを使用してUser Agent経由でAccess Tokenが返される場合、攻撃者にAccess Tokenが公開されるリスクが高くなり、攻撃者は後でそれを使用してUserInfoエンドポイントにアクセスする可能性がある。
アクセストークンがオフラインアクセスを可能にせず、サーバーがリクエストがオフラインで行われたかオンラインで行われたかを区別できる場合、リスクは大幅に軽減される。
したがって、本仕様では、アクセストークンがユーザーエージェントを介して送信されるとき、 オフラインアクセスリクエストを無視することを義務付ける。
:::info
つまり Client Credential や Implicit では Refresh tokenが発行されない=オフラインでアクセスできない(アクセストークンの有効期間が十分に短ければ)
:::
サーバーからオンラインとオフラインのアクセスを区別することは、特にネイティブクライアント にとって困難である可能性があることに注意すること。サーバーはヒューリスティックに頼らざるを得ないかもしれない。また、`code token` と `token` レスポンスタイプについて、ユーザーエージェントを通して送信される Access Token が暴露されるリスクは同じである。
したがって、実装はアクセストークンがユーザーエージェントを通して発行されたのか、トークンエンドポイントから直接発行されたのかを検知し、トークンがユーザーエージェントを通して発行された 場合にはオフラインアクセスを拒否するように準備されるべきである。