Oauth2.0について学んだことメモ

Oauthとはなにか?
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service,
Key Words
-
サードパーティアプリ
-
HTTPサービス
-
限定的なアクセス
-
認可フレームワーク
「アクセストークンの発行方法についてのルール」 -
アクセストークン
「許可して良いアクセスか?」の判断に使われるもの。

Oauthなぜいるの?
「OAuth を使えば、ユーザーはサードパーティアプリに HTTP サービスのユーザー名、パスワードを教える
必要がない」から。
逆に、Oauthが無い状態ならサードパーティのアプリにPWとユーザー名(email)を教えてやらんといかん。
こうなるとサードパーティアプリはなんでもアプリを無制限に利用出来ちゃう!怖ぇよ。
当然、PW/ユーザー名の漏洩のリスクもある。
アクセストークンは漏洩しても有効期限があるからまだマシ。

Oauthのロール、4人の主要人物
1. リソースオーナー
サードパーティアプリ及び、HTTPサービス(アクセストークン出してやる認可サーバーとファーストパーティアプリのこと)に置かれた情報がリソース。そのオーナー。つまりサービスの人間のユーザーさん。
リソースオーナーはサードパーティーアプリにリソースへのアクセス権限を委譲。
権限を委譲されたサードパーティアプリはその権限の範囲内でリソースへのアクセスが許可される。
2. クライアント
リソースサーバー(ファーストパーティ)の利用者(Not 人間)。
つまり、サードパーティアプリのこと。
認証情報である「クライアント ID」、「クライアントシークレット」をセキュアに保存できるか?
=>以下2種類に
2-1. コンフィデンシャルクライアント
セキュア、サーバーサイドのWebAPPなど。
2-2. パブリッククライアント
Not セキュア、ブラウザベースのWebAPPやネイティブのAPPなど。?TODO
3. リソースサーバー
Web APIのこと。ファーストパーティ。
リソースサーバーへアクセスには常にアクセストークンが含まれなければならんぞよ。
4. 認可サーバー
アクセストークンを発行するサーバー。3機能。
(1)リソースオーナーを認証
=>のリソースのリソースオーナーであること確かめるための認証「あんさん、本当にこのリソースのオーナーなの?」ログインのためちゃうけどこの「認証」のためユーザー名とPWが求められる。
(なので理屈上ログインとリソースオーナー認証の2回、ユーザー名/PW入力がユーザーは求められる。)
(2)クライアントのリソースへのアクセスについてリソースオーナーの同意を得る
(3)アクセストークンを発行
=>アクセス権の証やで

アクセストークン、リフレッシュトークン、認可コード
全て認可サーバーからクライアントに向けて発行。クライアントが送る先は違うので注意

アクセストークン(クライアント=>リソースサーバーに送られる)
クライアントからリソースサーバーに対するアクセスに利用
リクエストの内容とアクセストークンの持つ権限を見てリソースへのアクセスをリソースサーバーが許可(Not 認可サーバー、認可サーバーはアクセストークン発行まで)
(1)誰のどのリソースにどのような操作を行うことが許可されているか => スコープ
(2)有効期限はいつまでか => 有効期限
Bearer トークン
リソースサーバーはアクセストークンの送信元を確認しない。
アクセストークンを所有していれば、それだけでアクセストークンに紐付けられた権限でリソースにアクセスすることが可能になる
ベアラートークンの使用 | Docs | Twitter Developer Platform
スコープ
スコープはアクセストークンに紐づくアクセス権をきめ細かくコントロールするための仕組み。
Google ではスコープとして httpsで始まる URI の形式をとっていますが、標準仕様で形式が決められているわけではありません。
=>流出した時の傷を最小限にするためにも最小限の権限にしよう。
有効期限
有効期限を過ぎたアクセストークンを付与したアクセスは、リソースサーバーによって拒否される
リフレッシュトークンの有効期限に比べて短い時間に設定されることが一般的。有効期限が来るまでの間はクライアントはアクセストークンを何度でも利用することが出来る。
有効期限はアクセストークンを取得するときのレスポンスの中に記載(JSON形式、expires_in)

