Open bpieck opened 5 years ago
Looks interesting, @bpieck ! It would be great to have this in Doorkeeper :heart:
Ok, thanks, my colleague Dan Shi will propose a PR in near future :)
I would love to integrate this feature in my application as well @bpieck :)
@Blume73: We have already some implementation here: https://github.com/x-ion-de/doorkeeper/tree/draft-ietf-oauth-device-flow-15 Maybe you like to have a look into how to use it and give some feedback?
Dan Shi will post here some documentation about how to use it in near future.
@Blume73
here is a brief walkthrough for the flow. Looking forward to your feedback :)
Use generator to create all necessary tables:
rails generate doorkeeper:migration
To enable device flow, run:
rails generate doorkeeper:device_code_grant
This generator will modify some existing columns and add some new ones that comply with the device flow.
In Doorkeeper configuration initializer, enable the device flow:
grant_flows %w[urn:ietf:params:oauth:grant-type:device_code]
In addition, one can configure the polling interval and format of the use code in initializer.
# Configurations for device grant flow
#
# The polling interval configures how often the client should poll the access token from
# authorization server. The default value is 5 seconds
#
device_code_polling_interval 5
#
# The user code can be composed of letters, digits and hyphens.
# For example: "4d-6w" means a user code format with 4 digits and 6 letters joined by a hyphen.
# In case you need both digits and letters for the user code and hyphen is not used to separate
# letters and digits, which mismatches the accepted format, the default "4w-4w" will be applied.
#
user_code_format '4w-4w'
POST /oauth/authorize_device
Content-Type: application/x-www-form-urlencoded
client_id=<applicatio uid>
the response example is as follows:
"device_code":"54765a4bc22f30e8d867b93b24fc24d4",
"user_code":"309349",
"verification_uri":"https://example.com/oauth/device",
"verification_uri_complete":"https://example.com/oauth/device/309349",
"interval":5,
"expired_in":300
start polling token with client id and device code in a time interval given from step 2
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=<device_code>&client_id=<client_id>
After the device is authroized, response will give an access token back.
use the verification_uri or verification_uri_complete from step 2 to authorize the device
Thank you very much for the hard work you have put in so far. I will try to integrate this feature to my project and give you my feedback as soon as possible.
thanks, take your time, no pressure. It's just great to get some feedback before we open a PR.
Hi guys! I don't have much time right now, so I can't fully check it :( I take a quick look at the implementation and it seems good, but need a deeper analyze.
So feel free to discuss and propose a PR, I'll return to it when I will be not so busy :+1: :bowing_man:
I opened the PR for discussion.
@bpieck I'm sending a post to /oauth/authorize_device. After that, I'm receiving a response like you showed as an example. With the device_code and the client_id I start polling the token. But I'm not receiving any access token back. The response of that post is looking similar to the response of point 2.
Using Inosmnia, I make a post request to /oauth/authorize_device with the parameters grant_type, device_code and client_id.
I'm also trying to make a post only with the parameter grant_type. For that I'm receiving an invalid_client error.
I'm doing something wrong or how can I receive the access token?
Hi @Blume73 In case you had 'authoization_pending' back by polling the token, you should go step 4 to authorize the device first before you can get a valid token.
@ddanshi First I Send a post to /oauth/authorize_device. After receiving the user code, i go to the URL and paste the user code there. Everything is looking fine. But after I send a second post to /oauth/authorize_device I receive the same answer as in the first post. A new user_code and a new device_code.
Request POST /oauth/authorize_device Content-Type: application/x-www-form-urlencoded client_id=0a4dd341999470dfe41408a6bae1cc90f5743751750721
Response "devicecode":"Qp93qzn88tYskgNPR-PlVagLorhBKmh_sa7NKOmYi4", "user_code":"236-783", "verification_uri":"http://localhost:3001/oauth/device", "verification_uri_complete":"http://localhost:3001/oauth/device/236-783", "interval":5, "expired_in":300
User interactio I go to he verification_uri and authorize through code
Request POST /oauth/authorize_device Content-Type: application/x-www-form-urlencoded grant_type=urn:ietf:params:oauth:grant-type:device_code devicecode=Qp93qzn88tYskgNPR-PlVagLorhBKmh_sa7NKOmYi4 client_id=0a4dd341999470dfe41408a6bae1cc90f5743751750721
And now the respond looks like thiks:
@Blume73 This is so far expected. Every POST request with a valid client id will create a new access grant, which means a new device_code and a new user_code. We could of course check the old access grant's validity before creating a new one. In that case we may then have to calculate the real value of expired_in. Not sure whether we would obtain great benefits from that.
Thank you @ddanshi.
After the device is authroized, response will give an access token back.
Where i can find the access token, which endpoint i have to poll?
ah sorry! I put the wrong endpoint above. For polling it must be /oauth/token instead of /oauth/authorize_device.
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=<device_code>&client_id=<client_id>
I have corrected it :)
@ddanshi now everything is working, perfect! :+1:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
I checked the implementation here - https://github.com/x-ion-de/doorkeeper/tree/draft-ietf-oauth-device-flow-15 - and it seems to me that recently merged #1418 could help to extract this grant flow intro an extension
Hi, thanks for mentioning. But currently with kids at home while doing Homeoffice and having to prepare to move, I think I will not find time to check it. But ok, let me try this weekend to have at least a look into my wip branch, which I did not touch for half a year. And maybe I try to do some modifications. If I get anything working, I will at least push the current state somewhere.
Oh, now worries @bpieck , I just posted it FYI. Do (if you're want and interested in that) whenever you have time :) I totally understand you. If you need any help from me - just let me know.
it seems to me that recently merged #1418 could help to extract this grant flow intro an extension
The extend mechanism is great! Quite curious about how to implement device code flow. I will take it a try, too (based on the drafted works)
Based on https://github.com/x-ion-de/doorkeeper/commit/c87f7cd73d27efc8b81a703631f352fe4c42179d I see something like this:
DeviceAuthorizationsController
and DeviceCodesController
with viewsurn:ietf:params:oauth:grant-type:device
) using new mechanism (it's pseudocode for now):
# re-review what this grant requires to work (so that Doorkeeper will find it then try to resolve the grant strategy)
Doorkeeper::GrantFlow.register :device_code,
response_type_strategy: Doorkeeper::ExtensionName::DeviceResponse,
grant_type_matches: 'urn:ietf:params:oauth:grant-type:device_code',
grant_type_strategy: Doorkeeper::ExtensionName::DeviceCodeRequest
# in engine railtie
ActiveSupport.on_load(:active_record) do
Doorkeeper.config.access_grant_model.prepend Doorkeeper::ExtensionName::AccessGrantMixin
end
Maybe something more, it's hard to say right now.
For those who interested I can create a new repo under doorkeeper-gem organization and add you guys as collaborators. Just give me your thoughts about the name for the new extension :) And then we could continue to work on it there
We at EXOP have been using an in-house implementation of the device authorization grant based on some ideas discussed here since late 2019 to allow enterprise users to log in to our apps.
Since quite a few people have expressed their interest in this, we have decided to make our work public. Check it out at https://rubygems.org/gems/doorkeeper-device_authorization_grant.
This does not use the grant flow registration mechanism from https://github.com/doorkeeper-gem/doorkeeper/pull/1418 yet, but we will change that once the next version of Doorkeeper is released.
If you are interested, the best place to get started is probably the example app at https://github.com/exop-group/doorkeeper-device-flow-example.
GitLab uses doorkeeper. Device flow would be useful for GitLab support in git-credential-manager https://gitlab.com/gitlab-org/gitlab/-/issues/225215 https://github.com/GitCredentialManager/git-credential-manager/issues/589
@irminsul now that https://github.com/exop-group/doorkeeper-device_authorization_grant/ is version 1.0 can this issue be closed?
@hickford: Yes, I think this can be closed.
This is not about an issue in doorkeeper. We were requested to implement the Device Authorization Grant draft for oauth: https://tools.ietf.org/html/draft-ietf-oauth-device-flow-15
We currently are in a mode of refactoring. Now I would be interested if you are interested in this flow and would like to see a PR for doorkeeper. If so, we would consider this in our refactoring work. If not - work on our side is less. But of course we'd like to share this work, if anyone is interested in it.