Dynamic Client Registration

Authagonal implements OAuth 2.0 Dynamic Client Registration (RFC 7591), allowing client applications to register themselves at runtime without administrator involvement.

Enabling the Endpoint

Dynamic registration is disabled by default. Opt in via configuration:

{
  "Auth": {
    "DynamicClientRegistrationEnabled": true
  }
}

Or set Auth__DynamicClientRegistrationEnabled=true as an environment variable.

When enabled, the discovery document advertises the endpoint:

GET /.well-known/openid-configuration
{
  "registration_endpoint": "https://auth.example.com/connect/register"
}

Registering a Client

POST /connect/register
Content-Type: application/json

{
  "client_name": "My App",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "post_logout_redirect_uris": ["https://myapp.example.com/"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "client_secret_basic",
  "scope": "openid profile email offline_access",
  "audiences": ["https://api.myapp.example.com"],
  "allowed_cors_origins": ["https://myapp.example.com"],
  "backchannel_logout_uri": "https://myapp.example.com/oidc/backchannel",
  "frontchannel_logout_uri": "https://myapp.example.com/oidc/frontchannel",
  "frontchannel_logout_session_required": true
}

Response

HTTP/1.1 201 Created
Content-Type: application/json

{
  "client_id": "a1b2c3d4e5f6...",
  "client_secret": "xkCd2_base64url...",
  "client_id_issued_at": 1745000000,
  "client_secret_expires_at": 0,
  "client_name": "My App",
  "redirect_uris": ["https://myapp.example.com/callback"],
  "post_logout_redirect_uris": ["https://myapp.example.com/"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "scope": "openid profile email offline_access",
  "token_endpoint_auth_method": "client_secret_basic"
}

The client_secret is returned once and cannot be retrieved later. Store it securely.

Request Parameters

Parameter Required Notes
client_name no Defaults to the generated client_id if omitted
redirect_uris conditional Required when grant_types contains authorization_code. Must be absolute URIs; javascript:/data:/vbscript:/file: schemes are rejected (native custom schemes for mobile deep links are fine).
post_logout_redirect_uris no Valid redirect targets after logout
grant_types no Defaults to ["authorization_code"]. Only authorization_code and refresh_token are registrable: client_credentials, implicit, device and any other grant type are rejected with invalid_client_metadata, so open registration can never mint a machine-to-machine client. refresh_token is added automatically if offline_access is requested.
token_endpoint_auth_method no client_secret_basic (default), client_secret_post, or none for public clients
scope no Space-separated scopes, must all be built-in or previously registered (see Scopes). The administrative scope (AdminApi:Scope, default authagonal-admin) can never be registered.
audiences no JWT aud values added to access tokens
allowed_cors_origins no Origins permitted to call the token endpoint from a browser
backchannel_logout_uri no Enables Back-Channel Logout
frontchannel_logout_uri no Enables Front-Channel Logout
frontchannel_logout_session_required no Defaults to true; when true, the logout URL carries iss and sid parameters

Defaults & Invariants

Error Responses

HTTP error Cause
400 invalid_redirect_uri One of redirect_uris is not a valid absolute URI, or uses a script/data/file pseudo-scheme
400 invalid_client_metadata A non-registrable grant type was requested, or redirect_uris is missing for a grant type that requires it
400 invalid_scope A requested scope is neither built-in nor registered
403 invalid_scope The administrative scope was requested, it can never be granted through registration
403 not_supported Dynamic client registration is not enabled
429 rate_limited Too many registrations from this IP (10 per hour)

Security Considerations

The registration endpoint is unauthenticated, but constrained by design:

For stronger gating (initial access tokens, mTLS, software statements), front the endpoint with your own middleware or an IAuthHook. Consider disabling dynamic registration entirely and managing clients via the admin API in environments where self-service registration is not a requirement.