目次
0. 認証と認可
認証 (Authorization)
誰であるかの証明です。
指紋認証とか顔認証とか。
認可 (Authentication)
権限の付与です。誰が 誰に 何の権限を 与えるかが明確にされる必要があります。
例えば、あるファイルサーバの「管理者が」「新入社員に」「共通フォルダへのフルアクセス権を」与えるみたいなことを認可と呼びます。
1. OAuth2.0
OAuth2.0は認可のためのオープンスタンダードなプロトコルです
仕様はRFC6749, RFC6750で定められています。
そもそもどういう時にOAuth2.0を使いたいのかというと、
あるサービスAから他のサービスBのリソースにアクセスしたい時です。
サービスA->サービスBのアクセスにサービスBのアクセストークンが必要という状況を仮定します。
この時、OAuth2.0は
サービスAに対してサービスBのアクセストークンを発行する(アクセス権限を付与する)ためのプロトコル
ということができます。
1-1. 構成するエンティティ
OAuth2.0には以下の3つのエンティティが登場します。
-
リソースサーバ (resource server)
- アクセスしたいリソースを有するサーバ
- サービスBのこと
-
クライアント (client)
- リソースサーバにアクセスする側
- サービスAのこと
-
認可サーバ (authorization server)
- クライアントに認可ページの提供やアクセストークンの発行を行う機構のこと
- 認可のためのエンドポイントやトークン発行のためのエンドポイントなど、さまざまなエンドポイントを構えている
1-2. 処理フローについて
認可サーバがクライアントにアクセストークンを発行するまでの処理フローが4つ定められています。
それぞれのフローの詳細については以下の記事が大変参考になります。
本記事では概要のみ触れておくことにします。
1-2-1. 認可コードフロー(Authorization Grant Flow)
認可決定エンドポイントはクライアントに直接アクセストークンを返すのではなく認可コードなるコードを返します。
クライアントがアクセストークンを取得するには、認可コードをトークンエンドポイントに提示する必要があります。
1-2-2. インプリシットフロー(Implicit Flow)
認可決定エンドポイントはクライアントに直接アクセストークンを返します。
"Implicit"とは、"暗黙的"という意味です。1
1-2-3. リソースオーナーパスワードクレデンシャルフロー(Resource Owner Password Credentials Flow)
認可サーバは認可エンドポイントを構えておらず、リダイレクトの認可画面もありません。
その代わりにクライアントはリソースサーバのID/PWを保持する必要があり、それらをトークンエンドポイントに提示する必要があります。
1-2-4. クライアントクレデンシャルフロー(Client Credentials Flow)
クライアントがリソースサーバから事前に取得したクレデンシャルを使ってアクセストークンを取得します。
AWSで言うところの、(事前に取得しておいた)アクセスキーとシークレットアクセスキーを使ってcli操作するみたいなイメージでしょうか。
このフローに関しては、以下の記事がわかりやすかったです。
1-2-5. 処理フローまとめ
上記4つの処理フローは、使用するエンドポイントや登場するトークンに違いがあります。
それらをまとめると以下の表になります。
フロー | 認可エンドポイント | 認可決定エンドポイント | トークンエンドポイント | 認可コード | 備考 |
---|---|---|---|---|---|
認可コード | O | O | O | O | 認可コードを用いてアクセストークンの発行を許可する |
インプリシット | O | O | X | X | トークンエンドポイントを使用せず、認可クレデンシャルが通ればアクセストークンが直接もらえる |
リソースオーナーパスワードクレデンシャル | X | X | O | X | 認可情報の入力が不要なので認可エンドポイントを使用しない。リソースサーバのクレデンシャルでアクセストークンを取得。 |
クライアントクレデンシャル | X | X | O | X | 認可情報の入力が不要なので認可エンドポイントを使用しない。事前に取得したクレデンシャルでアクセストークンを取得。 |
2. OAuth認証とその脆弱性
OpenIDConnectの説明に入る前に、OAuth認証なる認証手順について説明します。認可じゃなくて、認証です。
上述の通り、OAuthはアクセストークンを用いた認可のためのプロトコルです。
が、その過程では認証も同時に行われています。
つまり、OAuthは認可のためのプロトコルでありながら、認証にも使えてしまうということになります。
このOAuthの特徴を利用して、本来認可のプロトコルであるOAuthを使って認証を"済ませてしまう"ような認証手法をOAuth認証などと呼んだりします。
ただし、OAuth認証には重大なセキュリティーホールを孕んでいることが知られています。
以下の記事が有名らしいです。
3. OpenIDConnect
OAuth認証の脆弱性を踏まえ、OAuth2.0の拡張として登場したのがOpenIDConnect(OIDC)です。つまりOIDCは認証のためのプロトコルであり、認可のためのプロトコルであるOAuthとは若干目的が異なります。
特徴としては、IDトークンなるJWTでクレデンシャルを管理する点にあります。
IDトークンについては以下で定義されています。
つまりOIDCとは、
OAuthの拡張として、IDトークンもレスポンスできるように設計されたプロトコル
ということができます。
3-1. 構成するエンティティ
OAuthの拡張になるので、基本的にはOAuthと変わらないのですが、OIDCの場合、認可サーバは IDプロバイダ(IdP) と呼ばれます。
登場するエンティティは以下の2つです。
- クライアント
- IdP
認可サーバがIdPという呼び方にかわりましたが、基本的な機能としてはOAuthに登場した認可サーバと変わりません。変わる点はむしろクライアント側にあって、クライアントは認可エンドポイントへのリクエストに含まれるscope
パラメータにopenid
を指定した上で、response_type
パラメータに特定の値を追加することでOIDCを利用できます。
3-2. response_type
パラメータの取りうる値
種類としては、以下の4つがあります。
-
code
認可コードのリクエストを意味します -
token
アクセストークンのリクエストを意味します -
id_token
IDトークンのリクエストを意味します -
none
何も(認可トークンも、アクセストークンも、IDトークンも)リクエストしないことを意味します
一点留意すべきなのは、上記のリクエストは認可エンドポイントへのリクエストであるという点です。
つまり、例えばresponse_type
にcode
を指定した場合、あくまでも認可エンドポイントは認可コードのみレスポンスするという意味になります。その他のトークンはトークンエンドポイントからレスポンスされ、最終的にクライアントは認可コードもアクセストークンもIDトークンも取得できます。
3-3. 処理フローについて
OIDCの処理フローは前述したresponse_type
の値の組み合わせによって複数あります。
フローの詳細については、以下の記事が大変参考になります。
先ほどのOAuth処理フローの解説記事と同じ方が執筆されています。神に感謝。。
詳細は上記記事に丸投げするのですが、要約すると
- リクエストの
scope
パラメータの値によって、OAuthのリクエストなのかOIDCのリクエストなのかが識別される - リクエストの
response_type
パラメータの値によって、使用するエンドポイントと最終的なレスポンスが異なる
という感じでしょうか。
最後に
OAuthとOIDC、よく聞くけどいつかちゃんと調べないとな〜と思ってましたがやっと"何となくわかる"ところまでは理解できたかなという感じです
処理フローのところ完全に他記事に任せっきりでしたが、実際めちゃくちゃ参考になったのでその記事だけでもぜひご参考ください!
次はOAuth、OIDCとAWS Cognitoの関連について調べようかな〜と思っております!
参考
-
認可トークンは暗黙して(トークンエンドポイントもスキップしちゃって)ええやろ的な意味かなと理解してます ↩