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

こんにちは!ネットワークの世界やAPIの仕組みに足を踏み入れたばかりの頃って、次から次へと出てくるカタカナ用語や暗号みたいな文字列に、ちょっと圧倒されてしまいますよね。

「なんだか難しそう……」と感じるかもしれませんが、大丈夫です!一歩ずつ、身近な例えを交えながら優しく紐解いていきましょう。

今回は、モダンなWebサービスやスマホアプリのログイン画面で大活躍している OpenID Connect (OIDC) の心臓部、「IDトークン」 の正体に迫ります。

—

1. IDトークンってなに? 身近な「身分証明書」に例えてみよう

私たちがホテルのチェックインをするときや、お酒を買うとき、年齢や本人確認のために「身分証明書(運転免許証やパスポートなど)」を提示しますよね。

Webの世界でも同じです。例えば、「Aという写真シェアアプリ」でログインするとき、わざわざ新しくパスワードを作らなくても、「Googleアカウントでログイン」というボタンを押すだけで、簡単に入ることができますよね。あのとき、Google(身分を証明する人)がAアプリに対して「このユーザーは、間違いなく〇〇さんですよ!」と渡してくれるデジタルな身分証明書こそが、IDトークンなんです。

このIDトークン、実の中身は JWT (JSON Web Token) という、ちょっとお洒落なコンパクトな形式でできています。見た目は eyJhbGciOiJSUzI1... のように、意味不明な文字列がドカンと並んでいるだけで、一見するとただの暗号の塊に見えます。

でも、恐れることはありません。中身をほどいてみると、ちゃんと人間にも読める大切な情報がギュッと詰まっているんですよ。

—

2. IDトークンの構造を覗いてみよう(3つのパーツ)

JWT形式のIDトークンは、ドット (.) で区切られた3つのパーツでできています。

1. ヘッダー (Header): 「この身分証明書は、どういう仕組み(アルゴリズム)で作られたものか」という封筒の種類を表す部分です。
2. ペイロード (Payload): 中身のデータ本体です。「誰が発行したのか」「誰宛のものか」「いつまで有効か」といった重要な情報(これらを専門用語でクレームと呼びます)が書かれています。
3. シグネチャー (Signature): 改ざんされていないことを証明する「発行元のサイン(印鑑)」です。

今回はこの中でも、実務で絶対に知っておくべきペイロードの中身(クレーム)と、シグネチャーによる改ざん検知の仕組みに絞って見ていきましょう!

—

3. ペイロード(クレーム)の主要メンバーたち

