Next: , Previous: , Up: Top   [Contents][Index]


5 Bits of OAuth and OIDC

In the Solid authentication flow, the client starts by redirecting the user to an authorization page on which the user will consent to the client using his or her identity. Then, the browser is redirected to the client application with an authorization code.

As an implementation detail, authorization codes are in fact encoded JWTs signed by the issuer, with a short life time (30 seconds). Authorization codes are defined in (pomdappi authorization). Note that the client does not need to parse an authorization code, it just treats it as an opaque identifier.

predicate: authorization-code? x
predicate: authorization-code-body? x

Test if x is is an authorization code, or an authorization code body.

function: authorization-code-body-jti authorization-code
function: authorization-code-jti authorization-code
function: authorization-code-body-client-id authorization-code
function: authorization-code-client-id authorization-code
function: authorization-code-body-sub authorization-code
function: authorization-code-sub authorization-code
function: authorization-code-body-exp authorization-code
function: authorization-code-exp authorization-code

An authorization code contains everything needed to create an ID token, an access token and a refresh token: a client-id, a subject (sub), and an expiration date (exp). It also expires in the near future, and the JTI makes sure it can only be used once.

function: make-authorization-code alg jti client-id sub exp

Create a decoded authorization code that should be signed with alg.

function: issue-authorization-code alg key jti client-id sub exp

Create an encoded authorization code, signed with key, ready to be returned in a callback.

function: authorization-code-parse code key current-time

Parse code as an authorization code, and check that it is valid at current-time and signed with key. Return #f if an error happens, or the authorization code if it is valid.

function: make-authorization-endpoint-handler authenticate alg key

Create a request handler. authenticate (username password) should return either #f if no one is authenticated by username/password, or the webid of the authenticated user as a structured (web uri) uri.

key should be the authorization server’s key pair, and it should be able to sign JWTs with alg.

The return function takes 4 arguments:

It returns 3 values:

Requests are the objects defined in (web request), and responses in (web response).

The authorization endpoint handler does not care what the request URI is, it treats every URI as an authorization URI. For finer-grain control, we need to define an OIDC config, in (pomdappi oidc-config).

predicate: oidc-config? x

Test whether x is an OIDC config.

function: oidc-config-jwks-uri cfg
function: oidc-config-authorization-endpoint cfg
function: oidc-config-token-endpoint cfg
function: make-oidc-config jwks-uri authorization-endpoint token-endpoint

An OIDC config contains at least 3 elements:

function: get-oidc-config cache current-time host

Query the web (or the cache if it has it) for the OIDC config of host. Return 2 values:

function: get-jwks cache current-time uri

Query uri for a JWKS. Return 2 values:

Once the client has an authorization code, it needs to trade it for an OIDC ID token and an access token bound to its key (see the DPoP section). The (pomdappi oidc-id-token) defines the functions to manage an ID token. An ID token is a JWT, signed by the identity provider.

predicate: oidc-id-token? x
predicate: oidc-id-token-body? x

Test whether x is an OIDC ID token (or an OIDC ID token body).

function: oidc-id-token-body-iss body
function: oidc-id-token-iss id-token
function: oidc-id-token-body-sub body
function: oidc-id-token-sub id-token
function: oidc-id-token-body-aud body
function: oidc-id-token-aud id-token
function: oidc-id-token-body-nonce body
function: oidc-id-token-nonce id-token
function: oidc-id-token-body-exp body
function: oidc-id-token-exp id-token
function: oidc-id-token-body-iat body
function: oidc-id-token-iat id-token

An ID token contains the following fields:

function: make-oidc-id-token alg iss sub aud nonce exp iat

Create a decoded ID token that is to be signed with alg.

function: issue-oidc-id-token alg key iss sub aud nonce exp iat

Create an encoded ID token, signed with key, a private key owned by the OIDC identity provider.

function: oidc-id-token-parse tk cache current-time

Parse and validate the encoded ID token tk. Return #f if it is invalid at current-time, or the decoded ID token.

function: make-token-endpoint-handler jwks key alg iss gen-nonce

Create a token endpoint handler. You need to pass the identity provider host name as iss.

The return function takes 4 parameters:

It returns 3 values:

This function will make requests to the world wide web, thus you need to enable suspendable I/O.

The token endpoint also grants a refresh token, which is a secret code that the token endpoint uses as an alternative to the authorization code to grant tokens. The client should not attempt to make sense of a refresh token, so this is only meaningful as an implementation detail of the identity provider.

predicate: refresh-token? x

Test whether x is a refresh token.

function: refresh-token-key refresh-token
function: refresh-token-sub refresh-token
function: refresh-token-aud refresh-token
function: make-refresh-token key sub aud

A refresh token is composed of a key, which is a secret shared with the client, the subject (sub) which is the user’s webid, and the audience (aud) to prevent another party from using the tokens.

function: lookup-refresh-token key
function: issue-refresh-token sub aud
function: revoke-refresh-token key
function: list-refresh-tokens

Refresh tokens are saved to disk, because they are useful secrets. The client should only be given the key, while the key, sub and aud should be saved. lookup-refresh-token returns either #f, if such a refresh token has been revoked or does not exist, or the full refresh token. issue-refresh-token returns the refresh token key. list-refresh-token returns the list of refresh tokens saved on disk.

function: refresh alg key iss client-id refresh-token current-time

Issue a pair of an OIDC ID token and a DPoP-bound access token, as two values, valid for an hour.


Next: , Previous: , Up: Top   [Contents][Index]