Skip to content

scope と claim ​

scope と claim は OIDC を学び始めた人が最も混同する 2 語です。同じものではありません。

  • scope はクライアントが authorize 要求で 要求する もの。OP が scopes_supported で公開している小さな識別子集合の中の 1 つです。
  • claim は OP が 返す key-value のペアです。構造化された応答、たとえば ID トークン、JWT アクセストークン、/userinfo 応答の中に入ります。

scope は要求、claim は応答です。scope を grant すると、claim ソースが値を返せる範囲で、対応する claim を OP が開示できるようになります。

30 秒で頭に入れる相関図

  • scope = 「あなたの email が見たい」 — scope=openid email
  • claim = "email": "alice@example.com" — 返ってきた値。
  • 1 つの scope が複数の claim を開示することがあります。下表の OIDC 標準対応がそのマッピングです。
このページで触れる仕様

scope: クライアントが要求するもの ​

/auth の scope パラメータは、半角スペース区切りの不透明な識別子のリストです。ユーザはその集合に同意し、OP は grant された集合を認可コードに記録し、アクセストークンとリフレッシュトークンの状態へ引き継ぎます。ID トークンには標準の scope claim は入りません。OP を /oidc に mount した場合の既定 endpoint は /oidc/auth です。

GET /auth?response_type=code&client_id=...&scope=openid%20profile%20email&...

初学者が見落としがちな点をいくつか:

  • scope 識別子は OAuth 2.0 にとって不透明。openid に特別な意味を与えるのは OIDC Core §3.1.2.1 です。それ以外の scope 名は OP とクライアントの合意や拡張仕様で定まります。
  • scope は case-sensitive。openid は scope ですが、OpenID は別物(かつ未認識の)scope です。
  • openid が OAuth を OIDC に変える魔法。openid が要求になければ ID トークンは発行されません。本ライブラリのデフォルトは OIDC(openid scope 必須)で、op.WithOpenIDScopeOptional() で純 OAuth 2.0 に切り替えられます。
  • ユーザは一部の scope を辞退できる。grant された集合は要求された集合の部分集合になり得ます。OP は実際に grant された scope を token 応答とアクセストークンの状態に反映します。
  • 未知の scope は失敗。WithScope で登録されていない(あるいは組み込み OIDC 標準でない)scope が要求されると、OP は RFC 6749 §5.2 の invalid_scope を返します。

claim: トークンや userinfo 応答の中の key-value ​

claim は JSON object 内の 1 フィールドです。トークンでは OP が署名し、/userinfo では既定で JSON として返ります。要求に応じて署名付きまたは暗号化された JWT になることもあります。OIDC Core §5.1 が長いカタログを提供しています。トークンの metadata claim とユーザ claim は分けて考える必要があります。

  • ID トークンの claim — iss、sub、aud、iat、exp は必須です。nonce、auth_time、acr、amr、azp、at_hash、c_hash、sid はフローや要求に応じて入ります。
  • JWT アクセストークンの claim — RFC 9068 で iss、sub、aud、client_id、iat、exp、jti が必須です。scope、cnf、auth_time、acr、amr などは条件に応じて入ります。本ライブラリでは opaque アクセストークン、リフレッシュトークン、認可コードは通信路上に claim を持ちません。
  • ユーザ claim — name、family_name、email、email_verified、phone_number、address、picture など。エンドユーザを説明する値です。grant された scope または明示的な claims request が許可し、claim ソースが値を返せる場合にだけ OP が開示します。

ユーザ claim は scope が制御し、トークンの metadata claim はトークンの種類とフローによって決まります。

OIDC Core の scope-to-claim 対応 ​

OIDC Core §5.4 は profile、email、address、phone に対応するユーザ claim を定めています。表には §3.1.2.1 の OIDC リクエストを示す openid と、§11 のリフレッシュトークン用同意を扱う offline_access も載せています。この 2 つは §5.4 のユーザ claim 群ではありません。

ScopeRelease される claim
openidsub
profilename、family_name、given_name、middle_name、nickname、preferred_username、profile、picture、website、gender、birthdate、zoneinfo、locale、updated_at
emailemail、email_verified
addressaddress
phonephone_number、phone_number_verified
offline_access(claim なし — リフレッシュトークン発行のためのユーザ向け同意画面と、適用されるリフレッシュトークンの TTL バケットを制御)

scope=openid email の要求は、ユーザ claim カタログから sub、email、email_verified を開示します。それ以外は何も開示しません。scope=openid profile email なら profile 群が丸ごと加わります。

この対応表だけでは、開示された claim が どこに載るか までは分かりません。通常の scope フローでは、sub と ID トークンの metadata claim は ID トークンに載り、profile・email・address・phone が開示するユーザ claim は /userinfo から返ります。アクセストークンには grant された scope が入り、ID トークンには標準の scope claim は入りません。

要求した scope → 開示される claim → 届き先
各標準 scope が開示する claim 群と、その届き先を示した図。openid が開示する sub は ID トークンに載り、profile・email・address・phone の claim は userinfo エンドポイントから返ります。offline_access は claim を開示しません。要求した scope開示される claim届き先openidsubprofilename · family_name · given_name · …(14 claim)emailemail · email_verifiedaddressaddressphonephone_number · phone_number_verifiedoffline_accessclaim は開示しない — 同意画面とリフレッシュトークンの TTL バケットを決めるID トークンiss · aud · exp · iat · sub任意: nonce · auth_time · azp任意: acr · amr · at_hash · sidOP 自身が埋める/userinfoRP がアクセストークンを付けて呼び出すと claim が返る(既定は JSON)許可された scope が認めたclaim だけが載る
scope は要求であって保証ではありません。OP が許可するのは、クライアントが登録した範囲・ユーザが同意した範囲・claim ソースが実際に返せる値の重なりです。この表に載っている claim でも応答に含まれないことがあります。

