Skip to content

Commit 73a6e18

Browse files
committed
Add docs for device flow
1 parent 8fafe7e commit 73a6e18

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

docs/internals.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,75 @@ stateDiagram-v2
104104
```
105105

106106
> **Note** This file is automatically generated by the `bin/structure.jl` script.
107+
108+
## Device flow authentication
109+
110+
Device flow authentication enables an application to authenticate a user by providing a link that can be opened on another device where the user can proceed with authentication. The application will be able to check whether the user has completed authentication on the other device by calling certain APIs. Finally, the application can retrieve the users OAuth token via the same API call. Device flow authentication becomes necessary on devices that do not have a browser based interface for regular login or applications that are not browser based such as command line applications. More details [here](https://auth0.com/docs/get-started/authentication-and-authorization-flow/device-authorization-flow).
111+
112+
### Working of device flow in PkgAuthentication.jl
113+
114+
We first call the dex [openid-configuration](https://dexidp.io/docs/openid-connect/) endpoint to determine whether the Pkg server supports device authentication. When device authentication is supported by the Pkg server we call the `/dex/device/code` endpoint. When the Pkg server does not support device authentication we fall back to the legacy browser authentication flow. The state machine for both flows are exactly the same (see diagram above). Only the http requests are different. The request and response for device code endpoint looks like:
115+
116+
Request:
117+
118+
```
119+
curl --request POST \
120+
-H 'Accept: application/json' \
121+
-H 'Content-Type: application/x-www-form-urlencoded' \
122+
--data 'client_id=device&scope=openid email profile offline_access' \
123+
https://juliahub.com/dex/device/code
124+
```
125+
126+
Response:
127+
128+
```json
129+
{
130+
"device_code": "abcdefghijklmnopqrstuvwxyz1234567890",
131+
"user_code": "FJMC-LPVR",
132+
"verification_uri": "https://juliahub.com/dex/device",
133+
"verification_uri_complete": "https://juliahub.com/dex/device?user_code=FJMC-LPVR",
134+
"expires_in": 300,
135+
"interval": 5
136+
}
137+
```
138+
139+
The `verfication_uri_complete` value is opened in the browser for the user so that they can continue logging in. As in the legacy browser flow which calls `/claimtoken` to poll for completion of authentication, we call `/dex/token` when device authentication is available.
140+
141+
The poll request looks like:
142+
143+
```
144+
curl --request POST \
145+
-H 'Accept: application/json' \
146+
-H 'Content-Type: application/x-www-form-urlencoded' \
147+
--data "client_id=device&scope=openid email profile offline_access&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=$device_code" \
148+
https://juliahub.com/dex/token
149+
```
150+
151+
While the user hasn't finished authenticating, the response will be:
152+
153+
```
154+
HTTP/1.1 401 Unauthorized
155+
156+
{"error":"authorization_pending"}
157+
```
158+
159+
Sometimes the response code might be 400.
160+
161+
After the user is successfully authenticated, the response will be:
162+
163+
```json
164+
{
165+
"access_token": "abcdefghijklmnopqrstuvwxyz1234567890",
166+
"token_type": "bearer",
167+
"expires_in": 86399,
168+
"refresh_token": "abcdefghijklmnopqrstuvwxyz1234567890",
169+
"id_token": "abcdefghijklmnopqrstuvwxyz1234567890"
170+
}
171+
```
172+
173+
We generate content for the `auth.toml` file with these values. We add some extra key/values to auth.toml when device authentication is enabled:
174+
- `client: "device"` This will help us distinguish between device authenticated auth.toml's and legacy auth.toml's.
175+
- `expires_at: <expires_in> + <time()>` This value is required to determine whether the token is expired and needs refresh. This is missing in the token response so we add it by summing the `expires_in` in value with the current timestamp.
176+
- `refresh_url` This value is also missing in the device token response but is necessary for refreshing expired tokens. We create this field with value `<server>/auth/renew/token.toml/device/`.
177+
178+
The mechanism to refresh the token is the same as in the legacy browser authentication flow.

0 commit comments

Comments
 (0)