Skip to content

Conversation

nsklikas
Copy link

Related Issue or Design Document

Adds docs for the device flow as implemented in ory/hydra#3912.

Checklist

  • I have read the contributing guidelines and signed the CLA.
  • I have referenced an issue containing the design document if my change introduces a new feature.
  • I have read the security policy.
  • I confirm that this pull request does not address a security vulnerability.
    If this pull request addresses a security vulnerability,
    I confirm that I got approval (please contact [email protected]) from the maintainers to push the changes.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added the necessary documentation within the code base (if appropriate).

Further comments

I am not sure if this is the right place to place the doc, The rest of the docs in that folder do not reference hydra configurations, but the docs in the hydra folder do not seem to document oauth2/oidc flows. Please let me know if there is a better place for it.

Copy link
Member

@vinckr vinckr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks so much, this already looks great!

left a couple of comments to bring the doc in line with our docs style guide.

content wise this looks very good - I did not test it out in practice though

@vinckr
Copy link
Member

vinckr commented Feb 21, 2025

as for the place of the doc and also place in the sidebar we can check what the best place is once its ready to merge.

@christiannwamba is currently working on a restructure of the docs, so depending on when its ready to merge we might have a different place for it.

@nsklikas
Copy link
Author

Thanks for the review @vinckr. I think I applied all of the requested changes, please have another look when you can.

@aeneasr
Copy link
Member

aeneasr commented Feb 26, 2025

We should probably add to the oauth2 quickstart this command chain as well, to try it out quickly:


