Endpoints & discovery
The provider registers the full OAuth2/OIDC endpoint surface itself from
config('oidc.handlers'). Each protocol endpoint below is a single entry in that map — see
Route handlers for how to customize, disable, or re-point it.
Endpoints
Section titled “Endpoints”| Endpoint | Route | Purpose |
|---|---|---|
| Discovery | GET /.well-known/openid-configuration |
OIDC provider metadata |
| AS metadata | GET /.well-known/oauth-authorization-server/{path?} |
RFC 8414 authorization server metadata (same document as Discovery) |
| Protected resource | GET /.well-known/oauth-protected-resource/{path?} |
RFC 9728 protected resource metadata — see Dynamic client registration & MCP |
| JWKS | GET /.well-known/jwks.json |
Public signing keys (RS256) |
| Authorize | GET /oauth/authorize |
Authorization request (PKCE S256 required) |
| Token | POST /oauth/token |
Token endpoint (all grants) |
| Register | POST /oauth/register |
RFC 7591 dynamic client registration (disabled by default) |
| UserInfo | GET|POST /oauth/userinfo |
Claims for the bearer token |
| End session | GET|POST /oauth/logout |
RP-initiated logout — see Logout |
| Introspection | POST /oauth/introspect |
RFC 7662 token introspection (client-authenticated) |
| Revocation | POST /oauth/revoke |
RFC 7009 token revocation (client-authenticated) |
UserInfo, End session, Introspection, and Revocation can each be toggled off by setting its
handler to false in config('oidc.handlers') (oidc.userinfo, oidc.logout,
oidc.introspect, oidc.revoke). When an endpoint is disabled it is also dropped from the
discovery document. Registration (oidc.register) is additionally gated behind
config('oidc.dcr.enabled') and only registered — and advertised as registration_endpoint
in both metadata documents — when that flag is on.
The three .well-known documents (oidc.discovery, oidc.authorization-server,
oidc.protected-resource) are never prefixed by oidc.routes.prefix: RFC 8414 and RFC 9728
clients construct those URLs from the issuer origin themselves.
The authorization code flow
Section titled “The authorization code flow”How the endpoints fit together for an interactive login:
sequenceDiagram
autonumber
participant B as Browser
participant RP as Relying party
participant OP as laravel-oidc (OP)
RP->>B: Redirect to /oauth/authorize (PKCE S256, scope openid)
B->>OP: GET /oauth/authorize
alt no identity session
OP->>B: Redirect to login
B->>OP: Authenticate (password, MFA, ...)
end
OP->>B: Consent view (skipped for trusted clients)
B->>OP: POST /oauth/authorize (approve)
OP->>B: Redirect to redirect_uri?code=...
B->>RP: Authorization code
RP->>OP: POST /oauth/token (code + code_verifier)
OP->>RP: access_token (at+jwt), id_token, refresh_token
RP->>OP: GET /oauth/userinfo (Bearer access_token)
OP->>RP: Claims for the granted scopes
The UserInfo endpoint
Section titled “The UserInfo endpoint”UserInfo authenticates the bearer token against the guard named by config('oidc.api_guard')
(default oidc), and requires the openid scope. The claims it returns are the token’s granted
scopes resolved through the ClaimsResolver — see Scopes & claims.
What discovery advertises
Section titled “What discovery advertises”GET /.well-known/openid-configuration returns a document built entirely from the configured
issuer origin — every endpoint URL is derived from that origin, not the incoming request’s
host — and is served with Cache-Control: max-age=3600, public. The fixed metadata it publishes:
| Field | Value |
|---|---|
response_types_supported |
["code"] |
response_modes_supported |
["query"] |
grant_types_supported |
authorization_code, refresh_token, client_credentials, plus the device-code URN when Passport’s device-code grant is enabled, plus urn:ietf:params:oauth:grant-type:token-exchange when token exchange is enabled |
subject_types_supported |
["public"] |
id_token_signing_alg_values_supported |
["RS256"] |
code_challenge_methods_supported |
["S256"] |
claims_parameter_supported |
false |
request_parameter_supported |
false |
request_uri_parameter_supported |
false |
backchannel_logout_supported |
true |
backchannel_logout_session_supported |
true |
token_endpoint_auth_methods_supported |
["client_secret_basic", "client_secret_post", "none"] |
scopes_supported is the non-hidden catalog from the ScopeRepository, and claims_supported
comes from config('oidc.claims_supported').
The userinfo_endpoint, end_session_endpoint, introspection_endpoint, and
revocation_endpoint keys appear only when their handlers are enabled. When present, the
introspection and revocation entries each also advertise an
*_endpoint_auth_methods_supported of ["client_secret_basic", "client_secret_post"].
Consent view (required)
Section titled “Consent view (required)”The authorization endpoint needs a consent view to render. The package wires Passport’s
authorization view seam internally and resolves it through the ConsentView contract
(Bambamboole\LaravelOidc\Server\Auth\Views\ConsentView), so no app code touches
Passport::authorizationView() directly. Bind the contract instead:
use Bambamboole\LaravelOidc\Server\Auth\Views\ConsentPrompt;use Bambamboole\LaravelOidc\Server\Auth\Views\ConsentView;use Illuminate\Http\Request;
app()->bind(ConsentView::class, fn () => new class implements ConsentView { public function respond(ConsentPrompt $prompt, Request $request) { return view('oauth.authorize', [ 'client' => $prompt->client, 'user' => $prompt->user, 'scopes' => $prompt->scopes, 'authToken' => $prompt->authToken, ]); }});Without a binding, the default throws MissingAuthViewException — install
bambamboole/laravel-oidc-ui (which binds it, among the other auth views) or bind it
yourself.
The view posts auth_token back to POST /oauth/authorize to approve, or sends
DELETE /oauth/authorize to deny.