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

みなさん、こんにちは!ネットワークとWebの深淵を愛するインフラアーキテクトです。

日頃からAPIを叩いたり、ログイン認証の仕組みを作ったりしていると、必ず耳にするのが「OIDC(OpenID Connect)」ですよね。「なんだか難しそうな名前だな…」「JWTとかIDトークンとか、アルファベットの呪文がいっぱい出てきて頭がクラクラする!」そんな風に感じていませんか?

大丈夫です。一歩ずつ、身近な例えから紐解いていけば、決して恐ろしいものではありません。今回は、OIDCの心臓部である「IDトークンの構造と、それが偽物ではないかを見破る検証のステップ」を、郵便配達の世界に例えながら優しく解説していきます!

—

1. IDトークンってなに?身近な「手紙」に例えてみよう

Webサイトやアプリで「Googleアカウントでログイン」や「LINEでログイン」といったボタンを押したとき、裏側では何が起きているのでしょうか?

あなたが「私は〇〇です!」と名乗ったとき、認証サーバー(GoogleやLINEなど)は、「この人は間違いなく、我が社が身元を確認した〇〇さんです!」という特別な証明書を発行してくれます。これが、今回主役となるIDトークンです。

これは例えるなら、区役所が発行してくれる「印鑑登録証明書付きの封筒」のようなものです。
中身が誰についてのものか(名前や住所など)が書かれていて、さらに区役所のガッチリとした公印が押されているため、誰も中身を勝手に書き換えることができません。

OIDCの世界では、この「封筒」が JWT(JSON Web Token) という特別な形式で作られています。

—

2. IDトークンの構造:JWTの3層パケットを解剖する

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

[ヘッダー(Header)] . [ペイロード(Payload)] . [署名(Signature)]

この3つのパーツが、それぞれどんな役割を持っているのか、順番に見ていきましょう!一歩ずつ理解していきましょうね。

① ヘッダー(Header):封筒の「表書き(利用する道具の指定)」

ヘッダーには、「この封筒を作るのに、どんなペン(アルゴリズム)を使ったか」という情報が書かれています。

{
  "alg": "RS256", // 署名に使った暗号化のアルゴリズム(RSA + SHA-256)
  "typ": "JWT"    // トークンの種類(これがJWTであることを示す)
}

「あ、今回はこの暗号方式ね」と、受け取る側が最初に確認するためのラベルだと思ってください。

② ペイロード(Payload):手紙の「中身(ユーザーの身分証明)」

ここが一番重要な、ユーザーのプロフィールや「いつまで有効か」といった情報が詰まっている場所です。JSON形式で書かれています。

{
  "iss": "https://accounts.google.com", // 発行者(誰がこの手紙を書いたか)
  "sub": "1234567890",                  // ユーザー固有のID(この世にたった一人の識別子)
  "aud": "my-awesome-app-client-id",    // 対象者(誰宛ての手紙か)
  "exp": 1719830400,                    // 有効期限(いつまでこの手紙が使えるか)
  "iat": 1719826800                     // 発行日時(いつこの手紙が書かれたか)
}

英語の略称が出てくると少し身構えてしまいますが、中身を日本語に訳せばただの「お墨付きのプロフィールカード」です。

③ 署名(Signature):区役所の「割印・公印」

一番大事なのがこの「署名」です。
もし、悪意ある第三者が途中でペイロード(中身)のデータをコソコソと書き換えたとします。そのとき、この署名が「おい、中身が書き換えられてるぞ!」と一発でバレるようにするための、暗号化されたシールの役割を果たします。

—

3. なぜ検証が必要なの?〜ネットワークの安全を守る関所〜

さて、発行者からあなたのアプリにこのIDトークンが届きました。
「やったー!ログイン成功だ!」と、そのまま信じて中身を読んでしまうのは、実はインフラエンジニアとしては大NG(重大なセキュリティホール)です。

