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:
- Create a key pair and deliver the public key to Wise (contact your implementation manager for details on how to do this).
- Wise installs the public key to be consumed by the Wise API.
- Once installed, you can call JWS enabled endpoint with signed request bodies.
- Wise verifies the signature using the public key provided and performs additional checks, including the validity of the URL.
- Wise returns the response encoded and signed.
- Your system verifies and decodes the header and payload from the returned JWS.
Contact your implementation manager about submitting your public key details to Wise.
When delivering the public key, Wise requires the following information:
- Key Material
- Algorithm used
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.
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).
Create a request body (according to the usual API reference) and sign it with the request URL in the header block (see example).
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.
{
"alg": "ES512",
"typ": "JWT",
"kid": "663a0e44-aa4a-4ff0-a9f8-cd99f5fbad71",
"url": "/v3/profiles/12345/transfers/12345/payments"
}{
"type": "BALANCE"
}The header and body should then be base64url encoded and signed, with the signature appended as per the JOSE standard for JWS. It is recommended that you use an established library 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
ewogICJhbGciOiAiRVM1MTIiLAogICJ0eXAiOiAiSldUIiwKICAia2lkIjogIjY2M2EwZTQ0LWFhNGEtNGZmMC1hOWY4LWNkOTlmNWZiYWQ3MSIsCiAgInVybCI6ICIvdjMvcHJvZmlsZXMvMTIzNDUvdHJhbnNmZXJzLzEyMzQ1L3BheW1lbnRzIgp9
.ewogICJ0eXBlIjogIkJBTEFOQ0UiCn0=
.Z-B7ScaZ37U_0CKrv03LTi0O0GWR2Hm5shzoEj8xRmMThe request must include the following headers:
Content-Type: application/jose+jsonAccept: application/jose+jsonX-TW-JOSE-Method: jws
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'Verify the response by fetching the latest Wise public key and checking the signature. See Get Wise JWT public key 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.
$ 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>'