Katalys ⇢ Merchant
From Katalys to the Integration
When Katalys issues HTTP sends Directives , the tokens are generated along the same guidelines as described in the Katalys ⇠ Merchant section. Take the time to read that first. The following section will describe the same process from the opposite perspective, so a few key points will be repeated.
In order to integrate with Katalys correctly, an integrator must verify that the requests are indeed coming from Katalys and have not been tampered with. We will now describe the authentication process from the perspective of an integrator (the receiver of the HTTP request).
The authentication process is based on PASETO tokens.
We can’t overstate how important it is to use an existing library (if available) to implement the process described in this section instead of implementing the algorithm yourselves.
Step 1: Read the token
HTTP requests sent by Katalys to integrators will include an Authorization
header in the following format: Authorization: Bearer TOKEN
. Let’s look at an example:
Authorization: Bearer v2.local.qwfi6mZ_xiom0Lz9dztkZ6p-_uXD06sb6DDHAe0UQbZbg7ESXD-h_izsciKQrR8P_WmrtQENAR4acJ0FEXpPUjEcUPwuYtYzKrqiS-naLkrNr-H2VWxDpQa8Zw2YtKBjM_aD.IntcImtpZFwiOlwiMGEzMTU2NjAtNGJiNy00MjI4LTk0MDgtZjQzMDA3MzMwNjZmXCJ9Ig
In order to read the token we drop the Bearer
prefix. What remains is a PASETO token:
v2.local.qwfi6mZ_xiom0Lz9dztkZ6p-_uXD06sb6DDHAe0UQbZbg7ESXD-h_izsciKQrR8P_WmrtQENAR4acJ0FEXpPUjEcUPwuYtYzKrqiS-naLkrNr-H2VWxDpQa8Zw2YtKBjM_aD.IntcImtpZFwiOlwiMGEzMTU2NjAtNGJiNy00MjI4LTk0MDgtZjQzMDA3MzMwNjZmXCJ9Ig
PASETO tokens consist of three or four segments (in our case we will be working with four) separated by a period:
version.purpose.payload.footer
Step 2: Verify version and purpose
When decoding a token, we start by verifying the version and the purpose. The version must equal to v2
and the purpose must equal to local
.
If the token does not match these two constraints we must reject the token as invalid.
Step 3: Decode the footer
The footer is a Base64-encoded JSON object. Continuing with the above example, the footer is:
IntcImtpZFwiOlwiMGEzMTU2NjAtNGJiNy00MjI4LTk0MDgtZjQzMDA3MzMwNjZmXCJ9Ig
After base64-decoding:
{"kid":"0a315660-4bb7-4228-9408-f4300733066f"}
This gives us the kid
or the key ID. Using this value we can fetch the appropriate shared secret.
This mechanism allows us to have multiple keys, which in turn allows us to rotate the keys without downtime. It is very likely that at the start of the integration process you will only have a single key. It is still important that you verify that the key ID is correct.
Step 3: Verify the signature
At this point we will repeat our mantra: you should use a PASETO library for this whole process, and especially for this step.
Let’s assume that in the previous step we fetched the following shared secret:
kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
(secrets are 32 bytes long)
If we pass the token and the shared secret to our library, we should be able to read the decoded payload:
{"exp":"2023-11-03T14:50:30Z","iat":"2023-11-03T14:50:30Z"}
exp
is the Expiration time and iat
is the Issued At time.
We must verify that iat
is in the past and that exp
is in the future.
This makes the token valid and authenticates the request. We can proceed servicing the request.
Troubleshooting
Certain shared hosting providers strip the Authorization
header from incoming requests.