Discovering metadata
Get endpoints, capabilities and scopes from the standard discovery documents instead of hardcoding routes.
The MuoCeon authorization server publishes three standard discovery documents. Prefer reading them over copying endpoint addresses into your code — addresses, algorithms and capability lists can evolve, and the metadata evolves with them.
Document locations
Assuming issuer is https://id.example.com/v1/oauth:
| Document | Path | Specification |
|---|---|---|
| Authorization server metadata | https://id.example.com/.well-known/oauth-authorization-server/v1/oauth | RFC 8414 |
| OpenID Provider metadata | https://id.example.com/.well-known/openid-configuration/v1/oauth | RFC 8414 path form |
| OpenID Provider metadata (other spelling) | https://id.example.com/v1/oauth/.well-known/openid-configuration | OIDC Discovery |
| Protected resource metadata (auth) | https://id.example.com/.well-known/oauth-protected-resource/v1/auth | RFC 9728 |
| Protected resource metadata (oauth) | https://id.example.com/.well-known/oauth-protected-resource/v1/oauth | RFC 9728 |
| Protected resource metadata (account) | https://id.example.com/.well-known/oauth-protected-resource/v1/account | RFC 9728 |
The issuer path segment must follow the well-known prefix
Because issuer itself carries /v1/oauth, RFC 8414 requires the metadata URL to be
/.well-known/oauth-authorization-server/v1/oauth, not the bare /.well-known/oauth-authorization-server.
Both OIDC spellings are registered because real clients try either one.
What the metadata tells you
Authorization server metadata (excerpt):
{
"issuer": "https://id.example.com/v1/oauth",
"authorization_endpoint": "https://id.example.com/authorize",
"token_endpoint": "https://id.example.com/v1/oauth/token",
"revocation_endpoint": "https://id.example.com/v1/oauth/revoke",
"introspection_endpoint": "https://id.example.com/v1/oauth/introspect",
"jwks_uri": "https://id.example.com/v1/oauth/jwks",
"response_types_supported": ["code"],
"response_modes_supported": ["query"],
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"],
"authorization_response_iss_parameter_supported": true,
"authorization_details_types_supported": [
"muoceon_credential_management",
"muoceon_session_management",
"muoceon_grant_management"
]
}Key points:
response_types_supportedcontains onlycode— there is no implicit flow.code_challenge_methods_supportedcontains onlyS256—plainis unavailable.authorization_response_iss_parameter_supportedistrue, meaning authorization responses carryisson both success and error; clients must validate it (see Authorization code flow).authorization_endpointpoints at the consent UI, not the server's/v1/oauth/authorize. The latter accepts POST + JSON only and is an internal endpoint used by the consent UI to submit its decision.
Protected resource metadata
Each resource audience (auth / oauth / account) has one document declaring which scopes it accepts and which authorization server issues them:
{
"resource": "https://id.example.com/v1/auth",
"authorization_servers": ["https://id.example.com/v1/oauth"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "profile", "email", "offline_access", "auth:credentials:read", "..."]
}The resource value corresponds one-to-one with the full URI inside the access token's aud array. Third-party applications normally only need the auth document, which covers the identity scopes.
What to do with the metadata
- Verify
issuermatches your expectation (prevents being pointed at another authorization server). - Fetch keys from
jwks_uri, match bykid, and verify token signatures; do not cache longer than the declaredCache-Control(currently 5 minutes). - Build requests from
token_endpoint,revocation_endpointand friends rather than hardcoding paths. - Request only scopes that appear in
scopes_supportedand that you were approved for at registration.
Do not put userinfo under the oauth path
UserInfo lives at https://id.example.com/v1/auth/userinfo with the auth audience. Calling it with an
oauth audience token is rejected — audience mismatch is a hard failure, not a degradation.