Integrating Your Application with ZITADEL using RFC 8628 OAuth 2.0 Device Authorization Flow
ZITADEL implements device authorization as per RFC 8628. This document demonstrates its use.
This documentation aims to guide you through the process of seamlessly integrating your application with ZITADEL, leveraging the capabilities of RFC 8628. ZITADEL is a powerful identity and access management (IAM) solution that provides robust authentication and authorization services for your applications. RFC 8628, also known as "OAuth 2.0 Device Authorization Grant", offers a standardized protocol for devices with limited input capabilities to obtain user authorization. By following the steps outlined here, you'll be able to empower your application with secure authentication and access control mechanisms provided by ZITADEL, ensuring a smooth and secure user experience.
What is RFC 8628?​
RFC 8628, or the OAuth 2.0 Device Authorization Grant, defines a protocol for OAuth 2.0 clients that have limited input capabilities, such as devices with no browser or low-power sensors. It allows such devices to obtain user consent for authorizing access to protected resources by directing the user to a device-friendly authentication endpoint.
Why Integrate with Zitadel?​
ZITADEL offers a comprehensive identity and access management solution, providing features like single sign-on (SSO), multi-factor authentication (MFA), user management, and more. By integrating your application with ZITADEL, you can leverage these powerful features to enhance the security and usability of your application without reinventing the wheel.
Getting Started​
To begin integrating your application with Zitadel using RFC 8628, follow the steps outlined in this documentation. We'll walk you through the process, from setting up your application in the Zitadel console to handling user authentication and access tokens in your application code.
-
Go to “Organization”/”Projects”.
-
Under “Applications” click the “New” button.
-
Select “Native” and enter a name for the application, and click “Continue”.
-
Select “Device Code”. Click “Continue”.
-
Check the details and click “Create”.
-
Copy the “Client ID” and store it for later use.
Device Client Example​
The ZITADEL OpenID Connect client and server library written for Go has a device client example, which can behave and authenticate as a device. In order to run this client, you need a recent version of Go (>=1.20) installed on your device.
The example requires two environment variables to be set:
-
ISSUER
: server address of your instance or domain. You can find the issuer URL in the “URLs” section. In this example, it will be set to https://test-0o6zvq.zitadel.cloud. Do not use a trailing slash! -
CLIENT_ID
: the Client ID we obtained earlier.
Replace ISSUER
and CLIENT_ID
values with the ones you obtained and run the example as shown below:
ISSUER="https://test-0o6zvq.zitadel.cloud" \
CLIENT_ID="232685602728952637@device_auth" \
go run github.com/zitadel/oidc/v2/example/client/device@latest
You should see some info-level log output with response data and a line with login instructions as given below:
Please browse to https://test-0o6zvq.zitadel.cloud/device and enter code GQWC-FWFK
INFO[0002] start polling
At this point, the device app starts polling the token endpoint at 5-second intervals until the request is allowed, denied, or times out (currently 5 minutes).
Authenticate​
When you browse to the given URL and the device code is entered, the authentication flow for a user is started. If you are already logged in, it skips right ahead to the final screen where you can choose to allow or deny the request. If you are not logged in, you will have to enter your credentials for login.
When “allow” is clicked, the device (the CLI in this case) will receive a token on the next poll. A log line will be shown as given below:
INFO[0165] successfully obtained token: &{Um2W5Od0yBU0KHfhP0AD0726rXrpxlepOR7yyftMvocgMWr25pVCuca1oiSSLiQjcXQqCEA Bearer 43199 }
At this point, the program terminates as it doesn’t have any other useful purpose. Regular device apps would of course use the token to consume the actual service.
Code URL​
During the start of the authorization flow ,there is a log line printed with the complete response object from ZITADEL that looks like this:
resp&{dOcbPeysDhT26ZatRh9n7Q KPVZ-DJGG https://test-0o6zvq.zitadel.cloud/device https://test-0o6zvq.zitadel.cloud/device?user_code=GQWC-FWFK 300 5}
From this object, we used the verification_uri
and user_code
fields to print the information to the user to go to an address and enter the code. We also return a verification_uri_complete
field, which already includes the code and allows skipping manual entry of the code.
https://test-0o6zvq.zitadel.cloud/device?user_code=GQWC-FWFK
In real-life applications, this could be used to create a QR code on the device screen, and users can use their mobile phones to scan the code to go to the required URL for authentication. In the context of this example, you can restart the device example program and copy/paste the complete link instead of manually entering it.
Security considerations​
The user uses a low entropy code to link a device to their account, which is easy to brute-force. Also, the code or QR might be displayed in environments where others could observe and use the code to authenticate the device (hijack the session) to their account.
The device authorization grant specification was written with the philosophy that hijacking such sessions is not beneficial for the attacker. For example, with an on-demand streaming service, the attacker would be paying for the services the user is benefiting from. Hence, economically, the attack would not make sense.
See here for more information.
Client library​
For Go clients, the ZITADEL OIDC repository already includes device authorization in the rp
package.
Use rp.DeviceAuthorization to start the flow and receive the URL and user code. rp.DeviceAccessToken polls the token endpoint and returns the access token once it succeeds.
The client implementation is rather simple and can easily be recreated in other languages. Go can be used as an example, or simply follow the RFC as a guide.