Discovery and JWKS
This page helps you configure a client or an API from the auth server’s discovery document, and check the signature of a token it issued.
Two endpoints do this, and neither needs a token:
GET /.well-known/openid-configuration, the discovery document: where every endpoint is and what the auth server supports. Most OpenID Connect libraries need nothing else to configure themselves. The same document is at/.well-known/oauth-authorization-server, for OAuth clients that look there. See Where the document is.GET /certs, the JSON Web Key Set (JWKS): the public keys the auth server signs tokens with. Its URL is the discovery document’sjwks_uri.
Configure from discovery
Section titled “Configure from discovery”-
Give your library the auth server’s base URL, or the discovery URL itself:
Terminal window curl https://auth.example.com/.well-known/openid-configuration -
It reads the endpoints and the issuer from the answer:
{"issuer": "https://auth.example.com","authorization_endpoint": "https://auth.example.com/auth/authorize","token_endpoint": "https://auth.example.com/auth/token","userinfo_endpoint": "https://auth.example.com/userinfo","end_session_endpoint": "https://auth.example.com/auth/logout","jwks_uri": "https://auth.example.com/certs",...} -
To check a token’s signature, it fetches the key set and picks the key whose
kidmatches the one in the token’s header:Terminal window curl https://auth.example.com/certs{"keys": [{"alg": "RS256","kid": "0e0c3f6a-...","kty": "RSA","use": "sig","n": "w8Zk...","e": "AQAB"}]}
Then it checks the token’s iss against the discovery document’s issuer, and its aud and exp. See Tokens.
Where the document is
Section titled “Where the document is”The auth server serves its discovery document at two addresses, the one OpenID Connect Discovery 1.0 defines and the one RFC 8414 defines for OAuth servers in general:
/.well-known/openid-configuration, which OpenID Connect libraries read./.well-known/oauth-authorization-server, which OAuth clients read. MCP clients try it first.
Both answer GET and HEAD with the same document.
Keep the issuer the address clients reach the auth server at. A client refuses the discovery document when its issuer isn’t exactly the URL it fetched the document under, as RFC 8414 section 3.3 and OpenID Connect Discovery 1.0 section 4.3 require. An issuer naming another host breaks discovery at both addresses.
The discovery document
Section titled “The discovery document”The auth server describes what it implements, which no setting changes but two: the issuer, and whether registration_endpoint is there. Every grant and response type is listed even while the implicit flow or the password grant is off, as OpenID Connect Discovery 1.0 and RFC 8414 define these fields: a client that isn’t allowed one is refused at the endpoint.
| Field | Value |
|---|---|
issuer |
Issuer, under Admin, General in the admin console: an https URL with no query, fragment or user info, or exactly the auth server’s base URL, at most 60 characters. A new installation starts with the base URL. Every token’s iss is this value. |
authorization_endpoint |
/auth/authorize, the authorization endpoint |
token_endpoint |
/auth/token, the token endpoint |
userinfo_endpoint |
/userinfo, the UserInfo endpoint |
end_session_endpoint |
/auth/logout, the logout endpoint |
jwks_uri |
/certs, the key set below |
registration_endpoint |
/connect/register, only while dynamic client registration is on. See Dynamic client registration. |
grant_types_supported |
authorization_code, refresh_token, client_credentials, password and implicit |
response_types_supported |
code, token, id_token and id_token token |
response_modes_supported |
query, fragment and form_post |
prompt_values_supported |
none, login and consent. See prompt. |
acr_values_supported |
urn:goiabada:level1, urn:goiabada:level2_optional and urn:goiabada:level2_mandatory. See ACR and AMR. |
subject_types_supported |
public: a user’s sub is the same for every client |
id_token_signing_alg_values_supported |
RS256 |
scopes_supported |
openid, profile, email, address, phone, groups, attributes and offline_access. Permission scopes aren’t listed. See Scopes. |
claims_supported |
The claims about the user and the sign-in the auth server can supply, in ID tokens, access tokens and /userinfo |
token_endpoint_auth_methods_supported |
client_secret_post, client_secret_basic and none, the last for a public client |
code_challenge_methods_supported |
S256. See PKCE. |
request_parameter_supported |
false: a request object is refused |
request_uri_parameter_supported |
false: a request_uri is refused |
authorization_response_iss_parameter_supported |
true: every authorization response carries iss, the same value as issuer. See The response. |
Each endpoint is the auth server’s base URL, GOIABADA_AUTHSERVER_BASEURL, followed by its path. The admin console’s home page links to the document.
The key set
Section titled “The key set”/certs answers with the public half of every signing key the auth server keeps, in this order:
- The next key, which will sign tokens after the next rotation. It’s published before it signs anything, so a client that caches the set already has it when it starts being used.
- The current key, which signs every token now.
- The previous key, while there is one: it signed tokens before the last rotation, and some of them may still be valid.
Each key is a 4096-bit RSA key with alg RS256, use sig, and a kid that the header of every token it signs carries.
To rotate, choose Rotate keys under Admin, Signing keys in the admin console. The next key becomes the current one, the current one becomes the previous one, the old previous key is deleted, and a new next key is created. A token signed by the deleted key no longer verifies, refresh tokens included, so don’t rotate twice within the lifetime of your longest-lived token.
A rotation can fail at its very end, if the database connection is lost while the change is saved. The page then says the rotation may or may not have happened. To tell which, compare the keys listed now with the ones you saw before pressing Rotate keys: the rotation happened if the key that was next is now current. Don’t rotate again until you know, since a second rotation deletes the key that was current a moment ago.
Calling them from a browser
Section titled “Calling them from a browser”The discovery document, at both its addresses, and /certs answer cross-origin requests from any origin, with nothing to register, so JavaScript in a browser can read them. See web origins for the endpoints that need one.