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?

OIDC実装のために、認証フローをGoogle・自作アプリに当てはめて理解する

0
Last updated at Posted at 2025-12-24

image.png

はじめに

そろそろ表面上の理解から脱却しOIDCを腹落ちさせたい、と思いPythonで処理を実装してみることにしました。

本記事は実装前に、ChatGPTの助けを借りながら OpenID Connect Core 1.0 日本語訳 を読んで認証フローを整理したものになります。IdP側の処理については省略している部分がありますのでご了承ください。

2025/12/24 時点
本記事にPythonの実装内容は含まれません
実装の過程で誤りなどに気づいた場合、本記事の内容を訂正する可能性があります

概要

OIDC(OpenID Connect)は OAuth 2.0を拡張した認証プロトコルです。OpenID Connect Coreでは、以下と説明されています。

Client が Authorization Server の認証結果に基づいて End-User のアイデンティティを検証可能にする.

本記事では、Client = Pythonアプリ、Authorization Server = Google、End-User = アプリのユーザーとなります。この場合、Googleは一般的にIdP(Identity Provider)と表現されることもありますが、今回はドキュメントの記載に従ってAuthorization Serverとします*。

*より正確には、OpenID Provider (OP)と表現されます

認証フロー(Googleとアプリと私)

OIDCの認証フローについて、以下の登場人物の間でどのようなやりとりが発生するのかざっくり流れを整理します。

  • ユーザー(私):ログインしたい
  • アプリ(Client):ユーザーの認証を行いたい
  • Google(Authorization Server):認証を行い、その結果をアプリに返す

OIDCの大まかな流れは以下になります。

No 通信元 → 通信先 内容
0 ユーザー → アプリ ユーザーはアプリ上で「Googleでログイン」を行う
1 アプリ → Google アプリがGoogleに認証リクエストを送信し、ユーザーをGoogleへリダイレクトする
2 ユーザー → Google ユーザーはGoogleアカウントでログイン(認証)を行う
3 Google → アプリ 認証後、Googleがアプリに認可コードを返す
4 アプリ → Google アプリは認可コードをGoogleに送り、IDトークンとアクセストークンをリクエストする
5 Google → アプリ Googleは認可コードを検証し、IDトークンアクセストークンをアプリに返却する
6 アプリ 取得したIDトークンを検証する
7 アプリ → Google
(オプション)
取得したアクセストークンを使ってユーザー情報をリクエストする
8 Google → アプリ
(オプション)
アクセストークンを検証し、ユーザー情報を返却する

※厳密には No.1 以降がOIDCの認証フローとして定義されています

OpenID Connect Coreに登場する用語

Pythonでアプリ側の処理を実装するために、次のセクションではより具体的な処理に落とし込んでいきます。この時、エンドポイントやらトークンやら複数登場しますので、先に用語を整理しておきます。

なお、この表には本記事では特に登場しない用語も含みます。OpenID Connect Coreを読むにあたり、自分用にメモした内容ですので、ドキュメントを読まれる方の参考になればと思い残しています。

用語 意味
Authorization Server 認証を行い、認可を発行したあとアクセストークンを発行するサーバー
OP (OpenID Provider) 認証を行えるAuthorization Serverのこと
Client 保護されたリソースへのリクエストを代理で行うアプリケーション
User Agent デバイス上でClientを実行させるもの。Webブラウザーなどを指す
RP (Relying Party) OpenID Providerにリクエストを行うClient
認可エンドポイント
(Authorization Endpoint)
認証のリクエスト先
OpenID Providerが提供する
ディスカバリーエンドポイント 各種エンドポイントなど、OpenID Providerの設定情報を公開するエンドポイント
OpenID Providerが提供する
認可コード
(Authorization Code)
OpenID Providerによる認証後、発行されるコード
トークンエンドポイント
(Token Endpoint)
認可コードの送信先であり、IDトークン・アクセストークンのリクエスト先
OpenID Providerが提供する
IDトークン 認証結果を示すJWT
アクセストークン 認可を表す文字列

認証フローの詳細

OIDCの認証フローとして、以下の3種類が定義されています。今回は、標準的に利用されている「**Authorization Code Flow」を取り扱います。

  • Authorization Code Flow
  • Implicit Flow
  • Hybrid Flow

では、登場人物のやりとりを詳細化しながら、実装方法について整理していきます。

⓪ ユーザー → アプリ

ユーザーがログインページにアクセスし、「Googleでログイン」ボタンをクリックする

① アプリ → Google

ユーザーがGoogleアカウントでの認証を選択したら、アプリはGoogleに対して 「認証リクエスト」を作成・送信します。

