Love Beautiful Code

誰でもわかるOAuth認証 入門

omniauthOAuth認証

2022/8/22

OAuthとは何か

まずは、RFC 6479で定義されているOAuth 2.0の定義を確認したいと思います

定義

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.

簡単な日本語訳

OAuth 2.0はサードパーティアプリケーションによるHTTPサービスへの限定的なアクセスを可能にする認可フレームワーク

正直これでは全然分からないと思います。(自分をこれだけでは全然分かりませんでしたw) 以下から図で説明した後、詳しく説明していきたいと思います。

図解

1. クライアント(Webサービス等)がユーザー情報を取得する

クライアントがユーザー情報を取得

あるサービス(クライアント)が外部情報を取得したいと思い、外部情報を保持する外部サービスはリクエストをしてきたサービスが本当にデータを渡しても問題がないかどうかが、分からない。 もし、悪意のあるサービスの場合、ユーザー情報が漏洩してしまうリスクがあります。

2. アクセストークンを使用した場合のリクエスト

そこで、以下のようにリクエスト時にアクセストークンも一緒に送ります。そのアクセストークンが適切なトークンかどうかを検証して情報を渡しても問題ないかどうかを判定します。そして、もし問題なければデータを渡します。

アクセストークンを利用したリクエスト

このアクセストークンは有効期限が設定されていることがあり、その場合には有効期限内のみデータにアクセスすることができます。もし、有効期限が切れた場合には、リフレッシュトークンで更新することができます

3. アクセストークン取得方法

ここまで、アクセストークンを使用すれば、外部サービスから情報を取得できることがわかりました。しかし、アクセストークンをクライアントはどのように知るのでしょうか? ここで、新たな登場人物の登場です リソースオーナー(エンドユーザー)認可サーバー です。 OAuthでは、外部にある情報もエンドユーザーの所有物であると考えます。なので、リソースオーナーと呼びます。 状況としては、リソースオーナーであるエンドユーザーがあるサービスを利用したいと想定しています。そのサービスはエンドユーザーの外部サービスにデータを預けており、そのデータにアクセスしてさまざまなサービスを提供します。

リソースオーナーと認可サーバー

  1. ①エンドユーザーがクライアントに使用意思を伝える(ログインなど)
  2. ②クライアントは外部サービスのデータを使用したいので、 認可コード をもらうようにエンドユーザーにリダイレクトします
  3. ③エンドユーザー経由で認可サービスに使用意思を伝えます
  4. ④,⑤もし、ここで外部サービスで認証が行われていない場合、外部サービスにもログインをします
  5. ⑥ログインをすると、クライアントがどのようなデータを扱う予定か提示され、許可を求められます
  6. ⑦,⑧ここで許可をすると、認可サーバーから 認可コード という有効期限の短いアクセスコードを渡されます
  7. ⑨この認可コードをクライアントに渡します
  8. ⑩,11 クライアントは認可コードを認可コードに渡すことによって、その認証コードが適切であればアクセスコードをクライアントに渡してくれます

おめでとうございます! ここまでの処理を全て完了して初めてこのアクセストークンを使用して外部サービスからデータを取得できるようになりました!

もう少し詳しく

最後に、アクセストークンを取得するまでに行う処理をもう少しだけ詳しく説明します。 まずは、②,③のクライアントから認可サーバーへのリダイレクト処理についてです。下記にリダイレクトパスを記述しています

1GET /authorize?response_type=code 2 &client_id=i39akdjfl3 3 &state=xyz 4 &scope=write_customer,read_product 5 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcallback 6HTTP/1.1 7Host: auth.example.com
param名概要
response_type認可コードグラントの場合、値として code を設定する 
client_id クライアントの事前登録時に発行されたクライアントIDの値を設定する。クライアントを識別する値。一意。
stateクライアントが生成したランダムな値を設定。セッションと結びつけて管理することでCSRFを防ぐことができます
scopeクライアントが要求するスコープを記載
redirect_uriクライアント経由で認可コードを渡すためのURIを指定。クライアントの事前登録の際に設定しておく

⑦,⑧で外部データへのアクセスを許可した後にリダイレクトされるHTTPのLocationヘッダーに含まれる値を示します。

1HTTP/1.1 302 Found 2 Location: https://client.example.com/callback?code=kli43klSeki34kjdhfjaJfklaFJ&state=xyz

このparamに指定されているcodeが 認可コード です。stateはクライアントがランダムに出力した値と同じものが渡されます。

認可コードをもとにアクセスコードを取得する際のリクエストパスを示します

1POST /token HTTP/1.1 2 Host: auth.example.com 3 Authorization: Basic mdaGkdA43FAdadfjkd9aFakDsfamS 4 Content-Type: application/x-www-form-urlencoded 5 6 grant_type=authorization_code 7 &code=kli43klSeki34kjdhfjaJfklaFJ 8 &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcallback
param名概要
 grant_type authorization_code を設定 
 code  認可コードを設定
 redirect_uri クライアント経由で認可コードを渡すためのURIを指定。クライアントの事前登録の際に設定しておく

これでOAuth認証の中で 認可コードグラント についてなんとなくわかっていただけたでしょうか? OAuthには他に インプリシットグラント クライアントクレデンシャルグラント リソースオーナーパスワードクレデンシャルグラント などもあります。ここら辺もまとめてみたいと思います。 今回はここまで!

参考