ユーザ claim を ID トークンに載せたい RP は、OIDC Core §5.5 の claims パラメータで明示的に要求する必要があります。scope を許可しただけでは /userinfo 側に載ります。

offline_access は claim を開示しない

offline_access は OIDC 標準 scope で、「ユーザが不在のときも動き続けたい」というクライアントの意思表明 — つまりリフレッシュトークン発行に対するユーザ向けの consent prompt です。ユーザ claim は何も開示しません。本ライブラリでは、結果として発行されるリフレッシュトークンを別の TTL バケット(op.WithRefreshTokenOfflineTTL)にルーティングするので、ログイン状態維持の chain は通常の短セッションのリフレッシュより長く保てます。詳細はリフレッシュトークン。

カスタム scope ​

本ライブラリは op.WithScope で scope を追加登録できます。各カスタム scope は op.Scope 構造体で、通信路上の識別子・consent prompt の表示テキスト・開示する claim のリスト・(任意で)どのクライアントが要求できるかを記述します。

go
op.WithScope(op.PublicScope("read:projects", "プロジェクトの読み取り")),
op.WithScope(op.Scope{
    Name:        "write:projects",
    Title:       "プロジェクトへの書き込み",
    Description: "あなたの代理でプロジェクトの作成・変更を行います。",
    Public:      true,
    Claims:      []string{"projects:permissions"},
    AllowedClients: []string{"trusted-client-1"},
}),

よくある用途には 2 つのヘルパが用意されています。

  • op.PublicScope(name, label) — discovery 文書の scopes_supported に公開する scope を登録します。審査済みのクライアントなら誰でも要求できる scope に使います。
  • op.InternalScope(name) — scopes_supported から 省略 する scope を登録します(RFC 8414 §2 / OIDC Discovery §3 が省略を明示的に許容)。受理判定は scope の AllowedClients リストで制御されます。discoverable にしたくないが特定クライアントには許す scope に使います。

OIDC 標準 scope は組み込みのデフォルトで自動認識されます。標準名(例: email)に対して WithScope を呼ぶと組み込みエントリが上書きされます — 翻訳や追加の claim mapping を付与する目的で使うのが典型です — が、Public: false で標準 scope を登録すると op.New が失敗します。discovery 文書が「標準 scope を欠落」と公告するのを防ぐためです。

op.Scope.Parse は組み込み側の文字列処理用ヘルパで、Unicode whitespace の連続で分割します。一方、通信路上の scope parsing は RFC 6749 の ASCII space grammar を使うため、/auth / /par 入力に tab や改行を混ぜることを互換性前提にしないでください。

i18n ラベル、claim mapping、consent prompt のレンダリングを含む詳細は使い方: scopeを参照してください。

scope と RFC 8707 resource indicator ​

よくあるモデリングの問い: 権限を分けるとき、新しい scope を切るのか、新しい audience を切るのか?

問い答え例
「同じ RS が解釈する 異なる種類 の権限ですか?」scope を使う。同じ projects API に対する read:projects と write:projects。
「別の resource server で、独自の audience が必要ですか?」RFC 8707 を使う。projects API 用のアクセストークンと billing API 用のアクセストークン。各 RS の verifier が cross-audience なトークンを拒否できるよう、aud を別にしたい。
「audience ごとに lifetime / 形式 / revocation ポリシーが違いますか?」per-audience format で RFC 8707 を使う。管理 API は opaque(即時失効)にしつつ、read API は JWT(水平スケール)を維持。本ライブラリは op.WithAccessTokenFormatPerAudience で実現します。

scope は 権限の幅 を、resource indicator は 対象 audience を表現します。1 つの認可リクエストに両方を載せることもできます。例えば scope=openid read:projects&resource=https://projects.example.com と指定すると、本ライブラリは指定した resource 向けにアクセストークンを 1 つ発行します。組み込みの認可フローで resource を繰り返すと invalid_target で拒否されるため、別のリソースサーバには別のリクエストを使います。

resource パラメータを受け付けるすべてのエンドポイントは、まず同じ正規形に落としてから比較します。

ルール効果
絶対 URI が必須scheme と host を欠く値は拒否します。
scheme と host を小文字化HTTPS://API.example.com と https://api.example.com は同じ resource になります。
デフォルトポートを除去HTTP の :80 と HTTPS の :443 は落とし、それ以外のポートは維持します。
末尾の / を 1 個除去https://api.example.com/ は https://api.example.com になります。
query は維持query 文字列も resource の同一性の一部です。
fragment と userinfo は拒否invalid_target でリクエストを失敗させます。

許可リストとの比較や WithAccessTokenFormatPerAudience も同じ正規化を通ります。そのため、authorize、PAR、token、device authorization、CIBA、token exchange の間で同じ resource の比較結果が変わることはありません。

OIDC §5.5 の claims パラメータ(scope 単位ではなく特定の claim を細かく要求する)は使い方: claims requestに、per-audience format のトレードオフはアクセストークン形式にあります。

次に読む ​