Receive encrypted responses from Signicat
Signicat can send encrypted responses. This means we will encrypt the responses on the given session.
All responses from Signicat are fully encrypted on the transport layer with HTTPS. You can implement message-level encryption (MLE) as an additional security layer.
This section explains how to set up and process encrypted responses.
For FTN, you are required to receive encrypted responses. If you do not set this up correctly, FTN will fail and you will not be able to obtain any FTN authentication results.
Prerequisites
To use encrypted responses, you must first generate a key pair.
You can use our website JWK generator by Signicat to securely generate this key pair, or any other method that is convenient for you; for example, OpenSSL, or a JOSE or JWK library for the language of your choice.
- The key pair needs to be in a valid JWK format.
- The technical requirements for the keys are:
For RSA key types
Field name | Value |
---|---|
Algorithm (alg ) | RSA-OAEP |
Key type (kty ) | RSA |
For RSA, we support key sizes of 2048 bits and 4096 bits if required.
For elliptic curve key types
Support for Elliptic curve cryptography (ECC) key pairs will be available soon.
Field name | Value |
---|---|
Algorithm (alg ) | ECDH-ES |
Curve (crv ) | P-256 , P-348 , P-521 |
Key type (kty ) | EC |
Implementation
To implement encrypted responses, you need to include the additional field encryptionPublicKey
when making a request to the Create session endpoint. You can find more details about this field in our API specifications.
Following this, all of your responses for both the Create session and the Get session endpoints will be encrypted with this key. The responses will also be encrypted in our session storage. This ensures full encryption in the Authentication REST API.
Example request
{
"allowedProviders": ["nbid"],
"flow": "redirect",
"requestedAttributes": [
"firstName",
"lastName",
"dateOfBirth",
"nin"
],
"callbackUrls": {
"success": "https://postman-echo.com/get?status=success",
"abort": "https://postman-echo.com/get?status=abort",
"error": "https://postman-echo.com/get?status=error"
},
"encryptionPublicKey": {
"alg": "RSA-OAEP",
"e": "AQAB",
"kty": "RSA",
"n": "1soz_f_GSGVYfYwIRSu6mkIsyymeqjEXdO-24ffhZnrwKNEeqO9vwxVKHpAUMA55QGBhPl-epJjYjzy_24n-0qvJEwddLvo0cuO0N-ms0LhB8WlUwhLKp6pqj_AO46Pt7qyBNFlWQh3KF_UakAb1Jq1P97Ba0FAIXJBaTKvnZ5hxwJY5i2tPA_NNQT5D40nqc0BNWS0Iv6Ww9oYfQn3pecyOygTFGMTg2SQ3t-4XRGaKclOwExIWTJTv21slOBMJQLomO0hJtnRAB9aBZRgit8K41TzuBp_wpbFlYLoep8lRyG-n2A_1yHlww1P2pVzmlynNDO87ERek6EyI6uPZvQ",
"use": "enc"
}
}
Example response
HTTP/2 200
Content-Length: 2048
Content-Type: application/jose
Date: Tue, 07 Feb 2023 15:08:43 GMT
eyJh...QifQ.Qq5TQR...xN-PQ.ojSGehTV7xw_xE078sFnTg.in8a...SITqA.SyVNrXe0C3UkKBQ_AVyQiw
The response will now say Content-Type: application/jose
instead of the usual Content-Type: application/json
. This tells you that the response is a JWE (JWT) as per RFC 7516: JSON Web Encryption (JWE).
You can now use your private key from the key pair you created earlier to decrypt this message. The payload of the JWE is a JSON structure that is exactly the same as a non-encrypted reply, so you will be able to continue with your normal implementation once you have decrypted the payload.
Example code
This code example is for illustrative purposes only. It is not intended for use in production. Signicat will not be held responsible if this code example is used inappropriately.
from jwcrypto import jwk, jwe
# ATTENTION: Insert your nested JWT (that you received from the Signicat Authentication REST API) here.
jwe_serialized = "eyJh...QifQ.Qq5TQR...xN-PQ.ojSGehTV7xw_xE078sFnTg.in8a...SITqA.SyVNrXe0C3UkKBQ_AVyQiw"
# For the sake of simplicity in this example, the JWKs have been manually loaded into a dictionary.
# In practice, you should do this in a secure manner. The jwe_private_key should be stored securely on your premises.
jwe_private_key = {
"alg": "RSA-OAEP",
"d": "IchOWqQUx_S2sRJqB5Ub5aDEYlTiuXJ8tb3xRgPCjieGZ-kSOTBlo-mQjZOMNU3FeOBf0xtffJR0tTyxEWLYM0LlHorRN28PekWBpiyo63AboRB3zgl-GdZmKcrwUJILPXeg376wYDhGvbNlkOMjQkjOk87HTc3Urthed4IvJH4N7SpHBuzFHucb_1Zcq7i_UZrvQecNZoODoeTJIeaN4LoN4AB63Jc75doVBvTqyyKl39VdrdDzsv17WOq_HjFe0KLwFGjK6VEQbiaNMS7Jh6XoKVkiVLKT2uzyzpWCHu68gB6BDuItlllhbMYYCW9yoC7mFkWroG_EZj8PJL-58Q",
"dp": "UU2ygH3JEjmyTEiOmNHSpoDjnn5JR0nmZDZ4AOrEUMuMmXbnkNfXN5vGmo8hBZbWUBcXN5CkeGysiFByldfw1oVRlNoA1np00Gtb_8RsaElcIr1aWSgACArCsbhplDNSzNDPjm6FvW21Rkdm0AwVmak7YgtMgodq1TLBUwd_-uE",
"dq": "VqinrWjEIgryjHdQmb_cFhxGFN167EvM5PSjrj3w1Dg6453MKZjriJmIT8LZbbcrLalkaeje2PK0Koy1ZEyBvmRHlZDShX8AigXeY2s478wWVk03bsJyWcrMO2Lokal_Zn6_ULJYkmIHPoXzzB56odEqxgQnP1ZM0O0nS2J76k0",
"e": "AQAB",
"kty": "RSA",
"n": "1soz_f_GSGVYfYwIRSu6mkIsyymeqjEXdO-24ffhZnrwKNEeqO9vwxVKHpAUMA55QGBhPl-epJjYjzy_24n-0qvJEwddLvo0cuO0N-ms0LhB8WlUwhLKp6pqj_AO46Pt7qyBNFlWQh3KF_UakAb1Jq1P97Ba0FAIXJBaTKvnZ5hxwJY5i2tPA_NNQT5D40nqc0BNWS0Iv6Ww9oYfQn3pecyOygTFGMTg2SQ3t-4XRGaKclOwExIWTJTv21slOBMJQLomO0hJtnRAB9aBZRgit8K41TzuBp_wpbFlYLoep8lRyG-n2A_1yHlww1P2pVzmlynNDO87ERek6EyI6uPZvQ",
"p": "2m4looTgE4Gx8Uu8mTjv3PGlHLYuG5zTIJAG9joxnOO-JdvIwUIi4Kc4QN-cJJpZsdpBQs5HKcI4F6TFccO_lx7q4xgXgzGBTMy6lLsYgFgIBM0SWXqQ3Ws35ewt40v9Zhs0kaRSpzuS0Pik90cwsPcMexB2BJ3kTSEgMctEDLE",
"q": "-7vDS1Cu9RuXX7Xktg6Ftn-FGiCQQ26is7s-ixwv0XGhV2nxzzKKhNcattYWFnOAA91NOzBy8XWaDMli2vNqqSlcDnvAZGpppv-nJRD3wyVvcYWV3Bi_xGsjh5NiyEC8RQOj5rzZ9jP3EJdw3pvfAZj_ncSfwpuGH9ESPaJssM0",
"qi": "coF8GU0fQ9-KcZfz2Vp8Si4MwzQElFwaAkJX64cZe57-IjDYWlU66VMB1tsoJbCWt_vWOSmOCXROVOSYIdI85y_W2PtSjRGxKInMlQ7MGpqhAVv75nD_k0yf2y8AFZk4SCoiVFlQWJ44Ke8vaf7FTKBCgzbznkY2xvBqYRv7N8Y",
"use": "enc"
}
# Loading JWK key
jwk_jwe_private_key = jwk.JWK()
jwk_jwe_private_key.import_key(**jwe_private_key)
jwetoken = jwe.JWE()
jwetoken.deserialize(jwe_serialized)
jwetoken.decrypt(jwk_jwe_private_key)
payload = jwetoken.payload.decode('unicode_escape')
print(payload)