Verifying signatures
Rabo Smart Pay signs all deliveries using a cryptographically secure signature, this allows your server to mathematically verify that a delivery is, indeed, originating from Rabo Smart Pay.
Rabo Smart Pay uses JSON Web Signatures with a detached payload as its, authentication mechanism.
Rabo Smart Pay publishes its public keys at https://pay.rabobank.nl/.well-known/jwks.json. When verifying a signature you must always use one of the published keys!
Verifying signatures using the SDK
When using the smartPay.processWebhook
or equivalent method of the SDK, signature validation is taken care of
automatically.
To manually verify the signature of an event, you need to provide the "raw" bytes of the HTTP request's body, together
with the signature from the HTTP header X-SmartPay-Signature
.
- Java
- Javascript
SmartPay smartPay = new SmartPay(REFRESH_TOKEN);
String signature = request.headers(SmartPay.Headers.X_SMARTPAY_SIGNATURE);
byte[] body = request.bodyAsBytes();
boolean isValid = smartPay.verifySignature(signature, body);
if (isValid) {
// good to go
} else {
// something went wrong
}
const smartPay = new SmartPay(REFRESH_TOKEN);
const signature = req.headers['x-smartpay-signature'];
const body = req.body;
const isValid = smartPay.verifySignature(signature, body);
if (isValid) {
// good to go
} else {
// something went wroing
}
Verifying signatures without the SDK
The Rabo Smart Pay SDK provides tooling to verify signatures. You should use the SDK whenever possible.
If you are for some reason unable to use the SDK, you should at least use an existing JWT library to do the JWS creation, and signature verification. When selecting a library ensure that the following algorithms are supported:
- ES256
- ES384
- ES512
- RS256
- RS384
- RS512
A list of JWT libraries can be found at https://jwt.io/libraries.
With a suitable library in place, your server must:
- Get the value of the HTTP request header with name
X-SmartPay-Signature
. This will be the detached-jws. - Split the detached-jws on the dot character (
.
), the first part will be the header, the last part will be the signature. - Get the body of the HTTP request as an array of bytes, this will be the payload.
- Craft a JWS using the header, payload, and signature as input.
- Read the key identifier (
kid
) from the JWS. - Download the Rabo Smart Pay public keys from https://pay.rabobank.nl/.well-known/jwks.json.
- Find the public key that matches with the key identifier of the JWK.
- Verify the JWK using the public key.
This is, at its core, what the SDK does when verifying signatures.
Maybe an example for your language, or framework can be found in the cookbook.