Skip to content

OpenID Connect

  • OpenID Connect Core 1.0
  • OpenID Connect Discovery 1.0
  • OpenID Connect Dynamic Client Registration 1.0
  • RFC 7591 / RFC 6750 / RFC 7523 (as used by registration and private_key_jwt)
Flow ID Name Description
oidc_authorization_code Authorization Code OIDC authentication with ID token
oidc_hybrid Hybrid Flow Combined code + token response (Section 3.3)
oidc_implicit Implicit (Legacy) Browser-based OIDC flow
oidc_userinfo UserInfo Claims retrieval from the UserInfo endpoint
oidc_discovery Discovery OpenID Provider metadata and JWKS resolution
interaction-code Interaction Code Interactive authorization with PKCE
  • Login with OpenID Connect – Full OIDC authentication flow
  • ID Token Deep Dive – Token decoding and claims inspection
  • Discovery Document Exploration – Provider metadata resolution
Path Methods Purpose
/.well-known/openid-configuration GET Discovery document at the issuer root (canonical path a Relying Party derives from the issuer, OIDC Discovery 1.0 Section 4)
/oidc/.well-known/openid-configuration GET Discovery document (prefixed alias, same content)
/oidc/.well-known/jwks.json GET JSON Web Key Set (RSA and EC signing keys; OKP/Ed25519 is held in the OP key set but not published here because discovery only advertises RS256 for ID Tokens)
/oidc/jwks GET JWKS alias
/oidc/authorize GET, POST Authorization endpoint
/oidc/token POST Token endpoint (returns ID token)
/oidc/userinfo GET, POST UserInfo endpoint
/oidc/register POST Open Dynamic Client Registration (OIDC Dynamic Client Registration 1.0)
/oidc/register/{client_id} GET, PUT, DELETE RFC 7592 Client Configuration Endpoint (Bearer registration access token)
/oidc/third-party/initiate GET, POST ProtocolSoup initiator that redirects to an RP initiate_login_uri (not a standardized OP endpoint)
/oidc/admin/rotate-keys POST Operator-only OP signing-key rotation (disabled unless OIDC_KEY_ROTATION_TOKEN is set)
  • ID token claims: iss, sub, aud, exp, iat, auth_time, nonce, at_hash, c_hash, acr, amr
  • Discovery fields: issuer, authorization_endpoint, token_endpoint, jwks_uri
  • JWKS: RSA/EC key type, algorithm, and key ID alignment with the token header (kid)
  • UserInfo: scope-dependent claims, subject consistency with ID token; signed responses include iss (OP issuer) and aud (RP client ID)
  • Hybrid: multiple response types in a single authorization request
  • Authorization errors after client_id and redirect_uri are validated are returned to the client by redirect (query for the code flow, fragment for implicit and hybrid), echoing state (RFC 6749 Section 4.1.2.1). Invalid client_id or redirect_uri is shown to the user agent and never redirected.
  • prompt=none returns login_required when no end-user session is present; prompt=login and an exceeded max_age force re-authentication and set auth_time.
  • The interactive login page includes a Cancel control in its own form (separate from Sign In). Submitting it redirects to the registered redirect_uri with error=access_denied (and echoes state / iss) so relying parties can treat user rejection as a normal OAuth/OIDC error (OIDC Core §3.1.2.6, RFC 6749 §4.1.2.1). An existing OP session that completes authorization returns a code instead of access_denied.
  • RFC 9126 PAR handles (request_uri values under urn:ietf:params:oauth:request_uri:) stay redeemable across repeated visits to /oidc/authorize until authorization completes. The OP consumes the handle only when it issues the authorization response, not when the login page is first shown (FAPI 2.0 Security Profile §5.3.2.2 Note 3). PAR-backed authorize requests never silently finish via an existing session cookie. When a session is already present, the OP shows a Continue confirmation (no password fields) so a browser preload or password-manager auto-submit cannot complete the first visit; authorization proceeds only after an explicit Continue (or a fresh password login when no session exists).
  • Public clients must use PKCE: an authorization code request without a code_challenge is rejected (RFC 7636 Section 4.4.1).
  • Authorization codes are bound to the client they were issued to; a different client redeeming a code is rejected with invalid_grant.
  • Authorization codes are single-use. Replaying a code is rejected with invalid_grant and additionally revokes the access (and refresh) tokens that code already issued; the revoked access token is then rejected at UserInfo with 401 invalid_token (RFC 6749 Section 4.1.2, RFC 6750 Section 3.1).
  • A token-endpoint client-authentication failure made over HTTP Basic returns 401 with a WWW-Authenticate: Basic challenge, and token-endpoint errors do not carry a Bearer challenge (RFC 6749 Section 5.2).
  • The authorization endpoint accepts requests by both GET and POST (OIDC Core 1.0 Section 3.1.2.1). A POST carrying authorization parameters is handled identically to GET; the interactive login form posts to the same path and is distinguished internally.
  • When the flow issues an access token (the code flow always does, as do the id_token token and hybrid flows), the scope-requested claims (profile, email, …) are served from the UserInfo endpoint and are not duplicated in the ID token. They appear in the ID token only for the response_type=id_token case, where no access token is issued (OIDC Core 1.0 Section 5.4).
  • The UserInfo endpoint accepts the access token in the Authorization: Bearer header or, for a form-encoded POST, in an access_token body parameter (RFC 6750 Section 2). Presenting both in one request is an invalid_request.
  • By-value request objects are not supported and are rejected with request_not_supported (OIDC Core 1.0 Section 6.3.1). Discovery always advertises request_parameter_supported as false. HTTPS request_uri Request Objects (OIDC Core §6.2) are available only when Dynamic Client Registration is enabled (request_uri_parameter_supported); otherwise they are rejected with request_uri_not_supported. Separately, RFC 9126 PAR request_uri values (urn:ietf:params:oauth:request_uri:…) are always accepted and merged at /oidc/authorize. Authorization error responses for unsupported or invalid request objects are delivered to the validated redirect URI using the requested response_mode and echo state (RFC 6749 Section 4.1.2.1). When a by-value request object carries response_mode and state inside the JWT, the OP reads only those two delivery values from the object (without verifying it or using any other claim) so the error reaches the client in the correct channel, for example as a form_post POST.
  • The authorization response is delivered in the requested response_mode: query, fragment, or form_post, all advertised in response_modes_supported. query is rejected for response types that return tokens in the front channel. For form_post the OP returns a self-submitting HTML form that POSTs the response parameters (success or error) to the redirect URI, so nothing is placed in a URL (OAuth 2.0 Form Post Response Mode). This enables the Form Post OP profiles.
  • The claims request parameter is supported (OIDC Core 1.0 Section 5.5), and discovery advertises claims_parameter_supported as true. Claims requested under the userinfo member are returned from the UserInfo endpoint; claims requested under the id_token member are returned in the ID token. Every returned value is real data from the user record, and a value the user does not have is omitted rather than erroring (Section 5.5.1). A claims value that is not a valid JSON object is rejected with invalid_request.
  • The profile scope returns the full profile standard-claim set from UserInfo (name, given_name, family_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthdate, zoneinfo, locale, updated_at). Every value is real data held on the demo user record, not synthesised per request (OIDC Core 1.0 Section 5.4).
  • The address and phone scopes are also supported and advertised in scopes_supported. The address scope returns the structured address claim (OIDC Core 1.0 Section 5.1.1) as a JSON object with the populated members (formatted, street_address, locality, region, postal_code, country); blank members are omitted. The phone scope returns phone_number and phone_number_verified (Section 5.1). All values are real data held on the demo user record.
  • ID tokens carry acr and amr describing the authentication that actually happened: single-factor password, reported as acr urn:protocolsoup:ac:password and amr ["pwd"] (OIDC Core 1.0 Section 2, RFC 8176). That value is advertised in acr_values_supported. The OP reports the context it genuinely performed and never echoes a higher assurance level (1, 2, …) requested via acr_values that it did not satisfy.
  • ID tokens are signed with RS256 only; the discovery metadata advertises only what the OP delivers.

