mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-13 17:35:12 +00:00
## What
Shorten the `title` frontmatter on 20 docs pages so that the rendered
`<title>` tag stays within the 70-character SEO limit.
The root layout appends ` | ZITADEL Docs` (15 chars) to every page
title, meaning the raw frontmatter `title` must be ≤ 55 characters. A
site scan flagged all 20 pages for the "Title too long" warning (titles
ranged from 71 to 92 characters in the final rendered tag).
## Why
Search engines may truncate or ignore `<title>` tags longer than 70
characters, hurting click-through rates and keyword relevance in search
results.
## How
Each title was rewritten to:
- Fit within 55 characters (leaving room for ` | ZITADEL Docs`)
- Front-load the primary search keyword (product name, protocol, or
feature)
- Include "ZITADEL" where users realistically search for `{feature}
ZITADEL`
- Avoid generic filler words ("Configure", "Set up", "Support for")
All 20 files already have a `sidebar_label` field that preserves the
original descriptive title for sidebar navigation — no navigation
changes result from this PR.
## Pages updated
| Page | Before (chars) | After (chars) |
|---|---|---|
| concepts/features/passkeys | 82 | 64 |
| guides/integrate/identity-providers/openldap | 72 | 58 |
| guides/solution-scenarios/b2b | 78 | 59 |
| guides/integrate/services/cloudflare-oidc | 86 | 54 |
| guides/integrate/login/hosted-login | 71 | 55 |
| guides/integrate/service-accounts/private-key-jwt | 76 | 56 |
| guides/integrate/service-accounts/client-credentials | 78 | 60 |
| guides/integrate/services/google-cloud | 92 | 57 |
| guides/solution-scenarios/saas | 88 | 65 |
| guides/migrate/sources/auth0 | 73 | 65 |
| guides/integrate/login-ui/oidc-standard | 81 | 55 |
| guides/integrate/login-ui/username-password | 73 | 59 |
| guides/integrate/login-ui/device-auth | 78 | 60 |
| guides/integrate/identity-providers/linkedin_oauth | 72 | 58 |
| guides/integrate/identity-providers/pingfederate-saml | 74 | 61 |
| guides/integrate/service-accounts/personal-access-token | 82 | 62 |
| legal/service-description/cloud-service-description | 76 | 61 |
| guides/integrate/login/login-users | 83 | 55 |
| guides/integrate/identity-providers/migrate | 74 | 65 |
| guides/manage/console/projects-overview | 71 | 62 |
All final `<title>` values are between 54 and 66 characters (well under
the 70-char limit).
167 lines
7.2 KiB
Plaintext
167 lines
7.2 KiB
Plaintext
---
|
|
title: Device Authorization Grant in Custom Login UI
|
|
description: "Implement the OAuth 2.0 Device Authorization Grant in your custom login UI for browserless devices."
|
|
sidebar_label: Device Authorization
|
|
---
|
|
|
|
In case one of your applications requires the [OAuth2 Device Authorization Grant](/guides/integrate/login/oidc/device-authorization) this guide will show you how to implement
|
|
this in your application as well as the custom login UI.
|
|
|
|
The following flow shows you the different components you need to enable OAuth2 Device Authorization Grant for your login.
|
|

