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. |