Skip to main content

Signed responses

JWS tokens can be generated by our API instead of JSON responses. It can be very beneficial if you or your customers need to affirm the data’s origin (it guarantees data was not altered), which request was used or the timestamp of the request execution.

💡 Information: Signed responses are not enabled by default. Please contact us if you’re interested in this feature.

Request signed responses

You just need to add the following parameter to your requests to get a signed response:

# query parameter
sign_response=true

JWS Token format

The JWS token our API return follow this structure:

{
"token": "header.payload.signature"
}

First we have the header:

  • It contains information about the signature process (it is a base64-encoded JSON).

  • See the token signature verification process below.

        {
    "kid": ...,
    "typ": ...,
    "key_url": ...,
    "alg": ...,
    }

Second we have the payload:

  • It is a base64-encoded JSON with the following structure.

        {
    "request_url": ...,
    "response_timestamp": ...,
    "response_payload": ...,
    }

Finally we have the signature:

  • It is a base64-encoded bytes section.

Verify token signature

  1. Get the key_url, found in the header part.
    • You must verify that this key is hosted on a trusted host, for example oxlin.io.
  2. Retrieve the public key using the GET /sign-keys endpoint (see below)
    • You will find in the result a key with the key kid found in the header.
  3. A key may be deprecated.
    • When that’s the case, the deprecated field is set and its value is the date and time of the deprecation.
    • Any signature made with a deprecated key should not be trusted.
    • If the deprecated field is null or missing, the signature can be verified.
  4. Use the public_key field to check the signature.

Keys resources

List all keys

GET /sign-keys

The response looks like this:

[
{
"public_key": ...,
"id": ...,
"deprecated": ...,
},
{
"public_key": ...,
"id": ...,
}
]

Get a key

GET /sign-keys/{key_id}

The response looks like this:

{
"public_key": ...,
"id": ...,
}

Keys resources

PropertyMandatoryTypeDescription
idyesStringUniqueID of the key.
public_keyyesStringPEM of the public key.
deprecatednoDateTime ISO 8601 extended format is used or nullIf set, this key is deprecated and any signature using it should not be trusted.

Full exemple

Request signed responses

The first step is to use one of our endpoints with query parameters sign_response=true.
In our case we will use the following endpoint: "http://sandbox-api.oxlin.io/v2.1/accounts/111865?sign_response=true"
The response we get is:

Token Base 64

