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?

ApplibotAdvent Calendar 2024

Day 16

OpenID Connectを超ざっくりな感じでまとめてみる

Last updated at Posted at 2024-12-15

Applibot Advent Calendar 2024 16日目の記事です

はじめに

みなさん普段からサードパーティ認証してますか?私はしてます。
最近は色んなサービスのログインにGoogleアカウント使ったり、Twitterアカウント使ったり出来るのでわざわざサービス毎にアカウントを作ってパスワードを覚えてなどしなくてよくて便利な時代になりました。
今回は初めて手元で認証周りを触る機会があったので、自分なりにざっくりとまとめてみました。

この記事のゴール

OpenID Connectを通してサードパーティからID Tokenを受け取って検証するところまで

OpenID Connectってなんぞや

OpenID ConnectとはOAuth2.0で定義されている認可フローに則りつつ、認証まで出来るようにした規格のことです。
詳しくはこちらを読んでください。
Fin.

……で終わるのは流石に雑すぎるのでもう少し解説します。

まずOAuth2.0というのは外部アプリケーションがあるサービス(GoogleやApple、Facebookなど)にアクセスするための認可のフローを規格化したフレームワークのことです。

通常、サービスに対してアクセスするためにはアクセストークンという文字列が必要になります。
このアクセストークンを鍵としてサービス側に渡すことで、ユーザーデータの取得を行ったり、SNS系のサービスであればソーシャルグラフの取得を行ったりなどをすることが出来るのですが、あらゆるアプリケーションがそれを無制限にできてしまうと困ったことになるので、サービスが認めた限定された外部アプリケーションのみに渡す必要があります。
このアクセストークンを渡す仕組みを規格化したものが先ほどのOAuth2.0となります。

ではその上でOpenID Connectとは何かというと、OAuth2.0に則ったフローを保ちながら認証も出来るようにした拡張規格となります。

OAuth2.0では認可の結果としてアクセストークンを取得しました。
これはこれでいいのですが、このアクセストークンには誰が認証したのかなどの情報は含まれていないため、これを振りかざして身分証明書のように使うことはできません。
そこで誰が認証したのかや署名による改ざん防止などをID Tokenというトークンに含めて、身分証明書のように使えるようにし、それをアクセストークンと一緒に発行しようと定めたのがOpenID Connectになります。

手順

こちらのフローで進めていきます。

認証リクエストを作って認可エンドポイントに投げる

まず認可エンドポイントってどこ?という話ですが、これは各サービスのOpenID Configurationに全て記載されています。(OpenID Configurationに関してはこちらを参照してください。)
例えば、Googleであれば以下のURLから確認できます。

https://accounts.google.com/.well-known/openid-configuration

ここにアクセスするとJSON形式でいくつかパラメータがありますが、その中でもauthorization_endpointにあたる箇所が認可エンドポイントになるため、URLは以下の通りです。

https://accounts.google.com/o/oauth2/v2/auth

さて、その上でリクエストをするためにいくつかパラメータを指定する必要があり、必須のものだけを集めると以下になります。

名前 説明
response_type codeと指定してください。認可の方法を表していて、OAuth2.0的には全部で4つのやり方があるのですが、OpenID Connectではそのうちの一つに乗っかっています
client_id クライアントIDです。各サービスの管理画面から取得してください。
scope 要求するアクセス権限となります。スペースもしくはカンマ区切りで要求する権限を記していきますが、必ずopenidを含めるようにしてください。また、サービス毎に固有のscope値が存在する場合があります。
redirect_uri レスポンスが返されるURIです。ここで指定するURIは全く同じものをサービス側にも登録する必要があります。
state リクエスト時とレスポンスを受け取った際に共通で把握できるランダム値です。CSRF対策に使用されます。

そしてリクエストの例が以下となります。

https://server.example.com/authorize?
    response_type=code
    &client_id=s6BhdRkqt3
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20profile
    &state=af0ifjsldkj

認可コードを貰う

無事認証が終わるとリダイレクトされてレスポンスが帰って来ます。
成功時は以下のパラメータが上で指定したredirect_uriの後ろにくっついてきます

名前 説明
code 認可コードです。次のセクションで使います。
state 上で送ったstateがそのまま送られてくるはずです。
全く同じであることを検証してください。

認可コードをトークンエンドポイントに投げる

認可コードだけ貰ってもしょうがないので、これをID TokenとAccess Tokenに交換してもらう必要があります。

まずトークンエンドポイントに関してですが、これも認可エンドポイントと同じようにOpenID Configurationに記載されています。
同じようにGoogleを例にとるとtoken_endpointの値がそれにあたるため、URLは以下になります。

https://oauth2.googleapis.com/token

次にリクエストのパラメータですが、以下を指定する必要があります。

名前 説明
grant_type 権限付与の種別です。ここではauthorization_codeを指定してください。
code 上で受け取った認可コードを指定してください。
redirect_uri 認可時で指定したものと同じものを指定してください。

リクエストの例は以下となります

POST /token HTTP/1.1
  Host: server.example.com
  Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
  Content-Type: application/x-www-form-urlencoded

  grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
  &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

ID TokenとAccess Tokenを貰う

レスポンスとして下記のパラメータが返ってきます

名前 説明
access_token アクセストークン
token_type トークンの種別です。ここでは必ずBearerが返ってきます。
id_token ID トークン

ID Tokenを検証する

最後は返ってきたID Tokenが本物なのかを検証する必要があります。
検証するにあたってID Tokenの構成について知っておく必要があります。

ID TokenはJWT(JSON Web Token)形式の文字列で、ドットで区切られたヘッダ、ペイロード、署名の3つの部分から構成されています。

特にペイロードに関しては以下のパラメータを含んでおり、これらを元に検証を行います。

名前 説明
iss Issuerの識別子
sub ユーザーの識別子
aud トークンの発行対象の識別子
exp トークンの有効期限
iat 発行日時

具体的な手順に関してはそのまま引用する形になってしまうのでこちらを参照してください。

まとめ

かなり駆け足のまとめになってしまい恐縮ですが、以上が一連の流れになります。
本当は軽く実装まで書けるとよかったのですが、この記事を書き終わったのがかなりギリギリで体力の限界でした。
もっと早めから記事を書き始めるべきだったかもしれない……

明日は@yuucuさんになります!

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?