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


4 Demonstration of Proof of Possession

Using DPoP, a client presents at each request an access token that has been bound to a public key by the authorization server, along with a proof that the client knows the bound private key. The proof is a simple JWT that encodes the essential parts of the request (method and URI), and that expires in the near future. Each proof may only be used once.

The (pomdappi dpop) module defines utilities to work with a proof, and the bound access token.

predicate: dpop-proof? x
predicate: dpop-proof-header? x
predicate: dpop-proof-body? x

Check whether x is a parsed DPoP proof, proof header or body. Since a DPoP proof is a JWT, these predicates indirectly indicate a JWT.

predicate: dpop-bound? x
predicate: dpop-bound-body? x

Check whether x is a parsed DPoP-bound access token or its body. An access token is a special JWT, signed by an authorization server, and containing the fingerprint of the public key used by the client.

function: dpop-proof-header proof
function: dpop-proof-body proof

Get the JWT header or body of proof.

function: dpop-proof-header-jwk proof-header
function: dpop-proof-jwk proof
function: dpop-proof-body-jti proof-body
function: dpop-proof-jti proof
function: dpop-proof-body-htm proof-body
function: dpop-proof-htm proof
function: dpop-proof-body-htu proof-body
function: dpop-proof-htu proof
function: dpop-proof-body-iat proof-body
function: dpop-proof-iat proof

A DPoP proof body contains the following elements:

The resource server should not accept any proof that has been issued too long ago; 30 seconds is a good value.

The header of a DPoP proof contains the key that is used for the signature of the proof, and confirmed in the access token.

function: make-dpop-proof alg key jti htm htu iat

Make a decoded DPoP proof. alg should be 'RS256, 'RS512, 'ES256, 'ES384, 'ES512, 'PS256, 'PS384, 'PS512, or the string representations of these symbols, depending on the key type. jti is the almost certainly unique number; it is recommended to use 96 bits of entropy. htm is the method as a string or symbol. htu is the URI as a structured URI from (web uri), or a string. iat is a number of seconds since 01/01/1970, a srfi-19 time or srfi-19 date.

function: issue-dpop-proof alg key jti htm htu iat

Make a DPoP proof, and encode it, with the signature generated from key.

function: dpop-bound-body-cnf-jkt body
function: dpop-bound-cnf-jkt dpop-bound

Get the confirmation of the client’s key in a dpop-bound access token, or its body. The key confirmation is the hash of encoding all required fields of a public key in alphabetical order.

In fact, there are two distinct uses of a DPoP proof: to request a token on the authorization server, or to issue a request on a resource server. For the former case, there is no confirmation to perform.

function: dpop-parse-get-key proof htm htu current-time

Decode a DPoP proof, and extract its key. If this function returns the key, then the proof has been signed with it. You need to pass the method and URI (which should be respectively POST and the token endpoint on the authorization server) to check it against the proof. If it is too late, or the proof is invalid, the function returns #f.

function: dpop-parse proof access-token htm htu current-time

Decode proof and parse and return it as a DPoP proof. The proof is only valid if not issued too long ago, if it is used to access htu with the htm method, and that its key is confirmed by the access-token (in its decoded form).

You can get the fingerprints of a key with the (pomdappi jkt) module:

function: jkt pub

Return the fingerprint of the public-key pub.

function: jkt-check pub cnf

Check that the fingerprint of pub is cnf.

function: check-jti jti current-time expiration

In order to make sure that JTIs can only be used once, the (pomdappi jti) module defines this thread-safe function.

The used JTIs are stored until their associated expiration date passes. If the expiration date is too far away in the future (5 minutes), the JTI will not be checked and the function will allow it multiple times.

Return whether the JTI has not been seen yet (or it expires too far away in the future).

function: jti-96
function: jti-256
function: jti-384
function: jti-512

In (pomdappi random), these functions let you generate 96, 256, 384 or 512 bits of entropy to serve as nonce or JWT.

The function dpop-parse expects that the access token has already been parsed. Access token processing is done in the (pomdappi access-token) module.

predicate: access-token? x
predicate: access-token-body? x

Test if x is an access token (resp. an access token body).

function: access-token-body-sub body
function: access-token-sub access-token
function: access-token-body-iss body
function: access-token-iss access-token
function: access-token-body-iat body
function: access-token-iat access-token
function: access-token-body-exp body
function: access-token-exp access-token
function: access-token-body-cnf-jkt body
function: access-token-cnf-jkt access-token
function: access-token-body-client-id body
function: access-token-client-id access-token

An access token contains the following fields:

function: make-access-token alg key sub iss iat exp client-id

Create a decoded access token.

function: access-token-parse cache access-token current-time

Parse and validate the access-token. This might need to request further resources on the internet, for instance to check the issuer’s signature. In this case, you should pass a cache and activate non-blocking I/O with GUile. This function returns 2 values:

function: issue-access-token alg iss-keypair client-key iss sub iat exp client-id

Create an access token, and encode and sign it with iss-keypair.

As seen with access-token-parse, some functions might need to access resources on the web. For such cases, we define a simple cache of responses in (pomdappi cache).

function: make-cache

Make an empty cache. The cache is an immutable data structure.

function: cache-append cache current-time uri response body

Return the resulting cache after adding the information that at current-time, accessing uri returned the specified response and response body.


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