client_secret
OAuth2ではclient_idに加えてclient_secretを求められることがある。
ウェブアプリであればこれはサーバに格納されているためユーザーから見えることはない。
ユーザーのデバイスにインストールされるアプリがclient_secretを持っていると、もはやこれは秘密とは言えない。
本当に秘密なのか気になる。
GoogleによるYouTube Data APIの認可フローの説明ではInstalled AppsとDevicesについての項目もあるが、いずれもアプリやデバイスがclient_secretを持っていることを前提としている。つまり秘密ではない。いいのか?
OAuth2におけるクライアントのタイプ
RFC6749ではクライアントのタイプとしてconfidential clientsとpublic clientsを規定している。
https://tools.ietf.org/html/rfc6749#section-2.1
confidential clientsは機密情報をユーザーから秘匿できるクライアントのこと
サーバー側でclient_secretやaccess_tokenを保持するウェブアプリケーションなど(web application)
public clientsは機密情報をユーザーから秘匿できないクライアントのこと
ブラウザのスクリプトがaccess_tokenを扱うアプリケーションなど(user-agent based application)
ユーザーの所有するデバイスにインストールされるアプリケーションなど(native application)
Google APIにおけるOAuth2
Using OAuth 2.0 to Access Google APIsによると5種類のフローが想定されている。
Mobile & Desktop AppsもTV and Limited-Input Device Applicationsも固定のclient_secretを埋め込む前提らしい。
いちおう「the client cannot keep the client_secret confidential」という認識はあるらしい。
Web Server Applications
Using OAuth 2.0 for Web Server Applications
これはRFC6749でAuthorization code grantと呼ばれているもの
grant_type = authorization_code
Do not store the client_secret.json file in a publicly-accessible location. In addition, if you share the source code to your application — for example, on GitHub — store the client_secret.json file outside of your source tree to avoid inadvertently sharing your client credentials.
Cient-side Web Application
OAuth 2.0 for Client-side Web Applications
This OAuth 2.0 flow is called the implicit grant flow
response_type = code
implicit grant flowなのでclient_secretについての言及は無い。
Mobile & Desktop Apps
OAuth 2.0 for Mobile & Desktop Apps
grant_type = authorization_code
incremental authorization with installed apps is not supported due to the fact that the client cannot keep the client_secret confidential
redirect_uriは4種類
Custom URI scheme
com.example.app:redirect_uri_path
com.googleusercontent.apps.123:redirect_uri_path
Loopback IP address
http://127.0.0.1:<port>
http://[::1]:<port>
Manual copy/paste
urn:ietf:wg:oauth:2.0:oob
Programmatic extraction
urn:ietf:wg:oauth:2.0:oob:auto
AppAuthなどのライブラリを使うことが推奨されている。
AppAuth ではDynamic client registrationができるようだ。
AppAuth for Android library
AppAuth for iOS library
OAuth for Apps: Windows Samples
TV and Limited-Input Device Applications
OAuth 2.0 for TV and Limited-Input Device Applications
これはRFC 6749でExtension Grantsに分類されるもの
grant_type = urn:ietf:params:oauth:grant-type:device_code
Server to Server Applications
Using OAuth 2.0 for Server to Server Applications
昔 two-legged OAuth と呼ばれていたもの
OAuthを使わずsigned JWTを使う方法もある
With some Google APIs, you can make authorized API calls using a signed JWT instead of using OAuth 2.0, which can save you a network request.
Your application can complete these tasks either by using the Google APIs client library for your language, or by directly interacting with the OAuth 2.0 system using HTTP.
we strongly encourage you to use libraries, such as the Google APIs client libraries, that abstract the cryptography away from your application code.
OAuth2における認可のタイプ
RFC6749で定義されている認可のタイプ5種類
Authorization Code Grant
認可コードを得るフェーズ
response_type = code
必須なのは他に client_id, redirect_uri
認可コードからトークンを得るフェーズ
grant_type = authorization_code
必須なのは他に code, redirect_uri, client_id
confidential clientsやclient credentialsを発行されたクライアントに対してはクライアント認証しなくてはならない
Implicit Grant
response_type = token
必須なのは他に client_id
ユーザーがその場にいることとリダイレクト先が登録済みであることが前提なのでクライアント認証を含まない。
Resource Owner Password Credentials Grant
grant_type = password
必須なのは他に username, password
confidential clientsやclient credentialsを発行されたクライアントに対してはクライアント認証しなくてはならない
Client Credentials Grant
クライアント認証だけでアクセストークンを発行するフロー。
grant_type = client_credentials
Extension Grants
認可サーバーによっては上記4種類以外の認可フローが使えることもある。
SAML2を使う場合はgrant_type = urn:ietf:params:oauth:grant-type:saml2-bearer&assertion=なんとかかんとか
YouTube Data APIの組み込みデバイス用認可フローならgrant_type = urn:ietf:params:oauth:grant-type:device_code
OAuth2におけるクライアント認証
RFC6749 2.3 Client Authentication
confidential clientsに対してはクライアント認証しなくてはならない(MUST)
クライアント認証の仕組みはセキュリティ上の要求に適合するならどんな方法をとっても良い(MAY)
一つのリクエストに複数の方式を含んではならない(MUST NOT)
public clientsに対してもクライアント認証してよい(MAY)が、それでクライアントの正当性が保証できると思ってはいけない(MUST NOT)。
クライアント認証においてはHTTPSを使わなければならない(MUST)
HTTPのBASIC認証のほかclient_idとclient_secretによる方法がある。それ以外の方法でもよい。
関連情報
OAuth2.0のclient_secretって本当に秘密鍵ですか?
Re: OAuth 2.0のclient_secretって本当に秘密鍵ですか?
RFC 6749 The OAuth 2.0 Authorization Framework
RFC 6750 The OAuth 2.0 Authorization Framework: Bearer Token Usage
access_tokenを得たあとはたいていこれ
RFC 7636 Proof Key for Code Exchange by OAuth Public Clients
code_challenge_methodがplainの場合は認可エンドポイントからのレスポンスの窃取に対抗できる。
code_challenge_methodがS256の場合はさらに認可エンドポイントへのリクエストリクエストの窃取にも対抗できる。
RFC 8252 OAuth 2.0 for Native Apps
RFC 7591 OAuth 2.0 Dynamic Client Registration Protocol