こんにちは!ネットワークやAPIの世界へようこそ。インフラアーキテクトの私です。
日々のWeb開発やインフラ構築で、GoogleやLINEなどの「ソーシャルログイン」を使ったことはありませんか?「別のサービスのIDを使って、パスワードを入力せずにログインする」あの便利な仕組みの裏側では、OpenID Connect (OIDC) というプロトコルが静かに、しかし力強く働いています。
そのOIDCの主役とも言えるのが、今回お話しする「IDトークン」です。
「JWT?署名?RS256?なんだか英語ばかりで難しそう……」と思った方もいらっしゃるかもしれません。大丈夫です!今回は、小難しい専門用語をいったん脇に置いて、私たちが普段使っている「郵便配達の仕組み」に例えながら、一歩ずつ優しく紐解いていきましょう。
—
1. IDトークンってそもそも何?現実世界に例えてみよう
突然ですが、あなたは高級マンションの管理人さんだと想像してください。
そこに、見知らぬ青年が「私はこのマンションの301号室に住む田中です。合鍵をください」とやってきました。
さて、あなた(管理人さん)はどうしますか?
「本当に301号室の田中さんですか?免許証で見せてください!」と確認しますよね。もし、その青年が手書きのメモで「私は田中です」と書いた紙を見せても、信用できません。誰でも偽造できるからです。
この「身分証明書」のデジタル版こそが、OIDCにおけるIDトークンです。
IDトークンは、信頼できる認証局(GoogleやAuth0など、いわば「お墨付きを与えてくれる公的機関」)が発行するデジタル証明書です。中身は JWT (JSON Web Token) という形式で書かれており、ドット(.)で区切られた3つのパート(ヘッダー・ペイロード・署名)からできています。
今回はその中身でも最も重要な、「ペイロード(中身のデータ)」のチェック項目と、「署名(消えないスタンプ)」の確認手順を見ていきましょう。
—
2. 郵便配達で理解する!IDトークンに含まれる5つの重要クレーム
IDトークンのペイロード(中身)には、そのユーザーが誰であるかを証明するための情報が詰め込まれています。これを「クレーム(主張)」と呼びます。
代表的な5つのクレームを、手紙の封筒に例えて確認していきましょう。
1. iss (Issuer / 発行者)
- 例:
https://accounts.google.com - 意味:「誰がこの手紙を書いたのか?」(差出人の消印です)
- 偽物の手紙ではないか、信頼できる発行者かどうかを確認します。
2. sub (Subject / 主体・ユーザーID)
- 例:
1092837465019283 - 意味:「この手紙は誰宛て(誰について)のものか?」
- サービス側でユーザーを特定するための、世界で唯一のID番号です。
3. aud (Audience / 宛先)
- 例:
my-awesome-app-client-id - 意味:「誰に向けられた手紙か?」
- あなたのアプリ宛てに発行されたものかを確認します。もし別のアプリ宛ての手紙だったら、受け取ってはいけません。
4. exp (Expiration Time / 有効期限)
- 例:
1711929600(Unix時間) - 意味:「いつまで有効か?」
- 生鮮食品と同じように、IDトークンにも賞味期限があります。期限切れのトークンはゴミ箱行きです。
5. iat (Issued At / 発行日時)
- 例:
1711926000 - 意味:「いつ作られたものか?」
- あまりに過去すぎるものや、未来の日時になっているものは不正の可能性を疑います。
—
3. 改ざんを防ぐ!「署名(RS256)」の秘密
さて、中身が正しくても、悪意あるユーザーがこっそり中身を書き換えていたら大変です。ここで登場するのが署名(Signature)です。
IDトークンの最後尾(3つ目のパーツ)には、発行者だけが持つ「秘密のハンコ(秘密鍵)」で押された暗号のスタンプがついています。代表的なアルゴリズムが RS256 です。
- R(RSA): 暗号化の仕組みの名前です。
- 256: ハッシュ関数のビット数(安全性を示す目安)です。
RS256の素晴らしいところは、「ハンコを押す鍵(秘密鍵)」と「ハンコが本物か検証する鍵(公開鍵)」が別々になっている点です。
アプリ側(検証する側)は、発行者がネット上に公開している「公開鍵」を使って、「おっ、このスタンプは本物のGoogleのハンコだな!」と安全に確かめることができます。アプリ側が秘密鍵を持つ必要はないため、万が一アプリがハッキングされても安全性が保たれるのです。
—
4. 実践!IDトークンの検証ステップ(Pythonコード例)
理論がわかったところで、実際のアプリケーション(バックエンド)でどのようにIDトークンを検証するのか、Pythonのコードで見てみましょう。
世の中には便利なライブラリ(Pythonなら PyJWT など)がありますので、これらを使って先ほどの5つのチェックをプログラムに代行させます。
import jwt
from jwt import PyJWKClient
# 1. 発行者が公開している「公開鍵(JWKS)」のURLを指定します
jwks_url = "https://www.googleapis.com/oauth2/v3/certs"
jwk_client = PyJWKClient(jwks_url)
# ユーザーから送られてきたIDトークン(例)
id_token = "eyJhbGciOiJSUzI1NiIsImtpZCI..."
try:
# トークンのヘッダーから「どの鍵で署名されたか」を特定し、適切な公開鍵を取得する
signing_key = jwk_client.get_signing_key_from_jwt(id_token)
# 2. 署名の検証と、各クレーム(iss, aud, expなど)の自動チェックを行う
payload = jwt.decode(
id_token,
signing_key.key,
algorithms=["RS256"], # 署名アルゴリズムの指定
audience="あなたのアプリのクライアントID", # aud のチェック
issuer="https://accounts.google.com" # iss のチェック
)
# 検証成功!中身を取り出す
user_id = payload["sub"]
print(f"認証成功!ようこそ、ユーザーID: {user_id} さん!")
except jwt.ExpiredSignatureError:
print("エラー: IDトークンの有効期限が切れています。再ログインしてください。")
except jwt.InvalidAudienceError:
print("エラー: 宛先(aud)が一致しません。このアプリ宛てのトークンではありません。")
except jwt.PyJWTError as e:
print(f"エラー: IDトークンの検証に失敗しました。不正なデータの可能性があります: {e}")
コードのポイント
ライブラリを使うことで、exp(有効期限)のチェックや、公開鍵を用いた RS256 の署名検証、さらには iss や aud の突合をたった数行で行うことができます。実務でも、自前で暗号計算を書くのではなく、こうした信頼できるライブラリの検証機能を正しく設定して使うのが鉄則です。
—
5. まとめ
いかがでしたでしょうか?
OIDCのIDトークンと闻くと難しく感じますが、要するにこういうことです。
1. 信頼できる発行者(iss)が作った
2. 宛先(aud)は自分のアプリで
3. 有効期限(exp)内であり
4. 主(sub)が誰だかはっきりしていて
5. 公開鍵を使った署名(RS256等)で、改ざんされていないことが証明されている
この5つの関門をしっかりとプログラムでチェックしてあげることで、安全で快適なAPI連携やシングルサインオンの仕組みが成り立っています。
現場のインフラやセキュリティ設計でOIDCを扱う際は、ぜひ今回の「郵便配達と身分証明書」の比喩を思い出してみてくださいね。それでは、また次回の技術解説でお会いしましょう!
コメント