|
|
|
|
1. Your application makes a device authorization request to your login UI
|
|
2. The login UI proxies the request to ZITADEL.
|
|
3. ZITADEL parses the request and does what it needs to interpret certain parameters (e.g., organization scope, etc.)
|
|
4. ZITADEL returns the device authorization response
|
|
5. Your application presents the `user_code` and `verification_uri` or maybe even renders a QR code with the `verification_uri_complete` for the user to scan
|
|
6. Your application starts a polling mechanism to check if the user has approved the device authorization request on the token endpoint
|
|
7. When the user opens the browser at the verification_uri, he can enter the user_code, or it's automatically filled in, if they scan the QR code
|
|
8. Request the device authorization request from the ZITADEL API using the user_code
|
|
9. Your login UI allows to approve or deny the device request
|
|
10. In case they approved, authenticate the user in your login UI by creating and updating a session with all the checks you need.
|
|
11. Inform ZITADEL about the decision:
|
|
1. Authorize the device authorization request by sending the session and the previously retrieved id of the device authorization request to the ZITADEL API
|
|
2. In case they denied, deny the device authorization from the ZITADEL API using the previously retrieved id of the device authorization request
|
|
12. Notify the user that they can close the window now and return to the application.
|
|
13. Your applications request to the token endpoint now receives the tokens or an error if the user denied the request.
|
|
|
|
## Example
|
|
|
|
Let's assume you host your login UI on the following URL:
|
|
```
|
|
https://login.example.com
|
|
```
|
|
|
|
## Device Authorization Request
|
|
|
|
A user opens your application and is unauthenticated, the application will create the following request:
|
|
```http
|
|
POST /oauth/v2/device_authorization HTTP/1.1
|
|
Host: login.example.com
|
|
Content-type: application/x-www-form-urlencoded
|
|
|
|
client_id=170086824411201793&
|
|
scope=openid%20email%20profile
|
|
```
|
|
|
|
The request includes all the relevant information for the OAuth2 Device Authorization Grant and in this example we also have some scopes for the user.
|
|
|
|
You now have to proxy the auth request from your own UI to the device authorization Endpoint of ZITADEL.
|
|
For more information, see [OIDC Proxy](./login-app#oidc-proxy) for the necessary headers.
|
|
|
|
<Callout>
|
|
The version and the optional custom URI for the available login UI is configurable under the application settings.
|
|
</Callout>
|
|
|
|
The endpoint will return the device authorization response:
|
|
```json
|
|
{
|
|
"device_code": "0jbAZbU3ClK-Mkt0li4U1A",
|
|
"user_code": "FWRK-JGWK",
|
|
"verification_uri": "https://login.example.com/device",
|
|
"verification_uri_complete": "https://login.example.com/device?user_code=FWRK-JGWK",
|
|
"expires_in": 300,
|
|
"interval": 5
|
|
}
|
|
```
|
|
|
|
The device presents the `user_code` and `verification_uri` or maybe even render a QR code with the `verification_uri_complete` for the user to scan.
|
|
|
|
Your login will have to provide a page on the `verification_uri` where the user can enter the `user_code`, or it's automatically filled in, if they scan the QR code.
|
|
|
|
### Get the Device Authorization Request by User Code
|
|
|
|
With the user_code entered by the user you will now be able to get the information of the device authorization request.
|
|
[Get Device Authorization Request Documentation](/reference/api/oidc/zitadel.oidc.v2.OIDCService.GetDeviceAuthorizationRequest)
|
|
|
|
```bash
|
|
curl --request GET \
|
|
--url https://${CUSTOM_DOMAIN}/v2/oidc/device_authorization/FWRK-JGWK \
|
|
--header 'Authorization: Bearer '"$TOKEN"''
|
|
```
|
|
|
|
Response Example:
|
|
|
|
```json
|
|
{
|
|
"deviceAuthorizationRequest": {
|
|
"id": "XzNejv6NxqVU8Qur5uxEh7f_Wi1p0qUu4PJTJ6JUIx0xtJ2uqmU",
|
|
"clientId": "170086824411201793",
|
|
"scope": [
|
|
"openid",
|
|
"profile"
|
|
],
|
|
"appName": "TV App",
|
|
"projectName": "My Project"
|
|
}
|
|
}
|
|
```
|
|
|
|
Present the user with the information of the device authorization request and allow them to approve or deny the request.
|
|
|
|
### Perform Login
|
|
|
|
After you have initialized the OIDC flow you can implement the login.
|
|
Implement all the steps you like the user the go trough by [creating](/reference/api/session/zitadel.session.v2.SessionService.CreateSession) and [updating](/reference/api/session/zitadel.session.v2.SessionService.SetSession) the user-session.
|
|
|
|
Read the following resources for more information about the different checks:
|
|
- [Username and Password](./username-password)
|
|
- [External Identity Provider](./external-login)
|
|
- [Passkeys](./passkey)
|
|
- [Multi-Factor](./mfa)
|
|
|
|
### Authorize the Device Authorization Request
|
|
|
|
To finalize the auth request and connect an existing user session with it, you have to update the auth request with the session token.
|
|
On the create and update user session request you will always get a session token in the response.
|
|
|
|
The latest session token has to be sent to the following request:
|
|
|
|
Read more about the [Authorize or Deny Device Authorization Request Documentation](/reference/api/oidc/zitadel.oidc.v2.OIDCService.AuthorizeOrDenyDeviceAuthorization)
|
|
|
|
Make sure that the authorization header is from an account which is permitted to finalize the Auth Request through the `IAM_LOGIN_CLIENT` role.
|
|
```bash
|
|
curl --request POST \
|
|
--url ${CUSTOM_DOMAIN}/v2/oidc/device_authorization/XzNejv6NxqVU8Qur5uxEh7f_Wi1p0qUu4PJTJ6JUIx0xtJ2uqmU \
|
|
--header 'Accept: application/json' \
|
|
--header 'Authorization: Bearer '"$TOKEN"''\
|
|
--header 'Content-Type: application/json' \
|
|
--data '{
|
|
"session": {
|
|
"sessionId": "225307381909694508",
|
|
"sessionToken": "7N5kQCvC4jIf2OuBjwfyWSX2FUKbQqg4iG3uWT-TBngMhlS9miGUwpyUaN0HJ8OcbSzk4QHZy_Bvvv"
|
|
}
|
|
}'
|
|
```
|
|
|
|
If you don't get any error back, the request succeeded, and you can notify the user that they can close the window now and return to the application.
|
|
|
|
### Deny the Device Authorization Request
|
|
|
|
If the user denies the device authorization request, you can deny the request by sending the following request:
|
|
|
|
```bash
|
|
curl --request POST \
|
|
--url ${CUSTOM_DOMAIN}/v2/oidc/device_authorization/ \
|
|
--header 'Accept: application/json' \
|
|
--header 'Authorization: Bearer '"$TOKEN"''\
|
|
--header 'Content-Type: application/json' \
|
|
--data '{
|
|
"deny": {}
|
|
}'
|
|
```
|
|
|
|
If you don't get any error back, the request succeeded, and you can notify the user that they can close the window now and return to the application.
|
|
|
|
### Device Authorization Endpoints
|
|
|
|
All OAuth2 Device Authorization Grant endpoints are provided by ZITADEL. In your login UI you just have to proxy them through and send them directly to the backend.
|
|
|
|
These endpoints are:
|
|
- Well-known
|
|
- Device Authorization Endpoint
|
|
- Token
|
|
|
|
Additionally, we recommend you to proxy all the other [OIDC relevant endpoints](./oidc-standard#oidc-endpoints).
|