Skip to main content

OpenID Connect Endpoints in ZITADEL

OpenID Connect 1.0 Discovery​

The OpenID Connect Discovery Endpoint is located within the issuer domain. This would give us {your_domain}/.well-known/openid-configuration.

Link to spec. OpenID Connect Discovery 1.0 incorporating errata set 1

authorization_endpoint​

{your_domain}/oauth/v2/authorize

note

The authorization_endpoint is located with the login page, due to the need of accessing the same cookie domain

The authorization_endpoint is the starting point for all initial user authentications. The user agent (browser) will be redirected to this endpoint to authenticate the user in exchange for an authorization_code (authorization code flow) or tokens (implicit flow).

Links to specs

Required request parameters​

ParameterDescription
client_idThe id of your client as shown in Console.
redirect_uriCallback uri of the authorization request where the code or tokens will be sent to. Must match exactly one of the preregistered in Console.
response_typeDetermines whether a code, id_token token or just id_token will be returned. Most use cases will need code. See flow guide for more info.
scopeopenid is required, see Scopes for more possible values. Scopes are space delimited, e.g. openid email profile
important

Following the OIDC Core 1.0 specs whenever an access_token is issued, the id_token will not contain any claims of the scopes profile, email, phone and address.

Send the access_token to the userinfo_endpoint or introspection_endpoint the retrieve these claims or set the id_token_userinfo_assertion Option ("User Info inside ID Token" in Console) to true.

Depending on your authorization method you will have to provide additional parameters or headers:

no additional parameters required

Additional parameters​

ParameterDescription
id_token_hintValid id_token (of an existing session) used to identity the subject. SHOULD be provided when using prompt none.
login_hintA valid logon name of a user. Will be used for username inputs or preselecting a user on select_account. Be sure to encode the hint correctly using url encoding (especially when using + or alike in the loginname)
max_ageSeconds since the last active successful authentication of the user
nonceRandom string value to associate the client session with the ID Token and for replay attacks mitigation. MUST be provided when using implicit flow.
promptIf the Auth Server prompts the user for (re)authentication.
no prompt: the user will have to choose a session if more than one session exists
none: user must be authenticated without interaction, an error is returned otherwise
login: user must reauthenticate / provide a user name
select_account: user is prompted to select one of the existing sessions or create a new one
create: the registration form will be displayed to the user directly
stateOpaque value used to maintain state between the request and the callback. Used for Cross-Site Request Forgery (CSRF) mitigation as well, therefore highly recommended.
ui_localesSpaces delimited list of preferred locales for the login UI, e.g. de-CH de en. If none is provided or matches the possible locales provided by the login UI, the accept-language header of the browser will be taken into account.
response_modeThe mechanism to be used for returning parameters to the application. See response modes for valid values. Invalid values are ignored.

Response modes​

ZITADEL supports the following response_mode values. When no response mode is requested, the response mode is choosen based on the configured Response Type of the application. As per OpenID Connect Core 1.0, Section 3.1.2.1:

The use of this parameter is NOT RECOMMENDED when the Response Mode that would be requested is the default mode specified for the Response Type.

Response ModeDescription
queryEncode the returned parameters in the URL query string. This is the default when the Response type is code, for example Web applications.
fragmentEncode the returned parameters in the URL fragment. This is the default when the Response Type is id_token, for example implicit User Agent apps. This mode will not work for server-side applications, because fragments are never sent by the browser to the server.
form_post1ZITADEL serves a small JavaScript to the browser which will send the returned parameters to the redirect_uri using HTTP POST. This mode only works for server-side applications and user agents which support / allow JavaScript.

Successful code response​

When your response_type was code and no error occurred, the following response will be returned:

PropertyDescription
codeOpaque string which will be necessary to request tokens on the token endpoint
stateUnmodified state parameter from the request

Successful implicit response​

When your response_type was either id_token or id_token token and no error occurred, the following response will be returned:

PropertyDescription
access_tokenOnly returned if response_type included token
expires_inNumber of second until the expiration of the access_token
id_tokenAn id_token of the authorized user
token_typeType of the access_token. Value is always Bearer
scopeScopes of the access_token. These might differ from the provided scope parameter.
stateUnmodified state parameter from the request

