【入門編】 OpenID Connect (OIDC)におけるIDトークンの構造と検証 – Web APIアーキテクチャ・データ連携実践ガイド

Webの世界の「通行手形」:OpenID ConnectのIDトークンを解き明かす

こんにちは!ネットワークとプロトコルの深淵を愛するインフラアーキテクトです。

今日は、Web APIの認証における「最強の身分証明書」こと、OpenID Connect (OIDC) の IDトークン についてお話しします。

「認証」や「トークン」と聞くと、なんだか暗号のような数字の羅列を想像して身構えてしまいますよね。でも大丈夫。実はこれ、皆さんが毎日手にしている「郵便物」や「会員証」と全く同じ仕組みで動いているんです。

一歩ずつ、パケットの裏側を覗きながら紐解いていきましょう!

—

1. IDトークンは「信頼できる第三者の証明書」

Webの世界では、サーバーとクライアントが離れた場所にいます。相手が本当に「本人」なのかを確認するために、信頼できる第三者(GoogleやAuth0のような認証サーバー)から発行された「IDトークン」を、パスポートのように使います。

このIDトークンは、JWT (JSON Web Token) という形式で書かれています。中身はただのJSONデータですが、改ざんされないように「署名」という封蝋(ふうろう)が施されているのが特徴です。

—

2. IDトークンの中身:5つの重要クレーム

IDトークンの中には、必ず含まれている「クレーム(主張)」と呼ばれる項目があります。これらは、まさに身分証明書に書かれた氏名や住所のようなものです。

  • iss (Issuer):発行元。「誰がこの証明書を作ったか」。信頼できる認証局の名前です。
  • sub (Subject):利用者ID。「誰のものか」。そのユーザーを一意に特定する背番号です。
  • aud (Audience):宛先。「誰に向けたものか」。このトークンを受け取っていいサービス(クライアントID)が指定されています。
  • exp (Expiration time):有効期限。「いつまで有効か」。郵便物の消印と同じで、期限を過ぎたものは無効です。
  • iat (Issued At):発行日時。「いつ発行されたか」。古すぎるトークンを排除するために使います。

これらがあるおかげで、サーバーは「このトークンは本物か?」「期限は切れていないか?」「うちのサービス宛か?」を瞬時に判断できるわけです。

—

3. 署名検証:手紙の封蝋を確かめるプロセス

IDトークンが改ざんされていないことを確認する作業を「署名検証」と呼びます。ここが一番の難所ですが、郵便に例えると簡単です。

1. 公開鍵の取得:認証サーバーは /.well-known/openid-configuration というURLで、自分の「ハンコ(公開鍵)」を公開しています。
2. 鍵のダウンロード:クライアントは、まずこのURLから鍵のリスト(JWKS)をダウンロードします。
3. 照合:トークンに付いている「署名」と、ダウンロードした「公開鍵」を照らし合わせます。もしデータが1ビットでも書き換えられていれば、パズルが合わなくなり「偽物だ!」と弾かれます。

—

4. 実務で役立つ検証のコード例 (Python)

実際にサーバーサイドでトークンを検証する際は、PyJWT のようなライブラリを使うのが一般的です。泥臭い計算を自前でする必要はありません。

import jwt
import requests

# 1. 認証サーバーから公開鍵(JWKS)を取得する
jwks_url = "https://accounts.google.com/.well-known/jwks"
jwks = requests.get(jwks_url).json()

# 2. 受信したIDトークンを検証する
token = "eyJhbGciOiJSUzI1Ni..." # クライアントから送られてきたIDトークン
header = jwt.get_unverified_header(token) # どの鍵を使うかヘッダーを確認
key = next(k for k in jwks['keys'] if k['kid'] == header['kid'])

# 3. 公開鍵を使って検証!
# iss, aud, exp はライブラリが自動でチェックしてくれます
decoded_token = jwt.decode(
    token,
    key=jwt.algorithms.RSAAlgorithm.from_jwk(key),
    algorithms=["RS256"],
    audience="あなたのクライアントID",
    issuer="https://accounts.google.com"
)

print(f"ようこそ、ユーザーID: {decoded_token['sub']} さん")

—

まとめ:ネットワークは「信頼」でできている

いかがでしたか?IDトークンは単なる文字列ではなく、インターネットという広大なネットワーク上で「私たちは他人同士だけど、この証明書があるから信頼し合えるよね」という約束事の塊なんです。

  • iss で発行元を確認し、
  • exp で期限を守り、
  • 公開鍵 で改ざんがないか封蝋を確認する。

この一連の流れを理解しておけば、万が一認証エラーが起きても「期限が切れているのかな?」「公開鍵の取得に失敗しているのかな?」と、パケットの行方を追うような冷静なトラブルシューティングができるようになります。

プロトコルの深淵は、意外と身近なところに繋がっています。ぜひ、皆さんの開発環境でも jwt.io などのサイトを使って、実際のトークンの中身を覗いてみてください。新しい世界が見えてくるはずですよ!

コメント

タイトルとURLをコピーしました