Open Dynamic Client Registration is enabled by default (OIDC_DYNAMIC_REGISTRATION_ENABLED=true). Registrations are ephemeral ordinary clients: TTL-bounded, capacity-capped, and rate-limited. They receive no privileges beyond a normal client registration.

POST /oidc/register
Content-Type: application/json
{
"redirect_uris": ["https://rp.example.com/callback"],
"client_name": "Example RP",
"token_endpoint_auth_method": "private_key_jwt",
"jwks_uri": "https://rp.example.com/jwks.json",
"initiate_login_uri": "https://rp.example.com/login",
"userinfo_signed_response_alg": "RS256",
"logo_uri": "https://rp.example.com/logo.png",
"policy_uri": "https://rp.example.com/policy",
"tos_uri": "https://rp.example.com/tos"
}

Successful responses are 201 application/json with Cache-Control: no-store, the registered/defaulted metadata, a unique client_id, credentials when required, HTTPS registration_client_uri, and an opaque registration_access_token. Unknown metadata is ignored. Invalid understood metadata returns 400 with invalid_client_metadata or invalid_redirect_uri.

GET /oidc/register/{client_id} with Authorization: Bearer <registration_access_token> returns the current registration (200). PUT accepts a complete replacement registration: it must contain the same client_id, may not contain response-only management fields, and must include the current client_secret for confidential clients. A successful update returns 200 and rotates the registration access token. DELETE deprovisions the client and returns 204 No Content; its client ID, secret, and registration access token are no longer usable. These management operations follow RFC 7592 Section 2.

Supported token authentication methods include client_secret_basic, client_secret_post, private_key_jwt, and none. Dynamically registered clients may request signed UserInfo (userinfo_signed_response_alg=RS256) and signed Request Objects by reference (request_uri) verified against jwks/jwks_uri. They may request subject_type: "pairwise"; the OP derives the subject deterministically from the user and sector, and returns that same subject in ID Tokens, access tokens, refresh tokens, and UserInfo. For multiple redirect URI hosts, a pairwise client must supply an HTTPS sector_identifier_uri. At registration time the OP fetches its JSON array without following redirects, rejects private-network addresses, and requires it to contain every registered redirect URI (OIDC Core §8.1; OIDC Registration §5). Unsigned ID Tokens, unsigned Request Objects, and by-value request objects are not advertised and are rejected when explicitly requested.

OIDC Core §4 sends iss (required, HTTPS), optional login_hint, and optional target_link_uri from an initiating party to the RP’s registered initiate_login_uri. Those parameters are not authorization-request parameters for the OP, so /oidc/authorize does not validate iss or target_link_uri.

ProtocolSoup exposes /oidc/third-party/initiate as a demonstration initiator. It selects a registered client, redirects only to that client’s HTTPS initiate_login_uri, and appends the Core §4 parameters. Non-HTTPS initiate_login_uri values are rejected at registration with invalid_client_metadata. The RP remains responsible for accepting the request and starting its own Authentication Request.