Skip to content

Commit

Permalink
docs: content updates (#387)
Browse files Browse the repository at this point in the history
Updates related to grants, IdP, and client keys
  • Loading branch information
melissahenderson authored Dec 7, 2023
1 parent 59268b5 commit ca08398
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 79 deletions.
62 changes: 36 additions & 26 deletions docs/src/content/docs/introduction/client-keys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,13 @@ All client requests in Open Payments are signed using a unique key that identifi

## Key registry

A key registry is a registry of all keys stored by an ASE for their users. A key is [generated](#key-structure) and added to the registry by the client that requires access to Open Payments resources that are protected by an authorization server.
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.

The client is represented by a [wallet address](/introduction/wallet-addresses). The keys specifically for the client are contained within a `jwks.json` and exposed publicly at `WALLET_ADDRESS/jwks.json`. For example, `https://wallet.example.com/alice/jwks.json`.
Each client is represented by a [wallet address](/introduction/wallet-addresses). 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`.

The key registry and public `jwks.json` allows servers to verify that a client is who they say they are.
### Registry structure

## Acquisition of a client's key set

Because a grant request is completed over multiple signed HTTP requests, it’s important for a client to provide a way to consistently identify itself across these requests.

The client generates an asymmetric key pair and the ASE assigns a key ID identifying the pair. When the client makes a grant request to the authorization server, the client must include a:

- signature in the header that's signed by the private key
- `signature-input` header that includes the key ID of the public key associated with the private key used to sign the signature.

Refer to the [HTTP message signatures](/introduction/http-signatures) page for more information about signature headers.

When the authorization server receives a signed grant request, the server makes a `GET` request to the client’s `jwks.json` endpoint to acquire the key set. The wallet address of the client is acquired by the authorization server during this initial grant request, after which the server binds the wallet address to the grant and uses it to acquire the key set for subsequent grant requests.

After the authorization server acquires the client’s key set, the server searches for the public key with a key ID that matches the one included in the `signature-input` header. Once the server finds the public key, the key will be used to verify the signature, allowing the server to proceed with the grant request.

## Key structure

In Open Payments, the key registry must expose public keys in the form of a JWK. Keys must be generated using the <LinkOut href='https://datatracker.ietf.org/doc/html/rfc8032'>ed25519 algorithm</LinkOut>, and the resulting JWK must have fields with the following values:
A key registry's JWKS document must contain the following fields and values.

```
{
Expand All @@ -41,9 +24,7 @@ In Open Payments, the key registry must expose public keys in the form of a JWK.
}
```

Additionally, the JWK must contain the `x` field and the public key `kid` field to identify it in a signature.

The key material must be available within a JSON Web Key Set (JWKS) document located at `WALLET_ADDRESS/jwks.json`.
Additionally, the JWK must contain the `x` and `kid` (key ID) fields for the specific client to identify the client in a signature.

<CodeBlock title="Example: https://wallet.example.com/alice/jwks.json">
```json
Expand All @@ -61,15 +42,15 @@ The key material must be available within a JSON Web Key Set (JWKS) document loc
```
</CodeBlock>

## Key proofing method
### Proofing method

The security of client requests follows a profile of the mechanism defined in the <LinkOut href='https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-protocol#name-securing-requests-from-the-'>GNAP specification</LinkOut>.

:::note
Open Payments **does not** support bearer tokens.
:::

Open Payments uses the <LinkOut href='https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-protocol#name-http-message-signatures'>HTTP message signatures</LinkOut> key proofing method. Clients typically secure their requests to the authorization and resource servers by presenting an access token and proof of a key it possesses. The exception is for calls to the 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.
Open Payments uses the <LinkOut href='https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-protocol#name-http-message-signatures'>HTTP message signatures</LinkOut> 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.

Expand All @@ -87,3 +68,32 @@ The `httpsig` proofing method must be declared as part of the key material when
```

When using `httpsig`, the signer creates an HTTP Message Signature as described in the <LinkOut href='https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures'>HTTP Message Signatures specification</LinkOut>. Review the [HTTP message signatures](/introduction/http-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
:::note
A `keyId` must be generated to identify the pair; however, this is usually the responsibility of the account servicing entity (ASE).
:::
2. Add the public key to the key registry
3. Store the private key

Keys must be generated using the <LinkOut href='https://datatracker.ietf.org/doc/html/rfc8032'>ed25519 algorithm</LinkOut>.

## 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.
Loading

0 comments on commit ca08398

Please sign in to comment.