{"token":"eyJ0eXAiOiJKV1QiLCJraWQiOiJzaWcuYXBpLm94bGluLmlvIiwiYWxnIjoiUlM1MTIiLCJrZXlfdXJsIjoiaHR0cDpcL1wvc2FuZGJveC1hcGkub3hsaW4uaW9cL3NpZ24ta2V5c1wvc2lnLmFwaS5veGxpbi5pbyJ9.eyJyZXF1ZXN0X3VybCI6Imh0dHA6XC9cL3NhbmRib3gtYXBpLm94bGluLmlvXC92Mi4xXC9hY2NvdW50c1wvMTExODY1P3NpZ25fcmVzcG9uc2U9dHJ1ZSIsInJlc3BvbnNlX3RpbWVzdGFtcCI6MTY3ODI3ODY5MCwicmVzcG9uc2VfcGF5bG9hZCI6eyJhY2NvdW50X251bWJlciI6IlBFQTIzNDQ1NjY1Iiwic3RhdHVzIjoiQUNUSVZFIiwibmFtZSI6IlBFQTIzNDQ1NjY1ICh4NTY2NSkiLCJ1c2FnZSI6IlBFUlNPTkFMIiwidHlwZSI6IlNBVklOR1MiLCJpZCI6IjExMTg2NSIsImNyZWF0aW9uX2RhdGUiOjE2NzgyNzg0MTYsInNhdmluZ3MiOnsiY2FwaXRhbF9nYWluIjp7ImFtb3VudCI6LTU2OTksInBlcmNlbnQiOi00LjJ9LCJzYXZpbmdzX3R5cGUiOiJTSEFSRVMiLCJ0eXBlIjoiUEVBIiwiZWZmZWN0X2RhdGUiOjEyODcyNjY0MDAsImludmVzdGVkX3JhdyI6MTM1NTY4fSwibGFzdF9jaGFubmVsX2RlZmluaXRpb25faWQiOiI4NzAwIiwiY3VycmVuY3kiOiJFVVIiLCJjb25uZWN0aW9uX2lkIjoiNjAxMzciLCJiYWxhbmNlX2RhdGUiOjE2NzgyNzg0MTgsImJhbGFuY2UiOjkwMTkwfX0.gSkdGA7tGuxZF0olRY-48jSBtBkthDHw74GJ8PeXlNtACYg0oNBEd9LUh2BF9p3Y7s3puQL6N-F_BehmL62ZOx8qgYFgL9cwldfnaTdBkWk9KsARdIzxiqTA2t9k_4N8n8GMUrsF5w_lenJcxzZAyX1NKBsVFwgDrxNf46TFUySPuT7h_55K1yLFrTi2L2PewtT1H3zG0mYVyI8FMl9kwS-AyyeTQ6kTtfYN0utJS23JFE8bhTFHzx5usgh6wDapUqldeLdHIUWdrrJgETCSeZ8jH9m2JKQQ1itGI8wqnO5Xlv5m6GitovdEPgN3DpbZ0EsogGncXMn-U3mzUXJXfpM97liUBuVWP0I9I51iftJLYgSBKbv0fl7kRXotyn-1-njMSE_ABjdxg_CPYbf0_U4f6I4H6-eFe27MYVWOGkyXKoBnkM6fsPnc4F1MC2IrMXFE3Fym_7pUVEw3NpMwd4kh-BtQOYIxpt9kOEb0O2AIKUQVMNaZ608U-AIdYkN22QSvLeoOh3JxVE7fQdWXRyJRzP1cw_V3dvqkdSpg7nIx2UCfhXsQ95HP96f3l26zGrNeZP85HuTJftTSLpIWx47CpJu4Lu2KEGvj5FhIIzmSakIAnduHDkfsieKWkNuUaChNuGVJLZf9lgPRYCv6XEy1nFA1uNrdrgFRerqZgNI"}

JWS Token format

We are now going to decode the token obtained previously.
Here is the content once the token is decoded.

  • Header part
{
"kid": "sig.api.oxlin.io",
"typ": "JWT",
"key_url": "http://sandbox-api.oxlin.io/sign-keys/sig.api.oxlin.io",
"alg": "RS512"
}
  • Payload part
{
"request_url": "http://sandbox-api.oxlin.io/v2.1/accounts/111865?sign_response=true",
"response_timestamp": 1678278690,
"response_payload": {
"account_number": "PEA23445665",
"status": "ACTIVE",
"name": "PEA23445665 (x5665)",
"usage": "PERSONAL",
"type": "SAVINGS",
"id": "111865",
"creation_date": 1678278416,
"savings": {
"capital_gain": {
"amount": -5699,
"percent": -4.2
},
"savings_type": "SHARES",
"type": "PEA",
"effect_date": 1287266400,
"invested_raw": 135568
},
"last_channel_definition_id": "8700",
"currency": "EUR",
"connection_id": "60137",
"balance_date": 1678278418,
"balance": 90190
}
}