Error response​

Regardless of the authorization flow chosen, if an error occurs the following response will be returned to the redirect_uri.

note

If the redirect_uri is not provided, was not registered or anything other prevents the auth server form returning the response to the client, the error will be display directly to the user on the auth server

PropertyDescription
errorAn OAuth / OIDC error_type
error_descriptionDescription of the error type or additional information of the error
stateUnmodified state parameter from the request

Possible errors​

error_typePossible reason
invalid_requestThe request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.
invalid_scopeThe requested scope is invalid. Typically the required openid value is missing.
unauthorized_clientThe client is not authorized to request an access_token using this method. Check in Console that the requested response_type is allowed in your application configuration.
unsupported_response_typeThe authorization server does not support the requested response_type.
server_errorThe authorization server encountered an unexpected condition that prevented it from fulfilling the request.
interaction_requiredThe authorization server requires end-user interaction of some form to proceed. This error MAY be returned when the prompt parameter value in the Authentication Request is none, but the Authentication Request cannot be completed without displaying a user interface for end-user interaction.
login_requiredThe authorization server requires end-user authentication. This error MAY be returned when the prompt parameter value in the Authentication Request is none, but the Authentication Request cannot be completed without displaying a user interface for end-user authentication.

token_endpoint​

{your_domain}/oauth/v2/token

The token_endpoint will as the name suggests return various tokens (access, id and refresh) depending on the used grant_type. When using authorization_code flow call this endpoint after receiving the code from the authorization_endpoint. When using refresh_token or urn:ietf:params:oauth:grant-type:jwt-bearer (JWT Profile) you will call this endpoint directly.

Authorization code grant (Code Exchange)​

As mention above, when using authorization_code grant, this endpoint will be your second request for authorizing a user with its user agent (browser).

Required request parameters​

ParameterDescription
codeCode that was issued from the authorization request.
grant_typeMust be authorization_code
redirect_uriCallback uri where the code was be sent to. Must match exactly the redirect_uri of the authorization request.

Depending on your authorization method you will have to provide additional parameters or headers:

Send your client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to build it correctly.

Successful code response​

PropertyDescription
access_tokenAn access_token as JWT or opaque token
expires_inNumber of second until the expiration of the access_token
id_tokenAn id_token of the authorized user
scopeScopes of the access_token. These might differ from the provided scope parameter.
refresh_tokenAn opaque token. Only returned if offline_access scope was requested
token_typeType of the access_token. Value is always Bearer

JWT profile grant​

Required request parameters​

ParameterDescription
grant_typeMust be urn:ietf:params:oauth:grant-type:jwt-bearer
assertionJWT built and signed according to Using JWTs for Authorization Grants
scopeScopes you would like to request from ZITADEL. Scopes are space delimited, e.g. openid email profile
curl --request POST \
--url {your_domain}/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
--data assertion=eyJhbGciOiJSUzI1Ni...

Successful JWT profile response​

PropertyDescription
access_tokenAn access_token as JWT or opaque token
expires_inNumber of second until the expiration of the access_token
id_tokenAn id_token of the authorized service user
scopeScopes of the access_token. These might differ from the provided scope parameter.
token_typeType of the access_token. Value is always Bearer

Refresh token grant​

To request a new access_token without user interaction, you can use the refresh_token grant. See offline_access Scope for how to request a refresh_token in the authorization request.

Required request parameters​

ParameterDescription
grant_typeMust be refresh_token
refresh_tokenThe refresh_token previously issued in the last authorization_code or refresh_token request.
scopeScopes you would like to request from ZITADEL for the new access_token. Must be a subset of the scope originally requested by the corresponding auth request. When omitted, the scopes requested by the original auth request will be reused. Scopes are space delimited, e.g. openid email profile

Depending on your authorization method you will have to provide additional parameters or headers:

Send your client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to build it correctly.

Successful refresh token response​

PropertyDescription
access_tokenAn access_token as JWT or opaque token
expires_inNumber of second until the expiration of the access_token
id_tokenAn id_token of the authorized user
scopeScopes of the access_token. These might differ from the provided scope parameter.
refresh_tokenAn new opaque refresh_token.
token_typeType of the access_token. Value is always Bearer