「認証リクエスト」は、Googleの「認可エンドポイント(URL)」に対して必要なリクエストパラメータを含めた形で送信されます。認証はユーザーとGoogle間で直接行われるため、アプリは「認証リクエスト」の送信と同時に、ユーザーに表示する画面を「認可エンドポイント」にリダイレクトします。

以下は、アプリからのリダイレクトレスポンスの例です。

HTTP/1.1 302 Found
Location: <認可エンドポイント>?    #以降リクエストパラメータ
    response_type=code
    &scope=openid%20profile%20email
    &client_id=s6BhdRkqt3
    &state=af0ifjsldkj
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

アプリの実装処理:「認証リクエスト」の作成・送信
→ 認可エンドポイント・リクエストパラメータをもとに、ユーザーをリダイレクトするURLを生成

アプリが「認証リクエスト」を作成するためには「認可エンドポイント」のURLを事前に知っている必要があります。Googleの場合、「ディスカバリードキュメント」にアクセスすることで、「認可エンドポイント」のURLを取得できます。

ディスカバリードキュメントのURLは以下で固定されています。

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

{IdPごとの固有の値}/.well-known/openid-configuration は一般的にディスカバリーエンドポイントと呼ばれ、他のIdPでもディスカバリーエンドポイントにアクセスすることで、各種エンドポイントのURLなどを知ることができます。

②ユーザー → Google

ユーザーは認可エンドポイントにリダイレクトされ、Googleのログイン画面で認証を行います。アプリはユーザーの認証情報を扱いません

このときGoogleはユーザーに対して、「ユーザーのデータをアプリに送信すること」の同意を得ます。この同意を得るプロセスもOIDCのフローに含まれています。

③ Google → アプリ

認証が成功すれば、Googleはアプリに認可コードを返却します。このとき、ユーザーの表示画面もアプリの画面に戻ります。

以下は、Googleからのレスポンスの例です。

HTTP/1.1 302 Found
Location: <アプリのリダイレクト先>
  ?code=<認可コード>
  &state=TH25QRQHJJC16YY7AKNS

④ アプリ → Google

アプリはGoogleから受け取った認可コードをGoogleに送信して、IDトークン・アクセストークンとの交換をリクエストします。

具体的には、Googleの「トークンエンドポイント」に対して、「認可コード」を送信します。このアプリからGoogleへのリクエストを「トークンリクエスト」と呼びます。

以下はトークンリクエストの例です。

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

grant_type=authorization_code&code=<認可コード>
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

アプリの実装処理:「トークンリクエスト」の作成・送信
→ トークンエンドポイントに対して、認可コードを含めたHTTPリクエストを行う

⑤ Google → アプリ

Googleでは認可コードの検証を行い、検証が成功したらアプリに対してIDトークンアクセストークンを返却します。

以下はレスポンスの例です。

  HTTP/1.1 200 OK
  Content-Type: application/json
  Cache-Control: no-store
  Pragma: no-cache

  {
   "access_token": "SlAV32hkKG",
   "token_type": "Bearer",
   "refresh_token": "8xLOxBtZp8",
   "expires_in": 3600,
   "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
     yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
     NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
     fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
     AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
     Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
     NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
     QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
     K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
     XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
  }

IDトークンはJWT(JSON Web Token)形式であり、JSON形式のデータをBASE64URLエンコードしています。IDトークンにはGoogleが管理するユーザー属性が含まれており、デコードすることでアプリはこれらのユーザーデータを使用できます。

アクセストークンは、Googleに対して追加でユーザー情報をリクエストする場合に使用します(フロー⑦,⑧)。

⑥ アプリ

アプリはIDトークン(JWT)をデコードし、その内容について検証します。検証内容は以下のように複数ありますが、Pythonの場合はAuthlibなどのライブラリで検証用モジュールが用意されています。

image.png
出典: 3.1.3.7. ID Token Validation

Authlibでは、JWT実装のために以下のようなモジュールを提供しています。

  • decode(id_token, public_key) :JWTのデコードを行う
  • validate(payload, header) :IDトークン(JWT)のペイロードを検証する

アプリの実装処理:「IDトークン」の検証
→ JWTは標準規格のため、Pythonのライブラリで用意されているモジュールを使用できる

まとめ

本記事で整理した内容により、AIに生成させたPythonコードをチェックできるくらいの理解にはなったかなと個人的には思います。ClientとUser Agentをひとまとめに「アプリ」と表現したり、IdP側の処理を割愛したり、詳しい方が読むとツッコミどころが多いかもしれませんが、明らかな誤りがあればご指摘いただけると幸いです。あと、Authorization Codeの訳は認可コードと認証コード、どちらが適切なのでしょうか…

さて、Pythonによる実装編の投稿に向けて頑張りたいと思います。

参照ドキュメント

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?