Dynamic client registration

POST https://sso.user.m7.org/register
Content-Type: application/json
Authorization: Bearer ACCESS_TOKEN

Dynamic registration creates an active OAuth client owned by the M7 account represented by the bearer token. It is suitable for developer tooling and self-service application setup. First complete a user sign-in to obtain that access token, then call /register. Use the M7 User API to manage a registered client's later configuration, status, or deletion.

The request must be JSON and must use an active M7 bearer access token. Requests without a valid bearer token fail with invalid_token. Do not opt a new integration into DPoP based on accepted headers; see the project-specific DPoP status.

Minimal public client

The minimal request creates a public web client enabled for authorization code flow:

curl --fail-with-body --silent --show-error \
  --request POST 'https://sso.user.m7.org/register' \
  --header 'Authorization: Bearer ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "client_name": "Example App",
    "redirect_uris": ["https://app.example.com/oauth/callback"],
    "token_endpoint_auth_method": "none"
  }'

M7 requires at least one HTTPS redirect_uris entry. Redirect URIs are exact values, not patterns. The registration endpoint does not permit HTTP loopback or custom-scheme exceptions; use a registered HTTPS redirect URI.

Request metadata

Field Required Rules
redirect_uris Yes Array of one or more unique HTTPS URLs.
client_name No Display name. Defaults from the first redirect URI host when omitted.
application_type No web (default), native, or spa.
response_types No Omit or set to ['code']; no other response type is supported.
grant_types No Defaults to ['authorization_code']. Allowed values: authorization_code, refresh_token, client_credentials, and urn:ietf:params:oauth:grant-type:device_code.
scope No Space-delimited string or array of allowed scopes.
token_endpoint_auth_method No none (default), client_secret_basic, client_secret_post, client_secret_jwt, or private_key_jwt.
client_secret No Optional caller-selected secret for a secret-based method. M7 generates one when omitted.
post_logout_redirect_uris No Array of exact HTTPS URLs allowed for end-session return.
initiate_login_uri No Application's HTTPS login-start URL. M7 can use it after an expired PAR request.
default_max_age No Non-negative integer default authentication age in seconds.
token_endpoint_auth_signing_alg Conditional Signing algorithm for client_secret_jwt or private_key_jwt.
jwks_uri Conditional HTTPS JWKS URL for private_key_jwt; cannot be combined with jwks.
jwks Conditional Inline JSON JWKS for private_key_jwt; cannot be combined with jwks_uri.

Dynamic registration supports only web, native, and spa application types. It cannot create an application_type=machine client; create and manage machine applications through the M7 User API instead.

The registration request also accepts these optional client metadata fields: client_uri, logo_uri, policy_uri, tos_uri, contacts, subject_type, sector_identifier_uri, id_token_signed_response_alg, id_token_encrypted_response_alg, id_token_encrypted_response_enc, userinfo_signed_response_alg, userinfo_encrypted_response_alg, userinfo_encrypted_response_enc, request_object_signing_alg, request_object_encryption_alg, request_object_encryption_enc, require_auth_time, default_acr_values, request_uris, software_id, and software_version.

URL-bearing metadata must be valid URLs. jwks_uri and the URL configuration fields that represent security metadata must use HTTPS.

Confidential-client examples

Client secret

{
  "client_name": "Example server app",
  "redirect_uris": ["https://app.example.com/oauth/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_method": "client_secret_basic"
}

M7 returns client_secret once in the successful registration response if the selected authentication method uses a client secret. Store it immediately in a secret manager; do not expect the plaintext secret to be retrievable later.

Private-key JWT

{
  "client_name": "Example private-key client",
  "redirect_uris": ["https://app.example.com/oauth/callback"],
  "token_endpoint_auth_method": "private_key_jwt",
  "token_endpoint_auth_signing_alg": "ES256",
  "jwks_uri": "https://app.example.com/.well-known/jwks.json"
}

For private_key_jwt, M7 selects the assertion key by kid from either the registered inline JWKS or the registered HTTPS JWKS URL. The assertion must use a configured supported signing algorithm and satisfy the token-endpoint client assertion checks described in Token endpoint.

Successful response

M7 responds with HTTP 201 and standard registration metadata:

{
  "client_id": "CLIENT_ID",
  "client_id_issued_at": 1786309200,
  "application_type": "web",
  "client_name": "Example App",
  "redirect_uris": ["https://app.example.com/oauth/callback"],
  "response_types": ["code"],
  "grant_types": ["authorization_code"],
  "token_endpoint_auth_method": "none"
}

The response includes the submitted optional metadata that M7 accepted. A secret-based registration additionally includes client_secret and client_secret_expires_at (currently 0 for no fixed expiry).

Common errors

Error Typical cause
invalid_token Missing, expired, revoked, or incorrectly bound bearer token.
invalid_client_metadata Body is not a JSON object or has unsupported metadata.
invalid_redirect_uri Missing, malformed, non-HTTPS, or duplicate-invalid redirect URI data.
server_error Registration could not reach or complete its management backend.