IDトークンのペイロードの中身を、郵便配達の封筒に例えて見てみましょう。ここに書かれている代表的な5つのクレーム(項目)がこちらです。

  • iss (Issuer): 発行者。誰がこの身分証明書を作ったのか(例: https://accounts.google.com)。
  • sub (Subject): 主体。この身分証明書の持ち主の「ID(識別子)」。名前が変わってもこのIDは変わりません。
  • aud (Audience): 宛先。誰に向けて作られた身分証明書か(例: アプリのクライアントID)。
  • exp (Expiration Time): 有効期限。いつまでこの証明書が使えるか(UNIX時間で記録されています)。
  • iat (Issued At): 発行日時。いつこの証明書が作られたか。

実際に、プログラムでデコードしたIDトークンのペイロード(JSONデータ)を覗いてみると、このような形をしています。

{
  "iss": "https://identity.example.com", 
  "sub": "user_123456789",               
  "aud": "my-awesome-web-app",           
  "exp": 1711929600,                     
  "iat": 1711926000,                     
  "name": "山田 太郎",
  "email": "yamada@example.com"
}

なんだかスッキリしていて分かりやすいですよね!「あ、この手紙はあの認証サーバーから出て、うちのアプリ宛てで、今日の〇時まで有効なんだな」と一目でわかります。

—

4. 署名検証:悪者による「偽造」を防ぐ仕組み

さて、ここで一つの疑問が浮かびます。
「もし、悪意あるユーザーがこのJSONデータを自分のパソコンでこっそり書き換えて、name を『大富豪』に書き換えたり、exp(有効期限)を何十年後かに書き換えたりしたら、アプリは騙されちゃうんじゃないの?」と。

ここで登場するのが、3つ目のパーツである「シグネチャー(署名)」です。

郵便の「赤いロウの封印」をイメージしてね

大昔の手紙には、差出人が本物であることを証明するために、溶かした赤いロウに自分の指輪や印章を押し付けて「封印」しましたよね。もし途中で誰かが手紙を勝手に開けて中身を書き換えようものなら、このロウの封印がバリッと割れて、偽造が一発でバレてしまいます。

IDトークンの署名も全く同じです。
発行者(Googleなどの認証サーバー)は、自分だけが持っている「秘密鍵」を使って、ヘッダーとペイロードを混ぜ合わせたデータに特殊な暗号のハンコ(署名)を押します。

アプリ側は、発行者があらかじめ公開している「公開鍵」を使って、「このハンコ、本当にあの発行者のものに間違いないかな?」と検証します。

もし、悪意あるユーザーがペイロードの数値を1文字でも書き換えたらどうなるでしょうか?
そう、ハンコ(署名)のデータと中身の辻褄がピタッと合わなくなるため、アプリ側は「おや、このトークン、途中で誰かにいじられたな(改ざんされているな)!」と瞬時に気づき、アクセスをシャットアウトできるのです。

—

5. 実装でチェックすべき「IDトークン検証」の基本ステップ

それでは、私たちが開発するWebアプリやAPIサーバーで、IDトークンを受け取ったときに何をすべきか、その検証手順をコードのイメージと一緒に見ていきましょう!

実務では、自前で暗号計算のプログラムを書く必要はほとんどありません。世界中で信頼されているライブラリ(Pythonなら PyJWT や authlib など)が用意してくれています。ただし、「ライブラリに何をチェックさせるべきか」という手順の理解はエンジニアの必須科目です。

以下に、Pythonを使った検証処理のイメージコードを載せます。日本語のコメントを参考にしてください。

import time
import jwt
from jwt import PyJWKClient

# 1. 発行者の公開鍵が置いてあるURL(JWKSエンドポイント)を指定
jwks_url = "https://identity.example.com/.well-known/jwks.json"
jwk_client = PyJWKClient(jwks_url)

# 2. クライアントから受け取ったIDトークンの文字列
id_token = "eyJhbGciOiJSUzI1NiIs..."

try:
    # 3. 署名検証で使われる公開鍵を自動で取得する
    signing_key = jwk_client.get_signing_key_from_jwt(id_token)

    # 4. トークンの検証を実行(署名、有効期限、発行者、宛先を同時にチェック!)
    payload = jwt.decode(
        id_token,
        signing_key.key,
        algorithms=["RS256"],  # 許可する暗号アルゴリズム
        audience="my-awesome-web-app",  # aud が自社アプリ宛てか?
        issuer="https://identity.example.com"  # iss が信頼できる発行者か?
    )

    # 検証成功!ペイロードからユーザーの情報を安全に取り出す
    print(f"ログイン成功!ようこそ、{payload['name']} さん")
    print(f"ユーザーID: {payload['sub']}")

except jwt.ExpiredSignatureError:
    # exp を過ぎている場合のエラー処理
    print("エラー: IDトークンの有効期限が切れています。再ログインしてください。")

except jwt.InvalidTokenError as e:
    # 署名がおかしい、または改ざんされている場合のエラー処理
    print(f"エラー: 不正なIDトークンです(改ざんの可能性があります): {e}")

現場で絶対に外してはいけないチェック項目

コード内でも行っていますが、検証時は以下のポイントを必ずプログラムに強制させてください。

1. 署名の検証: 発行者の公開鍵で、改ざんがないことを必ず確認する。
2. 有効期限 (exp) のチェック: 期限切れの古いトークンが使われていないか確認する(多くのライブラリは自動でやってくれます)。
3. 発行者 (iss) のチェック: 想定している信頼できる認証サーバーから発行されたものか確認する。
4. 宛先 (aud) のチェック: 「他のアプリ宛てに発行されたIDトークン」を、自分のアプリに持ち込まれていないか(なりすまし対策)を確認する。

—

まとめ

いかがでしたでしょうか?
一見すると難解な呪文のように見えるIDトークンも、「デジタルな身分証明書」というロールモデルで捉えれば、中身のクレーム(身元情報)も、署名(改ざん防止のハンコ)も、すべて私たちが現実世界で無意識に行っている安全確認の仕組みと同じであることが分かりますよね。

インフラやセキュリティの世界は、こうした「現実世界の安心・安全の仕組み」をデジタルに置き換えたものがたくさんあります。一つひとつのパーツの意味を優しく解きほぐしていけば、決して怖くありません。

ぜひ今日の知識を武器に、セキュアで美しいAPI設計や認証基盤の構築に自信を持ってチャレンジしてみてくださいね!

コメント

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