本稿は GitHub Docs の "Authorizing OAuth Apps" ページに書かれている情報に基づいています。英語版はこちら → "Spec Violations in GitHub OAuth Implementation and Security Considerations"
仕様違反箇所
-
認可リクエストの
response_type
リクエストパラメーターがない。当パラメーターは必須である。RFC 6749 (The OAuth 2.0 Authorization Framework) Section 4.1.1 (Authorization Request) 参照。 -
トークンレスポンスのデフォルトフォーマットが
application/x-www-form-urlencoded
のようである。フォーマットは常にapplication/json
でなければならない。RFC 6749 (The OAuth 2.0 Authorization Framework) Section 5.1 (Successful Response) 参照。 -
トークンレスポンスの
scope
レスポンスパラメーターに列挙されている値がカンマで区切られている。区切り文字はスペースでなければならない。RFC 6749 (The OAuth 2.0 Authorization Framework) Section 3.3 (Access Token Scope) 参照。 -
トークンレスポンスが
"token_type":"bearer"
と言っているにも関わらず、リソースアクセス時のAuthorization
ヘッダーのフォーマットがAuthorization: token OAUTH-TOKEN
である。フォーマットはAuthorization: Bearer OAUTH-TOKEN
でなければならない。RFC 6750 (The OAuth 2.0 Authorization Framework: Bearer Token Usage) Section 2.1 (Authorization Request Header Field) 参照。 -
デバイス認可レスポンスのデフォルトフォーマットが
application/x-www-form-urlencoded
のようである。フォーマットは常にapplication/json
でなければならない。RFC 8628 (OAuth 2.0 Device Authorization Grant) Section 3.2 (Device Authorization Response) 参照。 -
デバイスフローにおけるトークンレスポンスのデフォルトフォーマットが
application/x-www-form-urlencoded
のようである。フォーマットは常にapplication/json
でなければならない。RFC 8628 (OAuth 2.0 Device Authorization Grant) Section 3.5 (Device Access Token Response) 参照。当セクションは "If the user has approved the grant, the token endpoint responds with a success response defined in Section 5.1 of [RFC6749];” と言っている。 -
デバイスフローにおけるトークンレスポンスの
scope
レスポンスパラメーターに列挙されている値がカンマで区切られている。区切り文字はスペースでなければならない。トークンエンドポイントの実装は RFC 6749 に準拠すべきだと RFC 8628 は言っている。
GitHub 独自拡張
-
認可リクエストの
login
パラメーター。GitHub 独自のパラメーターを導入するよりも、OpenID Connect Core 1.0 Section 3.1.2.1 (Authentication Request) で定義されているlogin_hint
を活用したほうがよい。 -
認可リクエストの
allow_signup
パラメーター。GitHub 独自のパラメーターを導入するよりも、Initiating User Registration via OpenID Connect で定義されているprompt=create
を活用したほうがよい。 -
トークンリクエストの
Accept
ヘッダーの値に従って、トークンエンドポイントがレスポンスのフォーマットを変更している。否。フォーマットは常にapplication/json
でなければならない。 -
デバイス認可リクエストの
Accept
ヘッダーの値に従って、デバイス認可エンドポイントがレスポンスのフォーマットを変更している。否。フォーマットは常にapplication/json
でなければならない。 -
デバイスフローにおいてトークンエンドポイントが返す可能性のあるエラーコードの内、次のものは GitHub 独自のもので、標準仕様では定義されていない →
incorrect_client_credentials
,incorrect_device_code
,device_flow_disabled
セキュリティ上の考慮事項
-
RFC 7636 (Proof Key for Code Exchange by OAuth Public Clients) をサポートすべきである。具体的には、認可エンドポイントは
code_challenge
リクエストパラメーターとcode_challenge_method
リクエストパラメーターを、トークンエンドポイントはcode_verifier
リクエストパラメーターをサポートすべきである。この仕様は、攻撃者が盗んだ認可コードをトークンエンドポイントでアクセストークンと交換することを防ぐ。詳細は『PKCE: 認可コード横取り攻撃対策のために OAuth サーバーとクライアントが実装すべきこと』を参照のこと。 -
RFC 8705 (OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens) Section 3 (Mutual-TLS Client Certificate-Bound Access Tokens) をサポートすべきである。GitHub がこの証明書バインディングの仕様をサポートしていれば、先のセキュリティインシデント ("Security alert: Attack campaign involving stolen OAuth user tokens issued to two third-party integrators") の衝撃をかなり軽減できていたであろう。この仕様は、攻撃対象のクライアントアプリケーションのクライアント証明書の窃取にも成功していない限り、攻撃者が盗んだアクセストークンを用いてリソースにアクセスすることを防ぐ。証明書バインディングの説明については『実装者による Financial-grade API (FAPI) 解説』を参照のこと。
-
より安全なクライアント認証方式をトークンエンドポイントとデバイス認可エンドポイントでサポートすべきである。RFC 6749 の Section 2.3 (Client Authentication) で説明されている伝統的なクライアント認証方式は、クライアントシークレットがネットワーク上を流れる。これは避けるべきである。実際に、Financial-grade API 仕様では伝統的なクライアント認証方式は禁止されている。より安全なクライアント認証方式については『OAuth 2.0 クライアント認証』を参照のこと。
-
2012 年 10 月の RFC 6749 の公開 (約 10 年前!) 以降、他にも多くのセキュリティ向上のための仕様が策定された。例えば、JAR (RFC 9101 The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR))、JARM (Financial-grade API: JWT Secured Authorization Response Mode for OAuth 2.0 (JARM))、PAR (RFC 9216 OAuth 2.0 Pushed Authorization Requests) など。OpenID Foundation のワーキンググループのエキスパートに相談すべきである。