Skip to content

Commit 7eea233

Browse files
committed
update docs
1 parent b862fa7 commit 7eea233

File tree

2 files changed

+77
-76
lines changed

2 files changed

+77
-76
lines changed

docs/auth-flows.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,36 @@ The following information is necessary to start the authentication flow, to know
7676

7777
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this specification are to be interpreted as described in [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119).
7878

79+
### Authentication mechanisms
80+
81+
PkgAuthentication.jl supports two different authentication mechanisms:
82+
1. Classic Authentication Flow
83+
2. Device Authentication Flow
84+
85+
When initiating a fresh authentication, PkgAuthentication.jl calls `/auth/configuration` endpoint to determine whether the Pkg server supports device authentication. This endpoint MUST return a 200 response. When device authentication is not supported by the server the response body MUST contain the following JSON data :
86+
87+
```json
88+
{
89+
"device_flow_supported": false,
90+
"refresh_url": "https://juliahub.com/auth/renew/token.toml/v2/"
91+
}
92+
```
93+
94+
In this case, PkgAuthentication.jl will execute the Classic Authentication Flow. When device authentication _is_ supported by the server, the response body MUST contain:
95+
96+
```json
97+
{
98+
"device_flow_supported": true,
99+
"refresh_url": "https://juliahub.com/auth/renew/token.toml/device/",
100+
"device_authorization_endpoint": "https://auth.juliahub.com/auth/device/code",
101+
"token_endpoint": "https://auth.juliahub.com/auth/token"
102+
}
103+
```
104+
105+
In this case, PkgAuthentication.jl will execute the Device Authentication Flow.
106+
107+
Note: URLs in the examples are only representative. Actual URLs may differ.
108+
79109
### Classic Authentication Flow
80110

81111
The classic authentication flow is similar to the [OAuth 2.0 Authorization Code Grant flow](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1), but uses different conventions for endpoints.
@@ -141,3 +171,50 @@ The flow goes through the following steps:
141171

142172
If PkgAuthentication successfully acquires a token from polling the `/claimtoken` endpoint, it will write the token to the `auth.toml` file.
143173
It will write out all the keys and values of the `token` in the `auth.toml` file as TOML.
174+
175+
### Device flow authentication
176+
177+
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://datatracker.ietf.org/doc/html/rfc8628).
178+
179+
The flow goes through the following steps:
180+
181+
1. A `POST` request MUST be made to the `device_authorization_endpoint` with the headers `Accept: application/json` and `Content-Type: application/x-www-form-urlencoded`. The body of the request MUST contain the url encoded `client_id` and `scope` values.
182+
183+
The server MUST respond with a 200 status and a body containing a JSON encoded structure. The JSON structure MUST include a `device_code` and a `verification_uri_complete` among other values. Example:
184+
185+
```json
186+
{
187+
"device_code": "abcdefghijklmnopqrstuvwxyz1234567890",
188+
"user_code": "FJMC-LPVR",
189+
"verification_uri": "https://juliahub.com/dex/device",
190+
"verification_uri_complete": "https://juliahub.com/dex/device?user_code=FJMC-LPVR",
191+
"expires_in": 300,
192+
"interval": 5
193+
}
194+
```
195+
196+
2. The client should open `verfication_uri_complete` in the browser so that the user can login and approve the authorization request. The package server SHOULD provide an interface for the user to login and approve or deny the authorization request.
197+
198+
3. The client should now poll for completion of the authorization request. It can do so by making a `POST` request to the `token_endpoint` with same headers as was used for the `device_authorization_endpoint` call. The body of the request MUST contain the url encoded `client_id` and `scope`. The values of these parameters must match the values sent for `device_authorization_endpoint`. In addition to these two parameters, a `grant_type` and `device_code` parameter must also be included with values `urn:ietf:params:oauth:grant-type:device_code` and the `device_code` response value from the `device_authorization_endpoint` call, respectively.
199+
200+
While the user hasn't finished responding to the authorization request or has denied the authorization request, the `token_endpoint` response status will be `401` or `400`.
201+
202+
When the user approves the authorization request, the `token_endpoint` response status will be 200 with a JSON body containing the `access_token`, `id_token`, `refresh_token` and `expires_in`. Example:
203+
204+
```json
205+
{
206+
"access_token": "abcdefghijklmnopqrstuvwxyz1234567890",
207+
"token_type": "bearer",
208+
"expires_in": 86399,
209+
"refresh_token": "abcdefghijklmnopqrstuvwxyz1234567890",
210+
"id_token": "abcdefghijklmnopqrstuvwxyz1234567890"
211+
}
212+
```
213+
214+
4. The client must generate the `auth.toml` file with the above values. The following extra key/values must be added to auth.toml to keep the content consistent with Classic Authentication Flow:
215+
- `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 it must be added by summing the `expires_in` value with the current timestamp.
216+
- `refresh_url` This value is also missing in the device token response but is necessary for refreshing expired tokens. This field must be added with value same as the `refresh_url` from the `device_authorization_endpoint` response.
217+
218+
#### Client ID for device authentication flow
219+
220+
The `client_id` parameter for device authentication can be configured by setting the environment variable `JULIA_PKG_AUTHENTICATION_DEVICE_CLIENT_ID`. This value defaults to `"device"`.

docs/state-machine.md

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -104,79 +104,3 @@ 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://datatracker.ietf.org/doc/html/rfc8628).
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. Not to be confused with `client_id` parameter that is used in the http requests. (See below)
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.
179-
180-
### Client ID for device authentication flow
181-
182-
The `client_id` parameter for device authentication can be configured by setting the environment variable `JULIA_PKG_AUTHENTICATION_DEVICE_CLIENT_ID`. This value defaults to `"device"`.

0 commit comments

Comments
 (0)