AttestoPhoenix.Controller.UserinfoController (AttestoPhoenix v0.6.1)

Copy Markdown View Source

OpenID Connect UserInfo endpoint (OpenID Connect Core 1.0 §5.3).

Returns claims about the authenticated subject as a JSON object. The endpoint is a protected resource: the caller presents the access token issued during authentication, and the endpoint releases the subject claims the token's scopes authorize.

Authentication

Verification is delegated to the engine's protected-resource verify path, Attesto.Plug.Authenticate, which this controller runs at the top of its action. That plug parses the Authorization header (Bearer, RFC 6750 §2.1, or DPoP, RFC 9449 §7.1), verifies the access token through Attesto.Token, and - for a sender-constrained token - enforces the DPoP / mTLS binding, honouring cnf.jkt / cnf.x5t#S256. A DPoP-bound token presented under the Bearer scheme is rejected there, not here. On failure the plug halts the conn with the RFC 6750 §3 / RFC 9449 §7.1 WWW-Authenticate challenge, which this controller returns unchanged.

Per OpenID Connect Core §5.3.1 both GET and POST are accepted; the host router maps both verbs to the :userinfo action.

Authorization

The verified access token MUST carry the openid scope (OpenID Connect Core §5.3.1). A token without it is answered 403 with error="insufficient_scope" and the scope="openid" auth-param (RFC 6750 §3.1).

Claims

The scopes on the access token (its scope claim, RFC 9068 §2.2.3) gate which claims are released (OpenID Connect Core §5.4):

  • profile - the OpenID Connect Core §5.4 profile claim set.
  • email - email and email_verified.
  • address - the address claim (a JSON object, OpenID Connect Core §5.1.1).
  • phone - phone_number and phone_number_verified.

The host supplies the claim values through the :build_userinfo_claims callback (see AttestoPhoenix.Config); this controller keeps only the values the granted scopes authorize and always includes sub (OpenID Connect Core §5.3.2), the stable subject identifier, regardless of scope.

Beyond the scope-implied set, individual claims requested through the OpenID Connect claims request parameter's userinfo member (OpenID Connect Core §5.5) are also released. The authorization endpoint records that parameter on the access token (its claims claim) at issuance; the verify path surfaces it here, and the named claims are added to the release allow-list so a Relying Party can obtain a single claim without requesting the whole scope. A claim the host's source does not supply is simply omitted (a UserInfo response need not contain every requested claim, OpenID Connect Core §5.5). When the provider advertises claims_parameter_supported: false (the default, see AttestoPhoenix.Config), the access token carries no claims claim and this reduces to scope-gated release.

Configuration contract

Resolved through AttestoPhoenix.Config (see that module for the authoritative definitions):

  • :build_userinfo_claims - the host's claim source (required to mount this endpoint).
  • :issuer, :audience, :keystore, :access_token_ttl - claim-level policy supplied to the engine verify path as an Attesto.Config.
  • :dpop_enabled, :dpop_nonce_required, :nonce_store, :replay_check, :cert_der, :mtls_enabled, :htu - sender-constraint policy and stores, threaded into Attesto.Plug.Authenticate.

Summary

Functions

UserInfo action (OpenID Connect Core §5.3). Handles both GET and POST (OpenID Connect Core §5.3.1).

Functions

userinfo(conn, params)

@spec userinfo(Plug.Conn.t(), map()) :: Plug.Conn.t()

UserInfo action (OpenID Connect Core §5.3). Handles both GET and POST (OpenID Connect Core §5.3.1).

Named userinfo rather than call so it does not collide with the Phoenix.Controller plug entrypoint (Phoenix.Controller.Pipeline.call/2) that dispatches the action.