mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-06 14:22:15 +00:00
## Todos for release - [x] Configure Env in docs project on vercel - [x] Configure Root Path in the docs project on vercel - [ ] Remove old CSP https://github.com/zitadel/website/pull/1592 ## What we did This pull request migrates the project documentation from the old `docs/` directory to the new `apps/docs/` directory, introduces a new documentation system built with Next.js and Fumadocs, and updates all relevant references, configuration files, and documentation to reflect this change. It also adds new configuration and ignore files for the new documentation app, updates CI and linting to exclude the new docs from certain checks, and revises the contributing guidelines accordingly. **Documentation System Migration and New Docs App** * Migrated all documentation from `docs/` to `apps/docs/`, and updated all references in `README.md`, `CONTRIBUTING.md`, and other files to point to the new location. [[1]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L585-L640) [[2]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L660-R607) [[3]](diffhunk://#diff-eca12c0a30e25b4b46522ebf89465a03ba72a03f540796c979137931d8f92055L740-R687) [[4]](diffhunk://#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5L2-R3) [[5]](diffhunk://#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5L30-R30) * Added a new Next.js/Fumadocs-based documentation app under `apps/docs/`, including core app files, layouts, routing, search API, and a comprehensive `README.md` with development and contribution instructions. [[1]](diffhunk://#diff-5a1b07344a2c1b4d3f37b23ff1388b62cd9f57dea3c1cd23d8a0412b7602b132R1-R74) [[2]](diffhunk://#diff-462b9ad1eabbb7d1c29bb9c36e4931eb180fd7190900e6d2babf8f4d66ad1c28R1-R39) [[3]](diffhunk://#diff-e16ae25660ded787b10ac35dea96d5ecaacf895dae0afc8a9bd4382dc79a8c87R1-R7) [apps/docs/app/[[...slug]]/layout.tsxR1-R81](diffhunk://#diff-59e08acde4e805b7aeccef1dcf98f1d71dfc550777e6b9402085cee0e9fa4e0aR1-R81), [apps/docs/app/[[...slug]]/page.tsxR1-R79](diffhunk://#diff-e5df3f80d0fa01e12d63d81f29c57a9d14e846c78fd3beabb2ef768e38fd9580R1-R79), [[4]](diffhunk://#diff-389b34918e040cacaa87cd7201ffa462cc2b0b716736f537e3d3c660ac69353bR1-R7) [[5]](diffhunk://#diff-d3b03416d1c457b19f1c27b26f2db741412df841b875c26ccadc36e4522247f4R1-R29) [[6]](diffhunk://#diff-c8fb8339570a5305809be7c618e14705fd86390dc278e6ce8ba224a7bc8b0c3cR1-R25) **Configuration and Tooling Updates** * Updated `.github/workflows/codeql.yml`, `.golangci.yaml`, and `.github/dependabot.yml` to properly handle the new docs app: excluded `apps/docs` from certain checks, added npm dependency updates for the docs app, and excluded generated content. [[1]](diffhunk://#diff-12783128521e452af0cfac94b99b8d250413c516ec71fe6d97dbea666ff7ba27L8-R14) [[2]](diffhunk://#diff-9917ddc9f1c3304218f7269265b746d997c5c0615478177b5fceecd33ef47cb5R5-R6) [[3]](diffhunk://#diff-9917ddc9f1c3304218f7269265b746d997c5c0615478177b5fceecd33ef47cb5R126-R129) [[4]](diffhunk://#diff-dd4fbda47e51f1e35defb9275a9cd9c212ecde0b870cba89ddaaae65c5f3cd28R89-R106) * Updated `.devcontainer/devcontainer.json` to use the latest Go 1.25.3 version for consistency. **Licensing and Miscellaneous** * Added `apps/docs/` to the list of licensed directories in `LICENSING.md`. These changes ensure the documentation is now maintained in a modern, scalable system and all project tooling is updated to support the new structure. --------- Co-authored-by: Federico Coppede <[email protected]>
177 lines
11 KiB
Plaintext
177 lines
11 KiB
Plaintext
---
|
|
title: OIDC Back-Channel Logout
|
|
sidebar_label: Back-Channel Logout
|
|
---
|
|
|
|
The Back-Channel Logout implements [OpenID Connect Back-Channel Logout 1.0](https://openid.net/specs/openid-connect-backchannel-1_0.html)
|
|
and can be used to notify clients about session termination at the OpenID Provider. This guide will explain how
|
|
back-channel logout is implemented inside ZITADEL and gives some usage examples.
|
|
|
|
<Callout type="info">
|
|
Back-Channel Logout is currently an experimental [beta](https://help.zitadel.com/zitadel-software-release-cycle#beta) feature.
|
|
Be sure to enable it on the [feature API](#feature-api) before using it.
|
|
We highly recommend also enabling the `webkey` feature on your instance. This will prevent issues with automatic key rotation.
|
|
</Callout>
|
|
|
|
In this guide we assume your already familiar with getting and validation token. You should already have a good
|
|
understanding on the following topics before starting with this guide:
|
|
|
|
- Integrate your app with the [OIDC flow](/guides/integrate/login/oidc/login-users) to obtain tokens
|
|
- [Claims](/apis/openidoauth/claims)
|
|
- [Scope](/apis/openidoauth/scopes)
|
|
- Audience
|
|
|
|
## Concept
|
|
|
|
ZITADEL provides the possibility for OpenID Connect clients to be notified about the session termination, for example
|
|
if a user signs out from another client using the same SSO session.
|
|
This allows the client to also invalidate the user's session without the need for an active browser session.
|
|
|
|

|
|
|
|
1. When an unauthenticated user visits your application,
|
|
2. it will create an authorization request to the authorization endpoint.
|
|
3. The Authorization Server (ZITADEL) will send an HTTP 302 to the user's browser, which will redirect them to the login UI.
|
|
4. The user will have to authenticate using the demanded auth mechanics.
|
|
5. Your application will be called on the registered callback path (redirect_uri) for the authorization code exchange.
|
|
See [OIDC Flow](/guides/integrate/login/oidc/login-users) for more details.
|
|
On successful exchange, an SSO session will be created.
|
|
6. If the user opens another application,
|
|
7. the application will also create an authorization request to the authorization endpoint.
|
|
8. ZITADEL can then reuse the existing SSO session and will not ask the user to authenticate again and directly return the code for exchange.
|
|
See [OIDC Flow](/guides/integrate/login/oidc/login-users) again for details.
|
|
9. At a later point, the user signs out from one of the applications, in this case the second one.
|
|
10. The application will redirect the user to the end_session endpoint.
|
|
11. ZITADEL will terminate the SSO session and redirect the user back to the application's post_logout_redirect_uri.
|
|
The application can delete the local session.
|
|
12. ZITADEL will also send a back-channel logout request to every registered application with previously opened sessions.
|
|
The application can then invalidate the user's session without the need for an active browser session.
|
|
|
|
### Indicating Support
|
|
|
|
As required by the [specification](https://openid.net/specs/openid-connect-backchannel-1_0.html#BCSupport), ZITADEL
|
|
will advertise the `backchannel_logout_supported` and `backchannel_logout_session_supported`
|
|
on the discovery endpoint once the feature flag is enabled.
|
|
The latter boolean indicates, that ZITADEL will provide a session ID (`sid`) claim as part of the logout token. This
|
|
provides the possibility to match the exact SSO session, which was terminated.
|
|
|
|
### Client
|
|
|
|
To enable the back-channel logout on a client, they simply need to register a `backchannel_logout_uri` as part of their
|
|
configuration, e.g. [creating an OIDC application](https://zitadel.com/docs/reference/api/management/management-service-add-oidc-app).
|
|
|
|
As soon as the URI is set, every new authorization request will register a back-channel notification to be sent once
|
|
the session is terminated by a user sign out.
|
|
|
|
## Back-Channel Request
|
|
|
|
When the session is terminated, ZITADEL will send back-channel logout requests asynchronously to every registered
|
|
client of the corresponding session.
|
|
The request is an `application/x-www-form-urlencoded` POST request to the registered URI including a `logout_token`
|
|
parameter in the body.
|
|
|
|
Please be aware that body *may* contain other values in addition to logout_token. Values that are not understood by the
|
|
implementation *must* be ignored.
|
|
|
|
### Logout Token
|
|
|
|
The `logout_token` sent in the request is a JWT similar to an ID Token.
|
|
|
|
<Callout>
|
|
Note however, that a Logout Token must never contain a `nonce` claim, to make sure it cannot be used as an ID Token.
|
|
</Callout>
|
|
|
|
The following Claims are used within the Logout Token:
|
|
|
|
| Claim | Example | Description |
|
|
|--------|----------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
|
|
| iss | `${CUSTOM_DOMAIN}` | Issuer Identifier |
|
|
| sub | `77776025198584418` | Subject Identifier (the user who signed out) |
|
|
| aud | `69234237810729019` | Audience(s), will always contain your client_id |
|
|
| iat | `1311280970` | Issued at time |
|
|
| exp | `1311281970` | Expiration time (by default 15min after the issued at time) |
|
|
| jti | `69234237813329048` | Unique identifier for the token |
|
|
| events | `{ "http://schemas.openid.net/event/backchannel-logout": {} }` | JSON object, which always contains http://schemas.openid.net/event/backchannel-logout. This declares that the JWT is a Logout Token. |
|
|
| sid | `291693710356251044` | Session ID - String identifier for a Session. |
|
|
|
|
#### Validation
|
|
|
|
Verify the Logout Token the same way you verify an ID Token including signature validation, issuer, audience, expiration and issued at time claim checks.
|
|
Make sure that either a subject (`sub`) and / or a session ID (`sid`) is present in the token to identify the user or its session.
|
|
Also, check that the `events` claim contains the `http://schemas.openid.net/event/backchannel-logout` value.
|
|
Optionally, you can also verify that the TokenID (`jti`) has not been used before.
|
|
|
|
For details on how to validate the logout token, please refer to the [OpenID Connect Back-Channel Logout specification](https://openid.net/specs/openid-connect-backchannel-1_0.html#Validation).
|
|
|
|
## Example
|
|
|
|
This example assumes that your application is registered with client_id `243864426485212395@example` and the back-channel logout
|
|
URI is set to `https://example.com/logout`.
|
|
|
|
### Authentication
|
|
|
|
When the user signed in to your application, ZITADEL issued the following id_token:
|
|
```
|
|
eyJhbGciOiJSUzI1NiIsImtpZCI6IjI5NjkzMzA1NjAxNzY0Nzg3NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJzdWIiOiIxNjQ4NDk0OTQyOTc0NzczNzciLCJhdWQiOlsiMjQzODY0NDI2NDg1MjEyMzk1QGV4YW1wbGUiLCIyNDM4NjQzODExNjk4ODY0NDMiXSwiZXhwIjoxNzMzNzgyNDQ0LCJpYXQiOjE3MzM3MzkyNDQsImF1dGhfdGltZSI6MTczMzczOTI0NCwiYW1yIjpbInVzZXIiLCJtZmEiXSwiYXpwIjoiMjQzODY0NDI2NDg1MjEyMzk1QGV4YW1wbGUiLCJjbGllbnRfaWQiOiIyNDM4NjQ0MjY0ODUyMTIzOTVAZXhhbXBsZSIsImF0X2hhc2giOiJSWVFPSkJuT01LS0hrN1VnLWY1eFJnIiwic2lkIjoiVjFfMjk3MzY0ODE4OTgwMDM0MDA0In0K.lZxHE_Z4tiaDQE-DPtYjnvb0H9rz4wMoGfBMeEm4EG837DGJb7RTq7PuMHWc4Z2e_6lilwfVBWDEOhmrnjmkQwDVxInbbJfN0NiWgeqoW-C1SZ_G00UVIbJdaxPy2-haRihDNNpy0Gjmi7q3FkGXGqkJx9S7ZtC5ISbXLnqfbRbuapoMs7hHNf-Iltf8v7dMs3K8dcAPSHJm0X0x6Cu1ZMeAS2a6H05xKXGM0bRK830AZlL8xmxTNj_q_WZKzxz304XrRNHvYRcHKmJqURSHvRNUR38QeNaiKzINlV2sVvPEY6Dru_PHSPNFu7YLWiUi34VUla6VTxy9ctI_BtI4nw
|
|
```
|
|
|
|
This represents the following claims:
|
|
```json
|
|
{
|
|
"iss": "http://localhost:8080",
|
|
"sub": "164849494297477377",
|
|
"aud": [
|
|
"243864426485212395@example",
|
|
"243864381169886443"
|
|
],
|
|
"exp": 1733782444,
|
|
"iat": 1733739244,
|
|
"auth_time": 1733739244,
|
|
"amr": [
|
|
"user",
|
|
"mfa"
|
|
],
|
|
"azp": "243864426485212395@example",
|
|
"client_id": "243864426485212395@example",
|
|
"at_hash": "RYQOJBnOMKKHk7Ug-f5xRg",
|
|
"sid": "V1_297364818980034004"
|
|
}
|
|
```
|
|
|
|
As you can see, the `sid` claim is present in the token. This represents the application's specific session ID of the
|
|
user session.
|
|
|
|
### Sign Out and Back-Channel Logout
|
|
|
|
When the user signs out from another application, ZITADEL will send a POST request to `https://example.com/logout` with
|
|
the following body:
|
|
|
|
```http
|
|
POST /logout HTTP/1.1
|
|
Host: example.com
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
logout_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjI5NjkzMzA1NjAxNzY0Nzg3NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJzdWIiOiIxNjQ4NDk0OTQyOTc0NzczNzciLCJhdWQiOlsiMjQzODY0NDI2NDg1MjEyMzk1QGV4YW1wbGUiXSwiaWF0IjoxNzMzNzM5MjUyLCJleHAiOjE3MzM3NDAxNTMsImp0aSI6IjI5NzM2NDgzNDQ5ODkyMTEzNyIsImV2ZW50cyI6eyJodHRwOi8vc2NoZW1hcy5vcGVuaWQubmV0L2V2ZW50L2JhY2tjaGFubmVsLWxvZ291dCI6e319LCJzaWQiOiJWMV8yOTczNjQ4MTg5ODAwMzQwMDQifQo.ELOPuS61fy8GgCKEtru5df4-9GI4-KQlNf_DMp6b5mtJZIrfykA_M7lYOxOskYhTDicBoQ2jjOjzsDqktI4r6ptD068c5LEOx-k2OVk7ybADsK7tht5omYy4tsbHmkDCZN065WMH0SQH7NKGroVW-MACi6Peuiz3nlQsfho0EnLECqhZT60qxu6qtofvBVhHe15Zlkzffy0vxjKEIeJoTmX_cNVsHlrC_n1vTqZStBrkqu3_rwZxZuynX47vf7_kj_kKhJ3TffRF561n1AP5xnhZ9i--rnaucbGtGGImlKi2sdqC4GzjtdlaKJaRuVF-91x758SLBxqJXPucroJoWw
|
|
```
|
|
|
|
```json
|
|
{
|
|
"iss": "http://localhost:8080",
|
|
"sub": "164849494297477377",
|
|
"aud": [
|
|
"243864426485212395@example"
|
|
],
|
|
"iat": 1733739252,
|
|
"exp": 1733740153,
|
|
"jti": "297364834498921137",
|
|
"events": {
|
|
"http://schemas.openid.net/event/backchannel-logout": {}
|
|
},
|
|
"sid": "V1_297364818980034004"
|
|
}
|
|
```
|
|
|
|
After validating the token, the application can now invalidate the user's local session based on the `sid` claim.
|
|
|
|
Some applications might also want to delete all user sessions. In this case, the `sub` claim can be used to identify the user.
|