リフレッシュトークン(クライアント=>認可サーバーに送られる)
クライアントから認可サーバーに対してアクセストークンの再発行を要求する際に利用される。
※リフレッシュトークンの発行は標準仕様では必須とされていないので、 API によってはリフレッシュトークンが発行されないことも
アクセストークンがクライアントからリソースサーバーに送られるものであるのに対して、
リフレッシュトークンは認可サーバーに送られるものである。
リフレッシュトークンはアクセストークンと比較して長い有効期限を持つことが一般的。

認可コード(クライアント=>認可サーバー(?トークンエンドポイント)に送られる)
「リソースオーナーがクライアントへの権限委譲に同意した証」として発行される。
クライアントが認可サーバーに対してアクセストークンを要求する際に利用される。
認可サーバーはリソースオーナーのユーザー名、パスワードを確認し、アクセス権の委譲に関する同意を得ると認可コードを生成し、HTTP リダイレクトを利用してクライアントに送信します。クライアントはトークンエンドポイントにアクセストークンを要求する際に、認可コードを利用
認可コードが利用出来るのは一度だけ同じ認可コードを使って、複数回トークン
を要求することは出来ない。
認可コードの有効期限は通常数分程度の非常に短い時間に設定される。標準仕様では 10 分以内を推奨。(ブラウザを介してクライアントに届くためリスキーなので)

Oauth3つのエンドポイント
1. 認可エンドポイント
提供:認可サーバー
役割:認可コードの発行
※リソースオーナーが同意して発行された認可コードはリダイレクトエンドポイントに
2. トークンエンドポイント
提供:認可サーバー
役割:(リクエスト側は認可コード+パラメーターを投げる)Basic 認証によって、クライアントのアイデンティティを確認してアクセストークンを発行
※Basic 認証として Auhotization ヘッダーに設定されるのは、クライアントID(クライアントの識別子)とクライアントシークレット(PWみたいなもん)、いずれも認可サーバーにクライアントを事前登録する際に発行される。
3. リダイレクトエンドポイント(リダイレクトURI)
提供:クライアント
役割:認可サーバーから認可コードを受け取るために使われる(ステータスコード302のレスポンスのクエリパラメーターとして認可コードの値が渡される)

Basic認証 TODO

Oauthの4つのグラントタイプ(権限付与のタイプ)
(1)想定される利用シーン(2)リクエストのパラメータ
下記の1~3はクライアント登録が前提になっている(らしい?)
1. 認可コードグラント(3-legged OAuth)
コンフィデンシャルクライアントに最適化(パブリッククライアントが使うの禁止という訳ではないし使うの推奨)
リソースオーナー、クライアント、認可サーバーの3者間でのやり取り。
2. インプリシットグラント
3. クライアントクレデンシャルグラント
4.リソースオーナーパスワードクレデンシャルグラント
TODO:パブリッククライアントの場合のグラントタイプとして推奨されている「PKCEを用いた認可コードグラント」

クライアント登録
クライアントの開発者はリソースを提供する組織に対してクライアントの情報を登録し、クライアント ID、クライアントシークレットの発行を受ける必要がある。
※Googleの場合ならGoogle Developer Consoleに登録・申請
開発者がクライアントの情報として登録する情報で最も大切なものは、リダイレクト
URI です