code_client=$(go run . create client \
    --endpoint http://127.0.0.1:4445 \
    --grant-type authorization_code,refresh_token,urn:ietf:params:oauth:grant-type:device_code \
    --response-type code,id_token \
    --token-endpoint-auth-method none \
    --format json \
    --scope openid --scope offline \
    --redirect-uri http://127.0.0.1:5555/callback)

code_client_id=$(echo $code_client | jq -r '.client_id')
code_client_secret=$(echo $code_client | jq -r '.client_secret')

go run . perform device-code --endpoint  http://127.0.0.1:4444  --client-id $code_client_id 

Of course not with go run . but with the ory cli prefix. We'll need to release that then first and can then merge the docs, which also kinda makes sense as we need to release this stuff in any case before merging it as it would be confusing to users/customers

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there were some merge conflicts incorrectly addressed, can you please revert all non-relevant changes for this PR?

aeneasr pushed a commit to ory/hydra that referenced this pull request Feb 26, 2025
This patch introduces the OAuth 2.0 Device Authorization Grant to Ory
Hydra. The OAuth 2.0 device authorization grant is designed for
Internet-connected devices that either lack a browser to perform a
user-agent-based authorization or are input constrained to the extent
that requiring the user to input text in order to authenticate during
the authorization flow is impractical. It enables OAuth clients on such
devices (like smart TVs, media consoles, digital picture frames, and
printers) to obtain user authorization to access protected resources by
using a user agent on a separate device.

The OAuth 2.0 Device Authorization Grant may also become relevant for AI
Agent authentication flows and is generally an amazing step and
innovation for this project.

A very special thanks goes to @nsklikas from
[Canonical](https://canonical.com), @supercairos from
[shadow.tech](https://shadow.tech) and @BuzzBumbleBee.

For more details, please check out the documentation
(ory/docs#2026)

To implement this feature, you will need to implement two additional
screens in your login and consent application. A reference
implementation can be found
[here](https://github.com/ory/hydra-login-consent-node/blob/99ca6ad544f64110706c289dda74c7c622ec3110/src/routes/device.ts).

Closes #3851
Closes #3252
Closes #3230
Closes #2416
Copy link
Member

@vinckr vinckr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is looking great from my POV.

some "nits" that might improve readability, feel free to include or not.

Copy link
Member

@vinckr vinckr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm 🚀
thanks so much 🫶

@vinckr
Copy link
Member

vinckr commented Mar 25, 2025

can you take another quick look please @aeneasr ? It looks fine to me now, but I want to make sure before we merge.

@vinckr vinckr requested a review from aeneasr March 25, 2025 18:51
@aeneasr
Copy link
Member

aeneasr commented Mar 26, 2025

Yes, I think this generally is good, however this feature isn't released anywhere yet - neither in network nor oel nor open source, so I think we should merge it once that's done, which is why this is blocked

@vinckr
Copy link
Member

vinckr commented Mar 26, 2025

gotcha - i will apply the upstream label so its clear this is waiting for a release upstream to be merged.

@vinckr vinckr added the upstream Issue is caused by an upstream dependency. label Mar 26, 2025
Clarified the description of user code entropy options and their implications for user entry.
Updated the description and steps for the Device Authorization Grant to clarify the process and correct terminology.
Added an image to illustrate the device authorization flow.
Added a sequence diagram to illustrate the device authorization flow using Mermaid.
Copy link
Member

@zepatrik zepatrik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can also merge as is and refine this later, but the current state is still pretty basic. I added some ideas for improvements.
Later we should specifically add these sections or sub-pages:

  • how to get a refresh token
  • concrete use-cases and recommended configuration

Comment on lines +8 to +9
capabilities. This flow is designed for smart TVs, streaming devices, IoT hardware, printers, AI agents, and other connected devices
where typing credentials isn't practical. Here's how it works: the device to be authenticated displays a URL and a short code, prompting
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
capabilities. This flow is designed for smart TVs, streaming devices, IoT hardware, printers, AI agents, and other connected devices
where typing credentials isn't practical. Here's how it works: the device to be authenticated displays a URL and a short code, prompting
capabilities. This flow is designed for smart TVs, streaming devices, IoT hardware, printers, remote terminal sessions, AI agents, and other connected devices
where typing credentials or opening a browser isn't practical or possible. Here's how it works: the device to be authenticated displays a URL and a short code, prompting

The OAuth 2.0 Device Authorization Grant (RFC 8628) brings OAuth to devices with internet connectivity but limited input
capabilities. This flow is designed for smart TVs, streaming devices, IoT hardware, printers, AI agents, and other connected devices
where typing credentials isn't practical. Here's how it works: the device to be authenticated displays a URL and a short code, prompting
you to open that URL on your phone or computer to authorize access. The two devices don't need to communicate directly—the authorization
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
you to open that URL on your phone or computer to authorize access. The two devices don't need to communicate directly—the authorization
you to open that URL on your phone or computer to authorize access. After successful authorization, the device will get an access and (optionally) a refresh token. The two devices don't need to communicate directly—the authorization


### Step 2: Display user code and verification URI

The device shows the user the `user_code` and `verification_uri` it received from the authorization server.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The device shows the user the `user_code` and `verification_uri` it received from the authorization server.
The device shows the user the `user_code` and `verification_uri` it received from the authorization server. Depending on the device, this can be in form of a URL, QR-code, acoustically, or any other form that the device can communicate with the user.

- `device_code`: The device code returned from the authorization request
- `grant_type`: This must always be `urn:ietf:params:oauth:grant-type:device_code`

After the user grants permission, the authenicaton server sends an access token to the device, which is used to access the protected resource.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
After the user grants permission, the authenicaton server sends an access token to the device, which is used to access the protected resource.
After the user grants their consent, the authentication server sends an access token to the device, which is used to access the protected resource.

Comment on lines +104 to +108
```
urls:
device:
verification: http://path/to/device/verification/ui
success: http://path/to/device/success
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```
urls:
device:
verification: http://path/to/device/verification/ui
success: http://path/to/device/success
```yaml
urls:
device:
# The verification UI is where the user inputs the user-code
verification: http://path/to/device/verification/ui
# The success UI is where the user is send to after successful authorization
success: http://path/to/device/success

Comment on lines +116 to +118
- `high`: `user_code` is 8 characters long and consists of alphanumeric characters, excluding some ambiguous symbols
- `medium`: `user_code` is 8 characters long and consists of only upper case alphabetic characters
- `low`: `user_code` is 9 characters long and consists of only numberic characters
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just considering whether we should make this fully configurable (length and character set). It is pretty important for the security and UX to get this right. It is suggested to only use characters that can be unambiguously displayed by the device, which can be quite limited e.g. on a 7-segment display. Potentially this even has to be configurable on a per-client level. Maybe we keep this approach as a "fallback" option and implement the fully configurable variant per-client.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now added this, as it was quite trivial. The key now changed from oauth2.device_authorization.user_code_entropy to oauth2.device_authorization.user_code.entropy_preset. Additionally, I added oauth2.device_authorization.user_code.length and oauth2.device_authorization.user_code.character_set.

- `medium`: `user_code` is 8 characters long and consists of only upper case alphabetic characters
- `low`: `user_code` is 9 characters long and consists of only numberic characters

As users will need to manually enter the user code, the higher the entropy, the more difficult it will be for the user to enter the user code.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
As users will need to manually enter the user code, the higher the entropy, the more difficult it will be for the user to enter the user code.
It is important to strike the right balance between security and user-experience here. Higher entropy enhances security and protects against an attacker randomly guessing valid user-codes.
This is especially important the more concurrent device flows are being performed.
As users will need to manually enter the user code, the higher the entropy, the more difficult it will be for the user to enter the user code.
This is not of any concern when the user doesn't need to input the user-code manually, e.g. by scanning a QR-code. On the other side, ambiguous characters should be avoided (e.g. `O` and `0` on any display, or `1` and `7` on a 7-segment display).

### Configuring user code entropy

Depending on your security needs and your traffic load, you should choose the appropriate `user_code` entropy. The
`oauth2.device_authorization.user_code_entropy` configuration supports 3 values:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`oauth2.device_authorization.user_code_entropy` configuration supports 3 values:
`oauth2.device_authorization.user_code.entropy_preset` configuration supports 3 values:

- `high`: `user_code` is 8 characters long and consists of alphanumeric characters, excluding some ambiguous symbols
- `medium`: `user_code` is 8 characters long and consists of only upper case alphabetic characters
- `low`: `user_code` is 9 characters long and consists of only numberic characters

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
It is also possible to configure the length and character set directly:
```yaml
oauth2:
device_authorization:
user_code:
length: 8
character_set: abcdefghijklmnopqrstuvwxyz0123456789

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

upstream Issue is caused by an upstream dependency.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants