From ca08398173d532e57e7ac0c6635e2ccd80b7249b Mon Sep 17 00:00:00 2001 From: Melissa Henderson <57110301+melissahenderson@users.noreply.github.com> Date: Thu, 7 Dec 2023 12:46:30 -0500 Subject: [PATCH] docs: content updates (#387) Updates related to grants, IdP, and client keys --- .../content/docs/introduction/client-keys.mdx | 62 +++++---- docs/src/content/docs/introduction/grants.mdx | 124 ++++++++++++++---- .../src/content/docs/introduction/op-flow.mdx | 18 +-- .../drafts/guides/make-onetime-payment.mdx | 8 -- .../drafts/guides/make-recurring-payment.mdx | 8 -- docs/src/drafts/resources/glossary.mdx | 4 + 6 files changed, 145 insertions(+), 79 deletions(-) delete mode 100644 docs/src/drafts/guides/make-onetime-payment.mdx delete mode 100644 docs/src/drafts/guides/make-recurring-payment.mdx diff --git a/docs/src/content/docs/introduction/client-keys.mdx b/docs/src/content/docs/introduction/client-keys.mdx index 992ad1d3..516221e7 100644 --- a/docs/src/content/docs/introduction/client-keys.mdx +++ b/docs/src/content/docs/introduction/client-keys.mdx @@ -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 ed25519 algorithm, and the resulting JWK must have fields with the following values: +A key registry's JWKS document must contain the following fields and values. ``` { @@ -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. ```json @@ -61,7 +42,7 @@ The key material must be available within a JSON Web Key Set (JWKS) document loc ``` -## Key proofing method +### Proofing method The security of client requests follows a profile of the mechanism defined in the GNAP specification. @@ -69,7 +50,7 @@ The security of client requests follows a profile of the mechanism defined in th Open Payments **does not** support bearer tokens. ::: -Open Payments uses the HTTP message signatures 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 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. @@ -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 HTTP Message Signatures specification. 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 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. diff --git a/docs/src/content/docs/introduction/grants.mdx b/docs/src/content/docs/introduction/grants.mdx index faed040a..d6f1baa3 100644 --- a/docs/src/content/docs/introduction/grants.mdx +++ b/docs/src/content/docs/introduction/grants.mdx @@ -2,55 +2,123 @@ title: Grant negotiation and authorization --- -import { CodeBlock, LinkOut } from '@interledger/docs-design-system' +import { + CodeBlock, + LinkOut, + Tooltip, + Mermaid, + MermaidWrapper +} from '@interledger/docs-design-system' -Before a client can issue instructions for an incoming payment, quote, or outgoing payment, it must obtain the requisite grant(s). Open Payments leverages the Grant Negotiation and Authorization Protocol (GNAP) to define a standard mechanism for clients to obtain grants. GNAP is a protocol being developed by the Internet Engineering Task Force (IETF) as the successor to OAuth 2.0, designed to fill many of the gaps discovered through the use of OAuth in Open Banking and other financial use cases. +In Open Payments, a grant indicates a transfer, or delegation, of authorization from a resource owner (RO) to a piece of software. An RO can be a physical person, such as the software’s end user, or a process, such as predefined organizational rules. By delegating authorization, the RO allows the software to access and perform operations on protected resources on the RO’s behalf. -## Grants +Open Payments leverages the Grant Negotiation and Authorization Protocol (GNAP) as the mechanism by which the piece of software, known as a client instance (or client for short), is delegated authorization to use the Open Payments API to interface with supported accounts. -GNAP allows a client instance to request delegated authorization to protected resources from a party other than the end user. This delegation is facilitated by an authorization server, which exposes APIs compliant with the GNAP standard. The process by which the delegation occurs is known as a grant. +## GNAP vs OAuth 2.0 + +GNAP is being developed as the successor to OAuth 2.0 and is designed to fill many of the gaps discovered through the use of OAuth in Open Banking and other financial use cases. Appendix B in the GNAP specification outlines ways in which the protocol’s design differs from OAuth 2.0. Some examples include: + +| GNAP | OAuth 2.0 | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| The client declares the different ways it can start and finish an interaction, and these can be mixed together as needed for different use cases; interactions can use a web browser, but don’t have to | The type of interaction available is fixed and dictated by the grant type; assumes the end-user has access to a web browser | +| Allows the entity requesting access to protected resources to be different from the resource owner, but still works in the optimized cased of them being the same party | Assumes the end-user is the same user that will interact with the authorization server to approve access; assumes the resource owner is the person who requested the grant | +| Allows the client to present an unknown key to the authorization server and use that key to protect the ongoing request | Requires all clients to be registered at the authorization server and use a `client_id` known to the authorization server | +| Always starts at the same endpoint at the authorization server | Different grant types start at different endpoints | +| A client can ask for multiple access tokens in a single grant request | A client can only ask for a single access token in a single request | + +## Grant authorization servers + +An authorization server (AS) grants delegated privileges to a client in the form of access tokens. Access tokens represent a set of access rights and/or attributes granted to the client. With the requisite access token(s), the client can access a resource server’s (RS) Open Payments API and perform allowed operations, such as creating incoming payments and listing outgoing payments, on behalf of the resource owner. + +An AS is uniquely identified by its grant endpoint URI, which is an absolute URI that a client calls to initiate a grant request. + +### Key registries + +A key registry is a list of keys associated with clients requiring access to protected Open Payments resources. Key registries are publicly exposed via a `jwks.json` endpoint and allows an AS to verify that a client is who it says it is. + +A client must generate and add its key to its key registry before requesting a grant for the first time. For more information on key generation and registration, as well as how key registries work with authorization servers, refer to the [Client keys](/introduction/client-keys) page. ## Grant requests -An authorization server is uniquely identified by its grant endpoint URI, which is an absolute URI that a client calls to initiate a grant request. +Before a client can access the Open Payments API, it must send a grant request to the AS. The request must contain the type of resource it wants to work with and the action(s) it wants to take on the resource. Resource types include `incoming-payment`, `quote`, and `outgoing-payment`. The available actions depend on type, but examples include `create` and `read`. A successful grant request results in the AS returning one or more access tokens. -The grant request flow can take one of the paths below, with the first being the most common. +The sequence of requests a client makes when setting up a payment can follow one of the paths below. -- Grant → incoming payment → grant → quote → grant → outgoing payment -- Grant → incoming payment → grant → quote → outgoing payment +#### Path 1 (most common) -A successfully issued grant results in the client receiving an access token. The access token: +1. Request an `incoming-payment` grant from the payee's AS +2. Send request to create an incoming payment resource to the payee's RS +3. Request a `quote` grant from the payer's AS +4. Send request to create a quote resource to the payer's RS +5. Request an interactive `outgoing-payment` grant from the payer's AS +6. Send request to create an outgoing payment resource to the payer's RS -- Represents the rights granted to the client -- Acts as credentials when calling a resource server’s Open Payments API -- Allows the client to access protected resources (primarily OP-enabled accounts) on an ASE’s resource server and perform operations on these resources +#### Path 2 -:::note -An open-source implementation of an Open Payments resource server, called Rafiki, is currently in development. -::: +1. Request an `incoming-payment` grant from the payee's AS +2. Send request to create an incoming payment resource to the payee's RS +3. Request a single interactive grant for both `quote` and `outgoing-payment` from the payer's AS +4. Send request to create a quote resource to the payer's RS +5. Send request to create an outgoing payment resource to the payer's RS + +## Grant types + +### incoming-payment -The authorization of access to an OP-enabled account can be separated from the ASE if desired. The authorization service can even be fulfilled by multiple federated providers if a use case requires this in the future. +A client begins the Open Payments flow by requesting an incoming payment grant from the AS on the _payee_ side. The client can request a single grant to create multiple incoming payments for different OP-enabled accounts as long as each account belongs to the same ASE. -### Incoming payment grant +Incoming payment grants are non-interactive by default, meaning interaction by an individual (typically the client’s end-user) is not required for the AS to issue an access token. -A client requests an [incoming payment grant](/apis/resource-server/operations/create-incoming-payment) from the authorization server on the _payee_ side. The client can request one grant to create multiple incoming payments for different OP-enabled accounts as long as each account belongs to the same ASE. +### quote -Incoming payment grants are non-interactive by default, meaning interaction by an individual (typically the client's end-user) is not required for the authorization server to issue an access token. +After the client receives an incoming payment grant and an incoming payment resource is created on the payee’s account, the client requests a quote grant from the AS on the _payer_ side. The client can request a single grant to create multiple quotes for different OP-enabled accounts as long as each account belongs to the same ASE. -### Quote grant +Quote grants are non-interactive by default, meaning interaction by an individual (typically the client’s end-user) is not required for the AS to issue an access token. -A client requests a [quote](/apis/resource-server/operations/create-quote) from the authorization server on the _payer_ side. The client can request one grant to create multiple quotes for different OP-enabled accounts as long as each account belongs to the same ASE. +### outgoing-payment -Quote grants are non-interactive by default, meaning interaction by an individual (typically the client's end-user) is not required for the authorization server to issue an access token. +Having progressed through the incoming payment and quote portions of the Open Payments flow, the client is ready to request an outgoing payment grant from the AS on the _payer_ side. -### Outgoing payment grant +Open Payments requires outgoing payment grant requests to be interactive. When a grant request is interactive, it means explicit interaction by an individual (typically the client’s end user) is a required step in the delegation process. -A client requests an [outgoing payment grant](/apis/resource-server/operations/create-outgoing-payment) from the authorization server on the _payer_ side. Open Payments requires outgoing payment grants to be interactive, meaning interaction by an individual (typically the client's end-user) is required. After interaction is finished, the client must issue a [grant continuation request](/apis/auth-server/operations/post-continue). +After a successful interaction, the client must issue a [grant continuation request](/apis/auth-server/operations/post-continue) so the AS knows to issue an access token. -For more information, refer to the [create an interactive grant](/guides/create-interactive-grant) guide. +## Open Payments resource servers -## Grant continuation and cancellation +A resource server (RS) provides the Open Payments API through which resources can be created or accessed on the server. GNAP doesn’t presume or require a tight coupling between an RS and an AS and it’s increasingly common for the servers to be run and managed separately. -A client can issue a [grant continuation request](/apis/auth-server/operations/post-continue) when a grant needs to be modified or continued. For example, a client may initially need read access to a resource, but later require write access. +Operations on the API by a client require the client to have a valid access token issued by a trusted AS. When the client uses its access token to call the RS, the RS examines the token to determine if the token is sufficient for the request. The means by which an RS makes this determination are outside of the scope of Open Payments. If the token is sufficient, the client is given the right to access the operation(s) and resource tied to the token. + +:::note +An open-source implementation of an Open Payments resource server, called Rafiki, is currently in development. +::: -A client can request to [cancel a grant](/apis/auth-server/operations/delete-continue) if it no longer needs access to protected resources on the resource server. +## Identity providers + +Open Payments requires the use of an identity provider (IdP) during an interactive grant flow. An IdP is a system or service that manages user authentication, identity information, and consent. + + + +{/* prettier-ignore */} +>Authorization server (AS): Sends interactive grant request + Authorization server (AS)-->>Client instance: 200 returns interact redirect uri and continue uri + Client instance->>Authorization server (AS): Navigates to interact redirect uri + Authorization server (AS)->>Authorization server (AS): Starts interaction and sets session + Authorization server (AS)-->>Client instance: 302 temporary redirect to identity provider
uri with grant info in query string + Client instance->>Identity provider (IdP): Redirects to identity provider + Identity provider (IdP)->>Identity provider (IdP): Resource owner (e.g. client end-user)
accepts interaction + Identity provider (IdP)->>Authorization server (AS): Sends interaction choice + Authorization server (AS) -->>Identity provider (IdP): 202 choice accepted + Identity provider (IdP)->>Authorization server (AS): Requests to finish interaction + Authorization server (AS)->>Authorization server (AS): Ends session + Authorization server (AS)-->>Identity provider (IdP): 302 temporary redirect to finish url
(in outgoing-payment grant request)
secured with unique hash and
interact_ref in query string + Identity provider (IdP)->>Client instance: Follows redirect + Client instance->>Client instance: Verifies hash + Client instance->>Authorization server (AS): Sends continuation grant request with
interact_ref in body to continue uri + Authorization server (AS)->>Client instance: 200 returns grant access token +`} +/> + +
diff --git a/docs/src/content/docs/introduction/op-flow.mdx b/docs/src/content/docs/introduction/op-flow.mdx index 8434f523..44901602 100644 --- a/docs/src/content/docs/introduction/op-flow.mdx +++ b/docs/src/content/docs/introduction/op-flow.mdx @@ -27,7 +27,7 @@ In this flow, assume the client's end-user is the payer and that the client alre -2. The client requests/receives a grant from the payee's authorization server to create an `incoming-payment` resource on the payee’s account. The client then sends a request to the resource server to create the resource. When created, the resource server returns unique payment details the client will use to address one or more payments to the payee. +2. The client requests/receives a grant from the payee's authorization server to create an `incoming-payment` resource. The client then sends a request to the payee-side resource server to create the resource. When created, the resource server returns unique payment details the client will use to address one or more payments to the payee. @@ -47,7 +47,7 @@ In this flow, assume the client's end-user is the payer and that the client alre -3. The client requests/receives a grant from the end-user's authorization server to create a `quote` resource on the user's account. The client then sends a request to the user's resource server to create the resource. When created, the resource server returns, among other things, a quote `id` and the amount it will cost to make the payment. +3. The client requests/receives a grant from the end-user's authorization server to create a `quote` resource. The client then sends a request to the end-user's resource server to create the resource. When created, the resource server returns, among other things, a quote `id` and the amount it will cost to make the payment. @@ -67,7 +67,7 @@ In this flow, assume the client's end-user is the payer and that the client alre -4. The client issues an [interactive grant request](/introduction/grants/#outgoing-payment-grant) to the end-user's authorization server to obtain the user's explicit consent to send a payment of X amount. While the client must facilitate the interaction, the authorization server is responsible for the interface and collecting consent. +4. The client requests an interactive grant from the end-user's authorization server to create an `outgoing-payment` resource. An interactive grant requires that explicit consent from the end-user be collected before an access token is issued. While the client must facilitate the interaction, the end-user's authorization server and [identity provider](/introduction/grants/#identity-providers) are responsible for the interface and collecting consent. @@ -85,7 +85,7 @@ In this flow, assume the client's end-user is the payer and that the client alre -5. After consent is obtained, the client requests/receives permission to continue the grant request and create an `outgoing-payment` resource on the end-user's payment account. When created, the setup of the payment is complete and the Open Payments flow ends. +5. After consent is obtained, the client requests/receives permission to continue the grant request and create the `outgoing-payment` resource. When created, the setup of the payment is complete and the Open Payments flow ends. @@ -94,12 +94,12 @@ In this flow, assume the client's end-user is the payer and that the client alre participant C as Client participant AS as Authorization server + participant IDP as Identity provider - AS->>AS: End-user interacts with authorization server and approves the grant - AS->>C: Redirects end-user to client's finish URI, includes hash and interaction reference - C->>C: Verifies hash - C->>AS: Grant continuation request (POST) with interaction reference - AS->>C: 200 Success with access_token + C->>AS: Grant continuation request (POST) + AS->>C: 200 Success with access token + C->>AS: Create outgoing payment (POST) + AS->>C: 201 Outgoing payment created `} /> diff --git a/docs/src/drafts/guides/make-onetime-payment.mdx b/docs/src/drafts/guides/make-onetime-payment.mdx deleted file mode 100644 index e7a86238..00000000 --- a/docs/src/drafts/guides/make-onetime-payment.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Make a one-time payment -draft: true ---- - -:::caution -This section is WIP -::: diff --git a/docs/src/drafts/guides/make-recurring-payment.mdx b/docs/src/drafts/guides/make-recurring-payment.mdx deleted file mode 100644 index 793dcc41..00000000 --- a/docs/src/drafts/guides/make-recurring-payment.mdx +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Make a recurring payment -draft: true ---- - -:::caution -This section is WIP -::: diff --git a/docs/src/drafts/resources/glossary.mdx b/docs/src/drafts/resources/glossary.mdx index a7bd7dea..d1fa51e2 100644 --- a/docs/src/drafts/resources/glossary.mdx +++ b/docs/src/drafts/resources/glossary.mdx @@ -9,12 +9,16 @@ import { LinkOut } from '@interledger/docs-design-system' This section is WIP ::: +## Account servicing entity (ASE) + ## Authorization server (AS) ## Client ## Grant Negotiation and Authorization Protocol (GNAP) +## Interactive grant + ## Open Payments (OP) ## Resource server (RS)