Skip to content

Update back-channel logout

PUT
/api/v1/admin/clients/{id}/backchannel-logout
Code sample: Shell / cURL
curl --request PUT \
--url http://localhost:9090/api/v1/admin/clients/1/backchannel-logout \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "backchannelLogoutUri": "example", "backchannelLogoutSessionRequired": true }'

Set a client’s back-channel logout URI, where the auth server POSTs a logout token when a session the client was on ends (OpenID Connect Back-Channel Logout 1.0), and whether the client requires the session identifier (sid) in every logout token. Send both fields; an empty backchannelLogoutUri clears the URI.

The URI is an absolute https URI that names a host, at most 2048 bytes, with no user name or password and no fragment. A query is kept as sent. A confidential client an administrator created may use plain http on any host; a public client can’t, and neither can a client that registered itself, whatever its type. The client needs the authorization code flow or the implicit flow.

Setting the URI, or changing the stored one, needs authserver:manage: another token is refused 403 MANAGE_SCOPE_REQUIRED. authserver:manage-clients can clear the URI and change backchannelLogoutSessionRequired alone. On an administrator client, only authserver:manage may save at all.

id
required
integer format: int64

Client ID

Media typeapplication/json
object
backchannelLogoutUri
required

The back-channel logout URI, or an empty string for none. Surrounding spaces are trimmed. A URI that breaks the rules is refused with 400 and nothing is written; error_code is the refusal’s catalog key, such as handler.client_backchannel_logout.uri_http_public_client.

string
<= 2048 characters
backchannelLogoutSessionRequired
required

Whether the client requires the session identifier (sid) in every logout token.

boolean

Example generated

{
"backchannelLogoutUri": "example",
"backchannelLogoutSessionRequired": true
}

Back-channel logout settings updated

Media typeapplication/json
object
client
required
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
clientIdentifier
required
string
description
required
string
websiteUrl
required

The client’s website URL

string
privacyPolicyUrl
required

The client’s own privacy policy, linked from the consent screen whenever set; empty when it has none

string
termsOfServiceUrl
required

The client’s own terms of service, linked from the consent screen whenever set; empty when it has none

string
displayName
required

A user-friendly name for the client

string
enabled
required
boolean
consentRequired
required
boolean
rememberConsent
required

Whether a user’s earlier approval skips the consent screen for this client. Always true for a confidential client. A public client starts with it off, so users are asked whenever the consent screen is owed, even if they approved the app before.

boolean
backchannelLogoutUri
required

Where the auth server POSTs a logout token when a session the client was on ends; empty when it has none. Set through PUT /api/v1/admin/clients/{id}/backchannel-logout

string
backchannelLogoutSessionRequired
required

Whether the client requires the session identifier (sid) in every logout token. Set through PUT /api/v1/admin/clients/{id}/backchannel-logout

boolean
dpopBoundAccessTokens
required

Whether the client requires DPoP for token requests: a token request without a DPoP proof is refused, and so are the implicit response types that return an access token. Set through PUT /api/v1/admin/clients/{id}/dpop, or by dynamic client registration’s dpop_bound_access_tokens

boolean
createdViaDcr
required

Read-only. True when the client registered itself through /connect/register

boolean
administrativeScopesAllowed
required

Read-only. True when the client may request the administrative authserver scopes on a user’s behalf; always true for the admin console’s own client. Switched through PUT /api/v1/admin/clients/{id}/administrative-scopes, with authserver:manage alone

boolean
showLogo
required

When true, the client logo is displayed on sign-in and consent screens

boolean
showDisplayName
required

When true, the display name is shown instead of the client identifier

boolean
showDescription
required

When true, the client description is displayed on sign-in and consent screens

boolean
showWebsiteUrl
required

When true, the client website URL is displayed on sign-in and consent screens

boolean
isPublic
required
boolean
isSystemLevelClient
required
boolean
authorizationCodeEnabled
required
boolean
clientCredentialsEnabled
required
boolean
pkceRequired
required

Null inherits the global setting, true requires PKCE, false makes it optional. Ignored for public clients, which always require PKCE

boolean
nullable
implicitGrantEnabled
required

Null inherits the global setting, true enables the implicit flow, false disables it. Deprecated in OAuth 2.1

boolean
nullable
resourceOwnerPasswordCredentialsEnabled
required

Null inherits the global setting, true enables grant_type=password (RFC 6749 section 4.3), false disables it. Deprecated in OAuth 2.1

boolean
nullable
tokenExpirationInSeconds
required
integer
refreshTokenOfflineIdleTimeoutInSeconds
required
integer
refreshTokenOfflineMaxLifetimeInSeconds
required
integer
includeOpenIDConnectClaimsInAccessToken
required

“on” includes the OpenID Connect claims in this client’s access tokens, “off” leaves them out, “default” follows the global setting of the same name.

string
Allowed values: on off default
includeOpenIDConnectClaimsInIdToken
required

“on” includes the OpenID Connect claims in this client’s ID tokens, “off” leaves them out, “default” follows the global setting of the same name.