認可コードグラント(3-legged OAuth)
特徴
セキュア
以下2つの理由でセキュア。
(1)アクセストークンがブラウザーを介さずに、直接クライアントと認可サーバー間で受け渡されるため、 流
出するリスクが低い。
(2)以下のように相手が正しいことを確認しながらやり取りする。
- 認可サーバーは ID /PWの入力などでリソースオーナー認証
- 認可サーバーは HTTP Basic 認証によって、アクセス元のクライアントのクライアント ID、クライアントシークレットを確認
- クライアントは URI と SSL 証明書によって、アクセス先の認可サーバーのアイデンティティを確認
リフレッシュトークンが発行可能(任意)
シーケンス(やり取り)
認可コード(認可エンドポイント)=>アクセストークン(トークンエンドポイント)=>リソースアクセス
認可リクエストの5つのパラメーター
-
response_type
値はcode(認可サーバーがこれは認可コードほしいんだなと認識するために) -
client_id
クライアントの事前登録時に発行されたクライアントID -
state
クライアントが生成したランダムな値。csrfを防ぐ。 -
scope
そのままスコープを表す。 -
redirect_uri
クライアント登録の際に登録していたリダイレクトエンドポイント
リダイレクトURIの2つのパラメーター
-
code
認可コードの値 -
state
認可リクエストの時のstateの値と同じか確認してcsrf対策
トークンリクエストの5つのパラメーター
-
grant_type
認可コードグラントなら「authorization_code」 -
code
認可コードの値 -
redirect_uri
redirect_uriの値 -
client_id
クライアント登録時のクライアントID -
client_secret
くらいなんと登録時に発行されたクライアントシークレットの値。
トークンレスポンスの4つのパラメーター
-
access_token
アクセストークンの値 -
token_type
Bearer -
expires_in
有効期限。単位は秒 -
refresh_token
(任意)リフレッシュトークンの値
リソースへのアクセス
リソースサーバーごとの仕様に準ずる。
※Authorization Header の値として「Bearer」という文字列と共にアクセストークンの値を設定すること

インプリシットグラント TODO
現在は非推奨で「PKCE を使った認可コードグラント」が推奨されている。
パブリッククライアント向けのグラントタイプ。クライアントシークレットがやり取りの中で登場しない。
事前登録したリダイレクト URIにアクセストークンを渡すことで正しいクライアントへの受け渡しを担保しているとする。
「アクセストークンがリダイレクトでクライアントに受け渡されるため、漏洩や置き換えのリスクがある」
=>認可コードグラントの時はリソースオーナーには認可コードのみ渡されて、アクセストークンはあくまでクライアントまでしかイカなかったよね。

クライアントクレデンシャルグラント(2-legged OAuth) TODO
(コンフィデンシャル)クライアントがリソースオーナーの兼任あることが特徴。
「リフレッシュトークンは含むべきではない。
- 認可サーバーが提供するアクセストークンの権限はエンドユーザー単位ではなく、アプリ単位 (クライアント単位)
- クライアントがコンフィデンシャルクライアント

リソースオーナーパスワードクレデンシャルグラント TODO
リソースオーナーのユーザー名とパスワードがクライアントを通して認可サーバーに送られる。
リソースサーバーおよび認可サーバーとクライアントの提供元が同じ組織である場合に使われる。

リフレッシュトークンによるアクセストークン再発行 < イマココ

認可コードグラント + PKCE
リダイレクト URI としてカスタムスキームを利用している。
認可コード横取り攻撃
下記のような悪意あるアプリがいた時、
- リソースオーナーが所持するデバイスに画像編集アプリと悪意あるアプリがインストールされている
- 悪意あるアプリは画像編集アプリと同じカスタムスキームが設定されている
- 悪意あるアプリは画像編集アプリのクライアント ID を知っている
「重複カスタムスキームによる入れ替わりが発生した時はアクセストークンを発行させない」ためのPKCE
PKCE(Proof Key for Code Exchange by OAuth Public Clients)
以下3つのパラメータ
- code_verifier
ランダムな文字列 - code_challenge
code_verifier に対して次の code_challenge_method の計算をほどこして算出された値 - code_challenge_method
plain または S256
認可リクエストのパラメーターの「code_challenge」 と「 code_challenge_method」 を認可サーバーが保存。
トークンリクエストのパラメーターに 「code_verifier」認可サーバーはそれを検証。
※悪意あるアプリは正しい code_verifier を知らない。