Verify token signature

  1. The first step will be to retrieve the value of the “key_url” key in the header.
    You must verify that the signature key is hosted on a trusted host, for example oxlin.io.

    ```bash
    http://sandbox-api.oxlin.io/sign-keys/sig.api.oxlin.io
    ```
  2. The second step will be to use the “GET KEY” endpoint to retrieve the public_key, the id match with the “kid” field in the header.

    • It will look like this:
      {
      "public_key":"-----BEGIN PUBLIC KEY-----
      BIGOAjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs1KDiMH4B/Jajmp27+kq
      dhGXH6TX2bDYBAQFQ1nBa2mgLxzRDc4ehsMOuXr47MZ8LjqSVZA9b3kIP+IdtRzV
      i6TMxUwjhYQgzxZCWXmGE1LHYBuwt7og9JJ6g2L73DC4Ly6Y8ixM2k8RFBubnN+K
      7fL7tUv9bPlsuzhSH3hx7jsksO9lsjKe7pMlFNNvtSTl/+bqQ2h8C+O6cBTbSLUX
      lUNLwZt7SJaLd8e4Mox3jP0Rpyziqi0+4GM1b9cllm7O5T//qd6m0fzdbOAhngYT
      kfpcKQXS7c4/QkV+Mk9mt9t3N+MSw0E8dyrUfQiY0SLXxUPkXwhwHD5+OV34cdFs
      iUV47uGmZtiJKQYrW5tA2duE8rFDhezdumsNzuzyTSHjsjzU3spoqj4Tyni98GKe
      vlGamhDlLT54dvDlx58+/wnZIHUI8rY1SIZ6q0c7O3gDtyCdMniinMwO+lfeiumi
      dWq+TOK16NKb4Eu/4vWF+f/nuwfPY0fFl7BDzH7UYoMP2lGeQ0jkE728OnHXpN+w
      Ch4Gpi4YRnbYF9Qtr/64RvFkCTGLkXe3dqgPj52JHznsOYUXix4WCt872jmWk970
      1hW/dzdzfzueuueuDUsjz+PvMuQBhXNDqFg4sdzVWVeJmAXOtseSxvMZPnPECWJE
      fYY74VY/qVFXGpt+iGnLPSOXI2skX==
      -----END PUBLIC KEY-----",
      "id":"sig.api.oxlin.io"
      }
  3. The third step is to check if the deprecated field is present.

    • Make sure that the deprecated field is not present.
    • If it’s still present we have a public key which is not valid.
    • exemple:
      {
      "public_key":"-----BEGIN PUBLIC KEY-----
      BIGOAjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs1KDiMH4B/Jajmp27+kq
      dhGXH6TX2bDYBAQFQ1nBa2mgLxzRDc4ehsMOuXr47MZ8LjqSVZA9b3kIP+IdtRzV
      i6TMxUwjhYQgzxZCWXmGE1LHYBuwt7og9JJ6g2L73DC4Ly6Y8ixM2k8RFBubnN+K
      7fL7tUv9bPlsuzhSH3hx7jsksO9lsjKe7pMlFNNvtSTl/+bqQ2h8C+O6cBTbSLUX
      lUNLwZt7SJaLd8e4Mox3jP0Rpyziqi0+4GM1b9cllm7O5T//qd6m0fzdbOAhngYT
      kfpcKQXS7c4/QkV+Mk9mt9t3N+MSw0E8dyrUfQiY0SLXxUPkXwhwHD5+OV34cdFs
      iUV47uGmZtiJKQYrW5tA2duE8rFDhezdumsNzuzyTSHjsjzU3spoqj4Tyni98GKe
      vlGamhDlLT54dvDlx58+/wnZIHUI8rY1SIZ6q0c7O3gDtyCdMniinMwO+lfeiumi
      dWq+TOK16NKb4Eu/4vWF+f/nuwfPY0fFl7BDzH7UYoMP2lGeQ0jkE728OnHXpN+w
      Ch4Gpi4YRnbYF9Qtr/64RvFkCTGLkXe3dqgPj52JHznsOYUXix4WCt872jmWk970
      1hW/dzdzfzueuueuDUsjz+PvMuQBhXNDqFg4sdzVWVeJmAXOtseSxvMZPnPECWJE
      fYY74VY/qVFXGpt+iGnLPSOXI2skX==
      -----END PUBLIC KEY-----",
      "id":"sig.api.oxlin.io",
      "deprecated": "2023-02-21T15:24:29.987Z"
      }
      ⬆️ ⬆️
      NOT GOOD
  4. The 4th step is to verify using the public_key that the signature is verified and valid.

    screen code sign response

    signature verified