string
Allowed values: on off default
defaultAcrLevel
required
string
redirectURIs
required

Null when this collection was not loaded for the response.

Array<object>
nullable

The redirectURIs entries of ClientResponse.

The schema name is unchanged, but the shape below is not what releases up to and including v1.6.0 put on the wire: this position carried the persistence row directly, so its keys arrived capitalised and its createdAt arrived as a two-field {"Time":...,"Valid":...} object. The keys below are the ones every published contract has always declared.

object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
uri
required
string
clientId
required
integer format: int64
postLogoutRedirectURIs
required

The client’s sign-out redirect URIs, the addresses a sign-out may return to. Null when this collection was not loaded for the response.

Array<object>
nullable

The postLogoutRedirectURIs entries of ClientResponse: one of the client’s sign-out redirect URIs, in the shape of a redirect URI.

object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
uri
required
string
clientId
required
integer format: int64
webOrigins
required

Null when this collection was not loaded or the client has no web origins.

Array<object>
nullable

The webOrigins entries of ClientResponse. Its keys moved in the same release and for the same reason as RedirectURI above.

object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
origin
required
string
clientId
required
integer format: int64

Example

{
"client": {
"includeOpenIDConnectClaimsInAccessToken": "on",
"includeOpenIDConnectClaimsInIdToken": "on"
}
}

Invalid request body or parameters

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

Bearer challenge when token transport is malformed; ordinary validation errors omit it.

Missing or invalid access token (ACCESS_TOKEN_REQUIRED, INVALID_TOKEN), or a refused DPoP proof (INVALID_DPOP_PROOF)

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

A Bearer challenge, then a DPoP challenge naming the accepted proof algorithms, on token refusals, the error in the challenge of the scheme the token was sent with: Bearer realm="goiabada", error="invalid_token", error_description="...", DPoP realm="goiabada", algs="ES256 ...". An operation may also return a handler-level 401 without this header.

The token is valid but does not authorise this request. A caller tells the refusals apart by error_code.

INSUFFICIENT_SCOPE comes from the route’s authorisation middleware, before the handler runs: an Admin operation needs one of the scopes its route names, and an Account operation needs authserver:manage-account.

USER_CONTEXT_REQUIRED comes from the same middleware on the Account operations, which also require the token to have been issued for a user: one obtained through the client credentials grant carries no auth_time claim and is refused here.

FORBIDDEN comes from the handler, on the account endpoints that resolve a resource by id and then check it belongs to the caller, so a valid token for the wrong user reaches this rather than a 404.

CLIENT_NOT_ALLOWED comes from the route on the two Account operations only the admin console’s own client may call, deleteAccount and exportAccount. ACCOUNT_DELETION_DISABLED comes from deleteAccount while an administrator has turned off Let users delete their own account.

MANAGE_SCOPE_REQUIRED comes from the handler, on the Admin operations the administrative policy guards. Only authserver:manage creates an administrator, changes one, or changes what reaches one, so no granular scope will ever be enough: the remedy is a token holding authserver:manage, not requesting the route’s scope as for INSUFFICIENT_SCOPE. An administrator is a user, group or client holding any of the six administrative permissions (manage, admin-read, manage-users, manage-clients, manage-settings, browser-sessions), a user directly or through any of its groups, the admin console’s own client whatever it holds, and a client allowed to request the administrative scopes. A granular scope is refused here when it:

  • grants or revokes an administrative permission, directly or by moving a user into or out of a group that holds one, or deletes such a group;
  • writes to an administrator user (profile, credentials, enabled, sessions, consents, attributes, memberships, permissions, deletion), an administrative group (settings, attributes, members, permissions, deletion), or an administrator client (settings, authentication, flows, redirect URIs, sign-out redirect URIs, back-channel logout, DPoP, web origins, token settings, permissions, introspection resources, logo, deletion);
  • switches whether a client may request the administrative scopes, on or off, on any client;
  • adds the authserver resource to a client’s introspection resources;
  • reads an administrator client’s secret, or reads or sets the secret of a client listed for the authserver resource among its introspection resources;
  • sets or changes a client’s back-channel logout URI;
  • changes the email or the audit-log settings;
  • changes an administrative permission’s description. Granular scopes still read administrators. The refusal is answered after the request’s 400 and 404, writes nothing, carries the insufficient_scope challenge of the scheme the token was sent with, such as WWW-Authenticate: Bearer realm="goiabada", error="insufficient_scope", error_description="...", scope="authserver:manage", and leaves an administrator_change_refused audit record.
Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

An insufficient_scope challenge in the scheme the token was sent with, Bearer or DPoP, on every refusal but FORBIDDEN and ACCOUNT_DELETION_DISABLED, which omit it.

Resource not found

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}

The request failed inside the server, most often a storage error. error_code is INTERNAL_SERVER_ERROR: no detail about the failure, only the request id an operator can find the log line by, and retrying is reasonable. Key rotation’s 500 also answers KEY_SET_INCOMPLETE, which names its cause and no retry clears.

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}