Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SEP-24: Add callback signature requirement #1263

Merged
merged 7 commits into from
Aug 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 54 additions & 4 deletions ecosystem/sep-0024.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Title: Hosted Deposit and Withdrawal
Author: SDF
Status: Active
Created: 2019-09-18
Updated: 2022-06-08
Version 2.5.0
Updated: 2022-08-19
Version 2.6.0
```

## Simple Summary
Expand Down Expand Up @@ -87,6 +87,52 @@ In order for browsers-based wallets to validate the CORS headers, as [specified

This protocol involves the transfer of value, and so HTTPS is required for all endpoints for security. Wallets and anchors should refuse to interact with any insecure HTTP endpoints.

## URL Callback signature

_Note that the signature discussed here is only for **URL callbacks** and does not apply to **`postMessage` callbacks**_

This protocol involves the optional use of URL callbacks that the Anchor can issue to update the wallet on ```status``` of a transaction.
In order to validate the integrity and provenance of the callback, the Anchor MUST include a signature in an additional HTTP Header `X-Stellar-Signature`.
This Header MUST follow the specification: `X-Stellar-Signature: t=<timestamp>, s=<base64 signature>` where:
* __timestamp__ is the current Unix timestamp (number of seconds since epoch) at the time the callback is sent. This is used to assure the freshness of the request and to prevent this request to be replayed in the future.
* __base64 signature__ is the base64 encoding of the request signature. We explain below how to compute and verify this signature. The signature is computed using the Stellar private key linked to the `SIGNING_KEY` field of the anchor's [`stellar.toml`](sep-0001.md). Note that the timestamp and the Wallet hostname will be part of the signature to prevent replay and relay attacks.

It is the wallet's responsability to:
* Verify the signature using the corresponding Stellar `SIGNING_KEY` field of the anchor's [`stellar.toml`](sep-0001.md).
* Verify the freshness of the request by comparing the `timestamp` in the request with the current timestamp at the time of the reception and discard every request above a threshold of few seconds (1 or 2 minute(s) maximum).
* Send a working callback URL (parameter ```callback``` or ```on_change_callback```) to the anchor.

### VERIFY signature

* Check that callback request has `X-Stellar-Signature` header
* Parse the header and extract:
* Key `t`: __timestamp__
* Key `s`: __base64 signature__
* Verify the request freshness: _current timestamp_ - __timestamp__ < few seconds (1-2 minute(s) max)
* Extract the __body__ of the request
* Base64 decode the __base64 signature__ to get the __signature__
* Prepare the payload to verify the signature:
* The __timestamp__ (as a string)
* The character `.`
* The wallet host to send the callback request to
* The character `.`
* The __body__
* Verify the signature using the correct `SIGNING_KEY`

### COMPUTE signature

* Prepare the callback
* Prepare the payload to sign:
* Current timestamp (as a string)
* The character `.`
* The wallet host to send the callback request to
* The character `.`
* The callback request body
* Sign the payload `<timestamp>.<host>.<body>` using the Anchor private key
* Base64 encode the signature
* Build the `X-Stellar-Signature` header:
* `X-Stellar-Signature: t=<current timestamp>, s=<base64 encoded signature>`

## Content Type

All endpoints accept in requests the following `Content-Type`s:
Expand Down Expand Up @@ -380,8 +426,8 @@ The basic parameters are summarized in the table below.

Name | Type | Description
-----|------|------------
`callback` | string | (optional) [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) or a URL that the anchor should `POST` a JSON message to when the user successfully completes the interactive flow.
`on_change_callback` | string | (optional) [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) or a URL that the anchor should `POST` a JSON message to when the `status` or `kyc_verified` properties change.
`callback` | string | (optional) [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) or a URL that the anchor should `POST` a JSON message to when the user successfully completes the interactive flow. If the callback is a URL (not a `postMessage`), it needs to be signed by the anchor and the signature needs to be verified by the wallet according to the [callback signature specification](#callback-signature).
`on_change_callback` | string | (optional) [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) or a URL that the anchor should `POST` a JSON message to when the `status` or `kyc_verified` properties change. If the callback is a URL (not a `postMessage`), it needs to be signed by the anchor and the signature needs to be verified by the wallet according to the [callback signature specification](#callback-signature).

The URL supplied by both callback parameters should receive the full transaction object.

Expand All @@ -402,6 +448,8 @@ Because `callback` is used to notify the wallet that the interactive flow is com
Wallet applications display content rendered by a third party anchor service. It is recommended to use the [`rel=noopener`](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/noopener) attribute on links or the `noopener` feature for [`Window.open()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#window_functionality_features).

Note that using `noopener` prohibits the use of `postMessage` callbacks. If `postMessage` callbacks are required for your implementation, it recommended to only open URLs from anchors that you, the wallet developer, trust.

To validate the provenance and integrity of the callback, anchors [must sign it](#callback-signature) and wallet servers must validate the signature before taking any action.

**Differences between `callback` and `on_change_callback`**

Expand Down Expand Up @@ -939,6 +987,8 @@ There is a small set of changes when upgrading from SEP-6 to SEP-24.
* Solar wallet: https://solarwallet.io

## Changelog

* `v2.6.0`: Add callback signature and verification requirement. ([#1263](https://github.com/stellar/stellar-protocol/pull/1263))
* `v2.5.0`: Add `expired` transaction status. ([#1233](https://github.com/stellar/stellar-protocol/pull/1233))
* `v2.4.0`: Add `refunded` transaction status. ([#1195](https://github.com/stellar/stellar-protocol/pull/1195))
* `v2.3.0`: Change `lang` format from [ISO639-1](https://en.wikipedia.org/wiki/ISO_639-1) to [RFC4646](https://datatracker.ietf.org/doc/html/rfc4646) which is a superset of ISO639-1. Add `lang` field to GET `/transactions` and `/transaction`. ([#1191](https://github.com/stellar/stellar-protocol/pull/1191))
Expand Down