はじめに:静的認証ポリシーの限界と新たな選択肢
ユーザー認証はもはや単なる「ログイン成功/失敗」ではなく、そのセッションがどれだけ安全かを評価する時代です。パスワード漏洩、セッションハイジャック、アカウント乗っ取りといった攻撃がますます巧妙化する中、すべてのリクエストを同じ信頼レベルで処理する従来の方法は危険です。
Googleはこの問題に対処するため、**Sign in with Googleにセッションメタデータクレーム(auth_time, amr)**を新たに導入しました。これらのクレームはIDトークンに含まれ、バックエンドシステムがユーザーの認証時刻と認証方法を把握できるようにします。これにより、より動的でリスクベースのアクセス制御を実装できます。
この記事では、2つのクレームの意味と活用法、そして実際のサービスに適用する際の考慮点を解説します。
本論1: auth_timeとamrクレームの理解
auth_time (認証時刻)
auth_timeは、ユーザーがGoogleアカウントに最後に認証した時刻を示します。この値は**セッションの鮮度(freshness)**を判断する重要な指標です。例えば、ユーザーが1時間前にGoogleにログインしたなら、そのセッションは比較的最近検証されたと見なせます。
amr (認証方法参照)
amrは、ユーザーが認証時に使用した方法を示す値です。主な値は以下の通りです。
pwd: パスワード使用mfa: 多要素認証(MFA)チャレンジ完了hwk: ハードウェアセキュリティキー使用swk: ソフトウェアセキュリティキー使用tel: 電話認証sms: SMS認証
これらの値を組み合わせることで、認証の強度を正確に評価できます。例えば、hwk が含まれていれば、ハードウェアキーによる強力な認証であることがわかります。
実際のコード例
OIDC標準に従い、IDトークンにクレームを要求する方法は簡単です。以下は認証リクエストURLの例です。
# 認証リクエストURLの例 (Pythonコードではなく、URL構成例)
# claimsパラメータでamrとauth_timeを必須として要求します。
auth_url = (
"https://accounts.google.com/o/oauth2/v2/auth?"
"response_type=id_token&"
"client_id=YOUR_CLIENT_ID&"
"scope=openid email profile&"
"redirect_uri=https://example.com/user-login&"
"nonce=RANDOM_VALUE&"
"claims={\"id_token\": {\"amr\": {\"essential\": true}, \"auth_time\": {\"essential\": true}}}"
)
print(auth_url) # 実際のリクエスト時はこのURLにリダイレクト
このように要求すると、IDトークンに amr と auth_time が含まれて渡されます。バックエンドではJWTデコード後、これらの値を抽出してポリシーに利用できます。
# バックエンドでのIDトークンデコード例 (jwtライブラリ使用)
import jwt
# トークン検証後、クレームを抽出
decoded = jwt.decode(id_token, options={"verify_signature": False})
auth_time = decoded.get("auth_time")
amr = decoded.get("amr")
# 例: 機密操作の前にamrにmfaが含まれているか確認
if "mfa" not in amr:
raise PermissionError("MFA認証が必要です。")
リスクベースアクセス制御の実装アイデア
- 機密操作への段階的認証(Step-up)適用:
auth_timeが古い場合、パスワード変更や決済などの機密操作の前に追加認証を要求できます。 - 管理者機能へのアクセス制限:
amrにhwkまたはmfaが含まれない場合、管理者機能へのアクセスを拒否できます。 - 監査ログの記録:
amr値を記録し、どの認証方法でアクセスしたかを追跡できます。

本論1: auth_timeとamrクレームの理解
auth_time (認証時刻)
auth_timeは、ユーザーがGoogleアカウントに最後に認証した時刻を示します。この値は**セッションの鮮度(freshness)**を判断する重要な指標です。例えば、ユーザーが1時間前にGoogleにログインしたなら、そのセッションは比較的最近検証されたと見なせます。
amr (認証方法参照)
amrは、ユーザーが認証時に使用した方法を示す値です。主な値は以下の通りです。
pwd: パスワード使用mfa: 多要素認証(MFA)チャレンジ完了hwk: ハードウェアセキュリティキー使用swk: ソフトウェアセキュリティキー使用tel: 電話認証sms: SMS認証
これらの値を組み合わせることで、認証の強度を正確に評価できます。例えば、hwk が含まれていれば、ハードウェアキーによる強力な認証であることがわかります。
実際のコード例
OIDC標準に従い、IDトークンにクレームを要求する方法は簡単です。以下は認証リクエストURLの例です。
# 認証リクエストURLの例 (Pythonコードではなく、URL構成例)
# claimsパラメータでamrとauth_timeを必須として要求します。
auth_url = (
"https://accounts.google.com/o/oauth2/v2/auth?"
"response_type=id_token&"
"client_id=YOUR_CLIENT_ID&"
"scope=openid email profile&"
"redirect_uri=https://example.com/user-login&"
"nonce=RANDOM_VALUE&"
"claims={\"id_token\": {\"amr\": {\"essential\": true}, \"auth_time\": {\"essential\": true}}}"
)
print(auth_url) # 実際のリクエスト時はこのURLにリダイレクト
このように要求すると、IDトークンに amr と auth_time が含まれて渡されます。バックエンドではJWTデコード後、これらの値を抽出してポリシーに利用できます。
# バックエンドでのIDトークンデコード例 (jwtライブラリ使用)
import jwt
# トークン検証後、クレームを抽出
decoded = jwt.decode(id_token, options={"verify_signature": False})
auth_time = decoded.get("auth_time")
amr = decoded.get("amr")
# 例: 機密操作の前にamrにmfaが含まれているか確認
if "mfa" not in amr:
raise PermissionError("MFA認証が必要です。")

本論2: 注意点と応用のヒント
検証済みアプリのみ利用可能
これらのクレームは検証済みアプリケーションでのみ利用できます。つまり、Google Cloud Consoleでアプリの検証を完了する必要があります。まだ検証が済んでいない場合は、OAuth同意画面の設定で検証手続きを進めてください。
既存の認証フローとの互換性
既存のSign in with Googleフローを変更する必要はなく、単に claims パラメータを追加するだけです。そのため、移行コストは低いです。
プライバシー保護の考慮
auth_time と amr は機微な情報です。これらの値を保存・ロギングする際は、プライバシーポリシーに注意が必要です。特にGDPRなどの規制を遵守する必要があります。
日本開発エコシステムでの適用文脈
日本では、ソーシャルログインとしてGoogle Sign-inは広く利用されています。特に、ECサイトや会員制サービスでは、このクレームを活用することで不正アクセス防止や顧客情報保護に役立ちます。ただし、ユーザー体験を損なわないよう、段階的認証の基準を慎重に設計する必要があります。
この技術の限界
- Googleセッションに依存:
auth_timeはGoogleセッション基準のため、ユーザーがGoogleに長時間ログインしていても、アプリでの活動時間とは異なる場合があります。 - amr値の多様性: 一部の認証方法は組み合わせで現れることがあり、解釈に注意が必要です。
- 検証アプリの制限: 小規模アプリでは検証手続きが面倒な場合があります。

まとめ:実務適用のアドバイス
今回のアップデートは、Googleがすでに検証した認証情報を、あなたのサービスがそのまま活用できる強力な機能です。静的ポリシーから脱却し、動的でリスクベースのアクセス制御を実装したいなら、これらのクレームは良い出発点になるでしょう。
次のステップとして、実際のバックエンドでJWT検証時に署名検証を必ず実行し、クレーム値に対するテストコードを書くことをお勧めします。また、Google Identityドキュメントで追加の例を確認してください。
合わせて読みたい記事: