0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OAuthについて書いてみた

Last updated at Posted at 2023-06-18

Oauthとは?

現場でOAuth2.0を使用することになったので学習がてらまとめてみました。

OAuthとはめっちゃ簡単にいうとユーザーIDやパスワードを教えることなく、リソースを使用するための仕組みです。

OAuthの登場人物は4人(コードグラントによる)

登場部人物は基本的には4つあります。これをそれぞれロールと呼んだりもします。

  • リソースオーナー
  • 認可サーバー
  • クライアント
  • リソースサーバー

ちょっとややこしいですが、クライアントとはユーザーのことではなく、何かしらのリソース、例えば、写真やプロフィール情報などを利用したいアプリケーションのことです。

ちなみにユーザーはリソースオーナーです。

ざっくりしたOAuthの流れ

簡単に流れを説明すると、
あるウェブサイトを使っていて、そこでGooglePhotoに保存している写真を使いたいなーとなった場合を想定してみましょう。

ユーザーであるリソースオーナーは、クライアントであるウェブアプリケーションに対して、リソースを使いたい!と伝えます。

すると、認可サーバーというアクセスの許可を与えるためのサーバー(認可エンドポイント)が「君のリソースを使いたがってるんだけど、使わせてもいいのか?」と確認してきます。

そこで、リソースオーナーが「使ってもいいよ」と許可すると、
認可サーバーはクライアントに認可コードという、「リソースを使ってもいいことも認められた証明書」を発行するわけです。

で、その認可コードを使って、再度認可サーバーの中の別の場所(トークンエンドポイント)に
「自分はリソースを使ってもいいと許可もらってるんで、情報を取得させてください」と伝えます。

そこで、認可サーバーがそれを確認できたら、リソースにアクセスできるようなトークンを発行し、返してあげます。

クライアントはこのトークンをリソースサーバーに伝えると無事欲しい情報を取得できるようになるわけです。

もう少し詳しい流れを図でまとめてみました。
スクリーンショット 2023-06-18 14.20.57.png

補足説明

以下のようなクエリパラメータを付与している

GET /authorize
?response_type=code
&state=xyz
&scope=read
&redirect_url=https%3A%2F~/callback

HTTP/1.1
Hots: hoge.example.com

Locationヘッダーには3番で指定したリダイレクトURIが指定される。
このURIにはパラメータとして、認可コードとstateがセットされる。
認可コードの有効期限は基本仕様で10分以内。

stateは基本仕様では不要だが、クロスサイトリクエストフォージェリを防ぐために推奨
stateは1番で生成されたランダム文字列と9番でのセッションの値が同じか確認するために必要

POST /token HTTP/1.1
	Host: hoge.example.com
	Authorization: Basic gad32fgaE2RTga43tgsDH3w
	ContentType: application/x-www-forkm-urlencoded
	
	grant_type=authorization_code
	&code=SplcBeWEg35GasgasA
	&redirect_uri=https%3A3gagasdgG~2Fcallback

ここでのAuthorizationはclient_idとclient_secretを:でつないで、 Base64エンコードしたもの。
しかし、client_idとclient_secretをボディに含む形も認められている。その場合、Basic認証のためのAuthorizationヘッダーは必要ない。

  • grant_tyoe
    値にauthorization_codeを指定

  • code
    9番で取得した認可コードの値を設定

  • redirect_uri
    3番のリクエストで指定したredirect_uriを設定

  • client_id
    クライアントの登録時に発行されたクライアントIDの値を入れる

  • client_secret
    クライアントの登録時に発行されたクライアントsecretの値を入れる

11

HTTP/1.1 200 OK
	ContentType: application/json;charset=UTF-8
	Cache-Control: no-store
	Pragma: no-cache

	{
 	  "access_token" : "ASt3tgdL",
	  "token_type" : "Bearer",
	  "expires_in": 3600,
	  "refresh_token" : "as2rweaDFgaehAEH"
	}	
  • access_token
    そのまま、アクセストークンが返ってくる

  • token_type
    さっきはBearerで指定したので、それを示している

  • expires_in
    アクセストークンの有効期限が秒単位で入っている

  • refresh_token
    基本仕様では任意なので返ってくるかは分からない。
    access_tokenの再発行に必要

コードグラント

今回説明したフローは認可コードグラントというものです。
実はこれ以外にも色々とコードグラント(要はフローのパターン)があります。

  • インプリシットグラント
    インプリシットグラントは推奨されていないコードグラントです。

  • クライアントクレデンシャルグラント

  • リソースオーナーパスワードクレデンシャルグラント

認可コードグラント + PKCE

認可コードグラントの場合、悪質なアプリケーションによって認可コードが横取りされてしまう危険性がある。
それを防ぐ仕組みがPKCE(ピクシー)である。

横取りは以下のような条件で起こりうる

  • リソースオーナーが所持するデバイスにネイティブアプリと悪質なアプリがインストールされている
  • 悪質なアプリはネイティブアプリと同じカスタムスキームが設定されている
  • 悪質なアプリはネイティブアプリのクライアントIDを知っている

PKCEの登場人物

基本的には認可コードグラントのプロセスなのですが、いくつか新しい登場人物がいます。それは以下の3つです。

  • code_verifier
    長さが43文字、最大128文字までの間の[A-Z]/[a-z]/[0-9]/"-"/"."/"_"/"~"からなるランダムな文字列
  • code_challenge
    code_verifierに対して次のcode_challenge_methodの計算をほどこして算出された値
  • code_challenge_method
    code_challenge_methodの値はplainまたはS256
    ※2つあるが、基本的にはS256を使用する。
計算方法
plain code_challenge = code_verifier
s256 code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

で、何が違うかというとこれらを認可コードグラントのプロセスに追加する点です。

まず、code_challengeとcode_challenge_methodを認可リクエストに追加します。

GET /authorize
?response_type=code
&state=xyz
&scope=read
&redirect_url=https%3A%2F~/callback
&code_challenge=Egasgd~省略
&code_challenge_method=S256

HTTP/1.1
Hots: hoge.example.com

で、先にこの2つを渡しておいて、トークンリクエストの時にcode_challenge_methodで変換する前の生データであるcode_verifierをトークンエンドポイントに渡します。

POST /token HTTP/1.1
	Host: hoge.example.com
	Authorization: Basic gad32fgaE2RTga43tgsDH3w
	ContentType: application/x-www-forkm-urlencoded
	
	grant_type=authorization_code
	&code=SplcBeWEg35GasgasA
	&redirect_uri=https%3A3gagasdgG~2Fcallback
    &code_verifier=asgARher~省略

そして、トークエンドポイントではこれらを使って検証をし、成功すればトークンを返します。
こうすることで、もし悪意のあるアプリケーションが認可コードを奪ったとしても、code_verifierの検証に失敗するのでトークンを取得できないということですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?