なぜなら、ネットワークの途中で誰かが偽物のトークンを送りつけてきたり、とうに期限切れになった古いトークンを使い回しているかもしれないからです。

ここで、アプリ側(受け取る側)で必ず行うべき「3つの検証チェックポイント」を整理しましょう。

1. 発行者(iss)のチェック:本当に信頼できる機関(例: Google)から届いたものか?
2. 対象者(aud)のチェック:その手紙、本当に「うちのアプリ宛て」のものか?(他のアプリ宛ての使い回しじゃないか?)
3. 有効期限(exp)のチェック:タイムリミットが切れていないか?(過去の古い切符になっていないか?)
4. 署名の検証:中身が途中で改ざんされていないか、公開鍵を使って数学的に裏付ける。

—

4. 実装コードで見る!IDトークンの検証ロジック(Python版)

百聞は一見に如かず。実際にPythonの代表的なライブラリ PyJWT を使って、IDトークンを安全に検証するコードを見てみましょう。実務のWebアプリケーションでもそのまま参考にできる書き方になっています。

import jwt
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError
import requests

def verify_id_token(id_token: str, client_id: str):
    """
    受け取ったIDトークンが本物か、安全に検証する関数です。
    """
    try:
        # 1. 署名検証に必要な「公開鍵」をGoogleなどの発行者から事前に取得する想定
        # (実際にはJWKSエンドポイントから取得しますが、ここでは簡略化しています)
        issuer_url = "https://accounts.google.com"
        
        # 2. PyJWTライブラリを使って、署名・有効期限・宛先などを一気に検証します
        # ここで `exp` や `aud` のチェックも自動で行われます!
        decoded_payload = jwt.decode(
            id_token,
            options={
                "verify_signature": True, # 署名の改ざんチェックを行う
                "verify_exp": True,       # 有効期限切れになっていないかチェックする
                "verify_aud": True        # 当て先(クライアントID)が合致するかチェックする
            },
            audience=client_id,           # 自アプリのクライアントIDを指定
            issuer=issuer_url,            # 期待する発行者を指定
            algorithms=["RS256"]          # 許可するアルゴリズム
        )
        
        print("検証成功!安全なIDトークンです。")
        print(f"ログインしたユーザーのID (sub): {decoded_payload.get('sub')}")
        return decoded_payload

    except ExpiredSignatureError:
        # 有効期限が切れていた場合の例外処理
        print("エラー: IDトークンの有効期限が切れています。再ログインが必要です。")
        return None
        
    except InvalidTokenError as e:
        # 署名が不正、または中身が改ざんされていた場合の例外処理
        print(フローerr("エラー: 不正なIDトークンです(改ざんの可能性があります): %s", e))
        return None

コード内のコメントにも書いた通り、ライブラリが自動的に exp(有効期限)や aud(宛先)、そして 署名(Signature) のつじつまを隅々までチェックしてくれます。これなら、ネットワークの海を渡ってきた怪しいパケットからも、しっかりとアプリケーションを守ることができますよね。

—

5. まとめ

今回は、OIDCにおけるIDトークンの構造と、安全性を担保するための検証ロジックについて解説しました。

  • IDトークン は、ユーザーの身分を証明する「区役所の公印付きの封筒(JWT)」のようなもの。
  • 構造は [ヘッダー].[ペイロード].[署名] の3つのドット区切りでできている。
  • アプリで受け取ったときは、「発行者(iss)」「対象者(aud)」「有効期限(exp)」、そして「署名」の検証 を必ず行うのが鉄則。

インフラやセキュリティの世界は、一見すると難解な用語のオンパレードですが、一つひとつの部品が「現実世界のどんな仕組みに対応しているのか」を紐解いていくと、非常に美しく合理的にできていることが分かります。

ぜひ、日々の開発やインフラ設計の現場で、この「パスポートと関所の関係」を思い出して安全な認証基盤を築いていってくださいね!それではまた次回の技術解説でお会いしましょう。

コメント

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