In order to authenticate that your publicly exposed endpoint is indeed being called by a Penbox webhook, the HTTP call needs to be authenticated. This can be done by verifying the JWT signature sent along in the HTTP headers. Here are the steps needed to properly authenticate an incoming HTTP request:
Assuming you system is configured with an
<issuer_origin>equal to https://connect.penbox.io/ in production
First, verify the integrity of the payload
- As the request streams into you server, or after you received the full payload, you can compute its
sha-512digest. The base64 encoded digest of the (uncompressed) raw body (the plain JSON) must match thedigestclaim from the signature. - For conveniency this digest can also be found in the
[Digestheader](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest), allowing to check the validity in two (independent) phases:- Check that the jwt is valid and ensure that its
digestclaim matches the value from theDigestheader. - Ensure that the
sha-512hash of the http payload matches the value from theDigestheader.
- Check that the jwt is valid and ensure that its
Secondly, verify the authenticity of the HTTP request by validating the JWT contained in the x-pnbx-signature header.
- The
issclaim of the JWT payload must exactly match the configured<issuer_origin> - The
expclaim, if present, must be a timestamp (seconds since epoch) that is "in the future" wrt. the time at which the HTTP request is being made. - The
nbfclaim, if present, must be a timestamp (seconds since epoch) that is "in the past" wrt. the time at which the HTTP request is being made. - The
audclaim must exactly match the endpoint being called (your endpoint's public address) - The
methodclaim must exactly match the method use by the current HTTP request - The
digestclaim must exactly match the<base64_sha-512_digest>of the request body. - The signature part of the JWT must be validated against the public key of the issuer.
- The public key can be retrieved in the JWKS format at the following endpoint
<issuer_origin>/.well-known/jwks.json - You might want to cache this value (respecting the
Cache-Controlheader)
- The public key can be retrieved in the JWKS format at the following endpoint
- For additional security, you can protect agains "replays" of the exact same HTTP requests content by ensuring that the value contained in the
jticlaim is a value that was never seen by your server before (no need to keep this value longer than the token'sexpiration date).