Skip to content
GitHub

Client keys

All client requests in Open Payments are signed using a unique key that identifies the client to the authorization and resource servers. All requests, except for new grant requests, also carry an access token that is bound to the key.

Key registry

A key registry is a list of keys associated with clients that require access to protected Open Payments resources. Key registries are publicly exposed via a jwks.json endpoint and allows servers to verify that a client is who it says it is.

Each client is represented by a wallet address. When the client generates an asymmetric key pair, the public key is added to a key registry while the private key is stored by the client. Servers can then retrieve the client’s key registry by accessing WALLET_ADDRESS/jwks.json. For example, https://wallet.example.com/alice/jwks.json.

Registry structure

A key registry’s JWKS document must contain the following fields and values.

{
alg: 'EdDSA',
kty: 'OKP',
crv: 'Ed25519'
}

Additionally, the JWK must contain the x and kid (key ID) fields for the specific client to identify the client in a signature.

Example: https://wallet.example.com/alice/jwks.json

{
"keys": [
{
"kid": "3724c845-829d-425a-9a0d-194d6f12c336",
"x": "_Eg6UcC8G-O4TY2cxGnZyG_lMn0aWF1rVV-Bqn9NmhE",
"alg": "EdDSA",
"kty": "OKP",
"crv": "Ed25519"
}
]
}

Proofing method

The security of client requests follows a profile of the mechanism defined in the GNAP specification.

Open Payments uses the HTTP message signatures key proofing method. Clients typically secure their requests to servers by presenting an access token and proof of a key it possesses. The exception is for calls to an authorization server to initiate a grant. In this case, a key proof is used with no access token and is a non-authorized signed request.

The httpsig proofing method must be declared as part of the key material when directly using a key to request a grant. The key material below is for illustrative purposes. In Open Payments, it’s expected that the wallet address be used in the grant request.

"key": {
"proof": "httpsig",
"jwk": {
"kid": "3724c845-829d-425a-9a0d-194d6f12c336",
"x": "_Eg6UcC8G-O4TY2cxGnZyG_lMn0aWF1rVV-Bqn9NmhE",
"alg": "EdDSA",
"kty": "OKP",
"crv": "Ed25519"
}
}

When using httpsig, the signer creates an HTTP Message Signature as described in the HTTP Message Signatures specification. Review the HTTP message signatures page for more information about signatures as they relate to Open Payments.

Key generation

Before a client can request a grant for the first time, it must:

  1. Generate an asymmetric key pair
  2. Add the public key to the key registry
  3. Store the private key

Keys must be generated using the ed25519 algorithm.

Client requests

Since client requests are completed over multiple signed HTTP requests, it’s important for a client to provide a way to consistently identify itself across these requests. As such, clients must include the following when making requests:

  • Header
    • Signature-Input that includes the keyId associated with the client’s key pair
    • signature generated based on the Signature-Input, using the EdDSA signing algorithm
  • Body
    • client property containing the client’s wallet address

Grant requests

Upon receiving a signed grant request, the AS obtains the client’s domain from the client property. The AS binds the domain to the grant in order to use it to acquire the key set for subsequent grant requests.

The AS then acquires the client’s key registry by making a GET request to the client’s JWKS endpoint at WALLET_ADDRESS/jwks.json. When it locates the public key containing the keyId that was included in the request’s Signature-Input, the AS uses the key to decrypt and validate the requests signature. This binds the client to the grant and allows the AS to continue with the grant request.