Skip to Content
MuoCeon Docs
Third-party OAuth IntegrationBefore you start

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:

DocumentPathSpecification
Authorization server metadatahttps://id.example.com/.well-known/oauth-authorization-server/v1/oauthRFC 8414
OpenID Provider metadatahttps://id.example.com/.well-known/openid-configuration/v1/oauthRFC 8414 path form
OpenID Provider metadata (other spelling)https://id.example.com/v1/oauth/.well-known/openid-configurationOIDC Discovery
Protected resource metadata (auth)https://id.example.com/.well-known/oauth-protected-resource/v1/authRFC 9728
Protected resource metadata (oauth)https://id.example.com/.well-known/oauth-protected-resource/v1/oauthRFC 9728
Protected resource metadata (account)https://id.example.com/.well-known/oauth-protected-resource/v1/accountRFC 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_supported contains only code — there is no implicit flow.
  • code_challenge_methods_supported contains only S256 — plain is unavailable.
  • authorization_response_iss_parameter_supported is true, meaning authorization responses carry iss on both success and error; clients must validate it (see Authorization code flow).
  • authorization_endpoint points 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

  1. Verify issuer matches your expectation (prevents being pointed at another authorization server).
  2. Fetch keys from jwks_uri, match by kid, and verify token signatures; do not cache longer than the declared Cache-Control (currently 5 minutes).
  3. Build requests from token_endpoint, revocation_endpoint and friends rather than hardcoding paths.
  4. Request only scopes that appear in scopes_supported and 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.

On this page