Discovery and signing keys

Discovery

M7 publishes OpenID Connect and OAuth authorization-server metadata at both:

GET https://sso.user.m7.org/.well-known/openid-configuration
GET https://sso.user.m7.org/.well-known/oauth-authorization-server

Both endpoints return the same JSON metadata. Use discovery to obtain the issuer and endpoint URLs rather than duplicating them in application code.

The metadata advertises:

  • issuer
  • authorization_endpoint
  • pushed_authorization_request_endpoint
  • registration_endpoint
  • token_endpoint
  • end_session_endpoint
  • userinfo_endpoint
  • revocation_endpoint
  • introspection_endpoint
  • device_authorization_endpoint
  • jwks_uri
  • supported response types, grants, PKCE methods, client-authentication methods, claims, and scopes

Use GET or HEAD; other methods are rejected.

Supported protocol metadata

Discovery currently advertises:

Metadata item Values
response_types_supported code
response_modes_supported query
grant_types_supported authorization_code, refresh_token, client_credentials, urn:ietf:params:oauth:grant-type:device_code
code_challenge_methods_supported S256, plain (see compatibility note below)
token_endpoint_auth_methods_supported none, client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt
scopes_supported openid, profile, email, groups, offline_access

The discovery document is the source of truth for endpoint URLs and supported feature lists. A client still needs to be configured and authorized for every grant, scope, authentication method, audience, and redirect URI it uses.

query means M7 returns authorization success and safely returnable errors by top-level browser GET to the exact registered callback. See Authorization callback outcomes for the response fields and validation requirements.

Although discovery currently lists plain as a PKCE method, the token verifier currently accepts only the S256 transformation. Treat plain as advertised-only compatibility metadata and use S256 for every integration.

Signing-key lookup

M7 exposes this discovery key endpoint:

GET https://sso.user.m7.org/jwks.json

It deliberately does not return an enumerable RFC 7517 JWKS keys array. Instead it returns an instruction object similar to:

{
  "issuer": "https://id.m7.org",
  "template": "https://id.m7.org/api/v2/cert/kid/{kid}?response=jwk",
  "instructions": "Use the JWT header kid with the issuer template. Do not assume a single enumerable JWKS inventory."
}

To obtain the correct public key, read the signed JWT's protected header, substitute its kid into the returned template, and fetch the individual JWK. Do not assume a static, globally enumerable key list and do not configure an OIDC library to treat /jwks.json as a conventional JWKS document without an adapter for this lookup model.

Use GET or HEAD for /jwks.json.

Validate tokens before use

For an ID token or a resource-server JWT, validate at least:

  1. the JWS signature using the key selected by kid;
  2. the token type and intended audience for your client or resource;
  3. expiry and other time-based claims; and
  4. nonce for an ID token obtained from a browser authorization that supplied a nonce.

Two issuer identifiers

M7 currently has separate authorization-server and token/key identifiers:

Purpose Value
Authorization-server issuer in discovery https://sso.user.m7.org
Current signed-token iss value id.m7.org
Key-service issuer in /jwks.json https://id.m7.org

Do not configure a generic JWT validator to require the discovery issuer for an M7 access token: current access tokens carry iss: "id.m7.org" instead. Select the public key using the token header's kid and the /jwks.json template, then validate the token profile's issuer, signature, audience, time claims, and any OIDC nonce as applicable. Do not trust a decoded JWT merely because it has expected-looking claims.

Caching and key rotation

Respect HTTP caching headers returned by the individual key service. Cache keys by kid, tolerate a new kid at any time, and fetch an unknown key before failing validation. Do not pin a single signing key indefinitely.