Client credentials grant​

Required request parameters​

ParameterDescription
grant_typeMust be client_credentials
scopeScopes you would like to request from ZITADEL. Scopes are space delimited, e.g. openid profile

Additionally, you need to authenticate your client by either sending client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to build it correctly.

curl --request POST \
--url {your_domain}/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic ${BASIC_AUTH}' \
--data grant_type=client_credentials \
--data scope=openid profile

Or you can also send your client_id and client_secret as parameters in the body:

ParameterDescription
client_idclient_id of the application
client_secretclient_secret of the application
curl --request POST \
--url {your_domain}/oauth/v2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=${CLIENT_ID} \
--data client_secret=${CLIENT_SECRET} \
--data scope=openid profile

Successful client credentials response​

PropertyDescription
access_tokenAn access_token as JWT or opaque token
expires_inNumber of second until the expiration of the access_token
scopeScopes of the access_token. These might differ from the provided scope parameter.
token_typeType of the access_token. Value is always Bearer

Token Exchange grant​

The Token Exchange grant implements RFC 8693, OAuth 2.0 Token Exchange and can be used to exchange tokens to a different scope, audience or subject. Changing the subject of an authenticated token is called impersonation or delegation. ZITADEL also provides a token exchange guide with more details on using the Token Exchange Grant.

info

Token Exchange is currently an experimental beta feature. Be sure to enable it on the feature API before using it.

Request parameters​

ParameterDescription
grant_typeMust be urn:ietf:params:oauth:grant-type:token-exchange
subject_tokenA token that represents the identity of the party on behalf of whom the request is being made.
subject_token_typeAn identifier that indicates the type of the token in the subject_token parameter.
actor_tokenOptional. A token that represents the identity of the acting party. In ZITADEL this the impersonator.
actor_token_typeAn identifier that indicates the type of the token in the actor_token parameter. Required when actor_token is provided
requested_token_typeOptional. An identifier that indicates the type of the token requested. Defaults to access token if not provided.
scopeScopes you would like to request from ZITADEL for the requested token. Scopes are space delimited, e.g. openid email profile.
audienceOptional. Must be a subset of the combined audiences from both subject and actor tokens.
resourceCurrently not supported

Depending on your authorization method you will have to provide additional parameters or headers:

Send your client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to build it correctly.

Successful token exchange response​

PropertyDescription
access_tokenAn access_token as opaque token or JWT for the subject user
token_typeType of the access_token. Value can be Bearer or N_A
issued_token_typeToken type of the returned token, matches the requested_token_type
refresh_tokenA refresh token if the offline_access scope was requested
id_tokenAn ID Token of the subject user, only with openid scope
expires_inNumber of second until the expiration of the access_token
scopeScopes of the access_token. These might differ from the provided scope parameter

Token types​

The following table provides a matrix of supported token type parameter and responses for Token Exchange.

Identifiersubject_tokenactor_tokenrequested_token_type
urn:ietf:params:oauth:token-type:access_tokenJWT or OpaqueJWT or OpaqueOpaque only
urn:ietf:params:oauth:token-type:refresh_tokenNot allowedNot allowedNot allowed
urn:ietf:params:oauth:token-type:id_tokenAllowedAllowedAllowed
urn:ietf:params:oauth:token-type:jwtJWT signed by client, only in combination with actor_tokenNot allowedAccess Token as JWT
urn:zitadel:params:oauth:token-type:user_iduser ID as string, only in combination with actor_tokenNot allowedNot allowed

Error response​

error_typePossible reason
invalid_requestThe request is missing a required parameter, includes an unsupported parameter value (other than grant type), repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.
invalid_scopeThe requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner.
unauthorized_clientThe authenticated client is not authorized to use this authorization grant type.
unsupported_grant_typeThe authorization grant type is not supported by the authorization server.
server_errorThe authorization server encountered an unexpected condition that prevented it from fulfilling the request.
invalid_grantThe provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
invalid_clientClient authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method).

introspection_endpoint​

{your_domain}/oauth/v2/introspect

This endpoint enables clients to validate an acccess_token, either opaque or JWT. Unlike client side JWT validation, this endpoint will check if the token is not revoked (by client or logout).

