Skip to content
77 changes: 77 additions & 0 deletions docs/auth-flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,36 @@ The following information is necessary to start the authentication flow, to know

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).

### Authentication mechanisms

PkgAuthentication.jl supports two different authentication mechanisms:
1. Classic Authentication Flow
2. Device Authentication Flow

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 :

```json
{
"device_flow_supported": false,
"refresh_url": "https://juliahub.com/auth/renew/token.toml/v2/"
}
```

In this case, PkgAuthentication.jl will execute the Classic Authentication Flow. When device authentication _is_ supported by the server, the response body MUST contain:

```json
{
"device_flow_supported": true,
"refresh_url": "https://juliahub.com/auth/renew/token.toml/device/",
"device_authorization_endpoint": "https://auth.juliahub.com/auth/device/code",
"token_endpoint": "https://auth.juliahub.com/auth/token"
}
```

In this case, PkgAuthentication.jl will execute the Device Authentication Flow.

Note: URLs in the examples are only representative. Actual URLs may differ.

### Classic Authentication Flow

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.
Expand Down Expand Up @@ -141,3 +171,50 @@ The flow goes through the following steps:

If PkgAuthentication successfully acquires a token from polling the `/claimtoken` endpoint, it will write the token to the `auth.toml` file.
It will write out all the keys and values of the `token` in the `auth.toml` file as TOML.

### Device Authentication Flow

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).

The flow goes through the following steps:

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.

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:

```json
{
"device_code": "abcdefghijklmnopqrstuvwxyz1234567890",
"user_code": "FJMC-LPVR",
"verification_uri": "https://juliahub.com/dex/device",
"verification_uri_complete": "https://juliahub.com/dex/device?user_code=FJMC-LPVR",
"expires_in": 300,
"interval": 5
}
```

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.

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 the 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.

While the user hasn't finished responding to the authorization request or has denied the authorization request, the `token_endpoint` response status must be `401` or `400`.

When the user approves the authorization request, the `token_endpoint` response status must be 200 with a JSON body containing the `access_token`, `id_token`, `refresh_token` and `expires_in`. Example:

```json
{
"access_token": "abcdefghijklmnopqrstuvwxyz1234567890",
"token_type": "bearer",
"expires_in": 86399,
"refresh_token": "abcdefghijklmnopqrstuvwxyz1234567890",
"id_token": "abcdefghijklmnopqrstuvwxyz1234567890"
}
```

4. The client must generate the `auth.toml` file with the above values. The following extra key/values must be added by the client to the auth.toml:
- `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.
- `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.

#### Client ID for device authentication flow

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"`.
Loading
Loading