# JSON Web Signature (JWS)

Learn how JOSE JWS works with Wise Platform.

JSON Web Signature (JWS) is a JOSE specification that defines a compact and URL-safe way to represent digitally signed content. Implementing JWS in your system ensures the sender's identity and message haven't been altered, providing non-repudiation for your interactions with the Wise API.

Here's a summary of how the signing process works:

1. Create a key pair and deliver the public key to Wise (contact your implementation manager for details on how to do this).
2. Wise installs the public key to be consumed by the Wise API.
3. Once installed, you can call JWS enabled endpoint with signed request bodies.
4. Wise verifies the signature using the public key provided and performs additional checks, including the validity of the URL.
5. Wise returns the response encoded and signed.
6. Your system verifies and decodes the header and payload from the returned JWS.


## Providing public keys 

Contact your implementation manager about submitting your public key details to Wise.

### Encryption key requirements

When delivering the public key, Wise requires the following information:

* Key Material
* Algorithm used


### Optional key details

The following details are optional:

* KeyID: UUID
* Expiration Timestamp
* Deletion Timestamp
* Activation Timestamp


The KeyID, denoted in the JWS header as `kid`, indicates which key to use to validate the signature. This should be supplied if you plan to have multiple keys active at once, either for multiple services or rotation.

If the expiration, deletion, and activation timestamps are not included, once installed, the key will remain active until Wise is instructed to remove it.

## Using JWS endpoints workflow 

Here is a step-by-step workflow, with example commands, to manually sign a request.

Wise uses a standard implementation of JOSE JWS. For more information on constructing, signing, and validating JWS, see [JSON Web Signature (JWS)](https://openid.net/specs/draft-jones-json-web-signature-04.html).

### 1. Create request header & body

Create a request body (according to the usual API reference) and sign it with the request URL in the header block (see example).

Important!
The `url` must be included since Wise uses this to verify the request path has not been tampered with. Both the headers and payload are signed and verified against the actual call.

Header to be signed

```json
{
  "alg": "ES512",
  "typ": "JWT",
  "kid": "663a0e44-aa4a-4ff0-a9f8-cd99f5fbad71",
  "url": "/v3/profiles/12345/transfers/12345/payments"
}
```

Payload to be signed

```json
{
  "type": "BALANCE"
}
```

### 2. Sign with private key

The header and body should then be base64url encoded and signed, with the signature appended as per the [JOSE standard for JWS](https://jose.readthedocs.io/en/latest/#jws). It is recommended that you use an [established library](https://jwt.io/libraries) to complete this process to avoid difficulties and errors in the encoding and signing process.

This example uses the header and body as shown above and signs it with a private key. The three parts of this JWS are:

* Base64(base64url) Encoded Header
* Base64(base64url) Encoded Body
* Signed header + Body


Signed example

```shell
ewogICJhbGciOiAiRVM1MTIiLAogICJ0eXAiOiAiSldUIiwKICAia2lkIjogIjY2M2EwZTQ0LWFhNGEtNGZmMC1hOWY4LWNkOTlmNWZiYWQ3MSIsCiAgInVybCI6ICIvdjMvcHJvZmlsZXMvMTIzNDUvdHJhbnNmZXJzLzEyMzQ1L3BheW1lbnRzIgp9
.ewogICJ0eXBlIjogIkJBTEFOQ0UiCn0=
.Z-B7ScaZ37U_0CKrv03LTi0O0GWR2Hm5shzoEj8xRmM
```

### 3. Submit authenticated API request

The request must include the following headers:

* `Content-Type: application/jose+json`
* `Accept: application/jose+json`
* `X-TW-JOSE-Method: jws`


Complete API request example

```bash
curl -X POST 'https://api.transferwise.com/v3/profiles/12345/transfers/12345/payments' \
     -H 'Authorization: Bearer XXXXXXX' \
     -H 'Content-Type: application/jose+json' \
     -H 'Accept: application/jose+json' \
     -H 'X-TW-JOSE-Method: jws' \
     -H 'Accept-Encoding: identity' \
     -d 'ewogICJhbGciOiAiRVM1MTIiLAogICJ0eXAiOiAiSldUIiwKICAia2lkIjogIjY2M2EwZTQ0LWFhNGEtNGZmMC1hOWY4LWNkOTlmNWZiYWQ3MSIsCiAgInVybCI6ICIvdjMvcHJvZmlsZXMvMTIzNDUvdHJhbnNmZXJzLzEyMzQ1L3BheW1lbnRzIgp9.ewogICJ0eXBlIjogIkJBTEFOQ0UiCn0=.Z-B7ScaZ37U_0CKrv03LTi0O0GWR2Hm5shzoEj8xRmM'
```

### 4. Verify the response

Verify the response by fetching the latest Wise public key and checking the signature. See [Get Wise JWT public key](/api-reference/jose/joseresponsepublickeysget) for details.

The response is a fully formed JWS with a Base64 encoded JSON body.

Wise will sign the response using the same algorithm that was used to sign the request body.

If there is no body in the original request, the ES512 algorithm will be used for signing the response.

Request

```bash
  $ curl -i -X GET 'https://api.wise-sandbox.com/v1/auth/jwt-public-key?algorithm=ES512&scope=PAYLOAD_SIGNING' \
         -H 'Content-Type: application/json' \
         -H 'Authorization: Bearer <your api token>'
```