ParameterDescription
tokenAn access token

Depending on your authorization method you will have to provide additional parameters or headers:

Send your client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to build it correctly.

curl --request POST \
--url {your_domain}/oauth/v2/introspect \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic {your_basic_auth_header}' \
--data token=VjVxyCZmRmWYqd3_F5db9Pb9mHR5fqzhn...

Successful introspection response​

Upon successful authorization of the client a response with the boolean active is returned, indicating if the provided token is active and the requesting client is part of the token audience.

If active is true, further information will be provided:

PropertyDescription
audThe audience of the token
client_idThe client_id of the application the token was issued to
expTime the token expires (as unix time)
iatTime of the token was issued at (as unix time)
issIssuer of the token
jtiUnique id of the token
nbfTime the token must not be used before (as unix time)
scopeSpace delimited list of scopes granted to the token
token_typeType of the inspected token. Value is always Bearer
usernameZITADEL's login name of the user. Consist of username@primarydomain

Additionally and depending on the granted scopes, information about the authorized user is provided. Check the Claims page if a specific claims might be returned and for detailed description.

Error response​

If the authorization fails, an HTTP 401 with invalid_client will be returned.

userinfo_endpoint​

{your_domain}/oidc/v1/userinfo

This endpoint will return information about the authorized user.

Send the access_token of the user (not the client) as Bearer Token in the authorization header:

curl --request GET \
--url {your_domain}/oidc/v1/userinfo
--header 'Authorization: Bearer dsfdsjk29fm2as...'

Successful userinfo response​

If the access_token is valid, the information about the user depending on the granted scopes is returned. Check the Claims page if a specific claims might be returned and for detailed description.

Error response​

If the token is invalid or expired, an HTTP 401 will be returned.

revocation_endpoint​

{your_domain}/oauth/v2/revoke

This endpoint enables clients to revoke an access_token or refresh_token they have been granted.

important

If you revoke an access_token only the specific token will be revoked. When revoking a refresh_token, the corresponding access_token will be revoked as well.

ParameterDescription
tokenAn access token or refresh token

Depending on your authorization method you will have to provide additional parameters or headers:

Send your client_id and client_secret as Basic Auth Header. Check Client Secret Basic Auth Method on how to construct a request correctly.

end_session_endpoint​

{your_domain}/oidc/v1/end_session

The endpoint has to be opened in the user agent (browser) to terminate the user sessions.

No parameters are needed apart from the user agent cookie, but you can provide the following to customize the behavior:

ParameterDescription
id_token_hintthe id_token that was previously issued to the client
client_idclient_id of the application
post_logout_redirect_uriCallback uri of the logout where the user (agent) will be redirected to. Must match exactly one of the preregistered in Console.
stateOpaque value used to maintain state between the request and the callback

The post_logout_redirect_uri will be checked against the previously registered uris of the client provided by the azp claim of the id_token_hint or the client_id parameter. If both parameters are provided, they must be equal.

If neither an id_token_hint nor a client_id parameter is provided, the post_logout_redirect_uri will be ignored.

jwks_uri​

{your_domain}/oauth/v2/keys

The endpoint returns a JSON Web Key Set (JWKS) containing the public keys that can be used to locally validate JWTs you received from ZITADEL. The alternative would be to validate tokens with the introspection endpoint.

Key rotation​

Keys are automatically rotated on a regular basis or on demand, meaning keys can change in irregular intervals. ZITADEL ensures that a proper kid is set with each key.

Keys rotate without prior notice

Be aware that these keys can be rotated without any prior notice.

Caching​

You can optimize performance of your clients by caching the response from the keys endpoint. We recommend to regularly update the cached response, since the keys can be rotated without prior notice. You could also combine caching with a risk-based on-demand refresh when a critical operation is executed.

Without caching you will call this endpoint on each request. This might result in being rate limited for a large number of requests that come from the same backend.

OAuth 2.0 metadata​

ZITADEL does not yet provide a OAuth 2.0 Metadata endpoint but instead provides a OpenID Connect Discovery Endpoint.

Footnotes​

  1. Implements OAuth 2.0 Form Post Response Mode ↩