Security and going live
Checklist to validate before opening the integration to real users.
This list gathers the points that, in our exchanges with RPs, cause the most vulnerabilities or incidents. Tick every line before requesting production access.
Secrets
- The
client_secretand the webhook signing key are in a secrets manager or environment variables, never in the Git repository, nor in a front end, a mobile app, a ticket or a message. - They appear in no log and no error trace (watch out for
print(response.text)and configuration dumps). - You know how to rotate them (secret: request to A3BC; webhook key: versioned
v1/v2, keep both during the switch). - Sandbox and production secrets are different.
Redirect and flow
- The
redirect_uriis HTTPS in production and strictly identical to the registered one. -
stateis randomly generated, tied to the user’s session, compared on return, then deleted. -
nonceis randomly generated, tied to the session, compared with thenonceclaim of theid_token. - The code exchange is done server-side only.
- The
error/error_descriptionparameters of the callback are handled with a clear message to the user.
Tokens and claims
- The
id_tokensignature is verified, withiss,aud(yourclient_id) andexp. - Access tokens are never put in a URL, a browser-readable cookie or a log.
- Useful claims are stored on receipt (access is only guaranteed for 30 minutes).
- The code handles an absent, empty (credential pending) and unverified (
*_verified) claim, see Reading claims. - Credential expiration dates (
*.credential.expiration) are checked when your use case requires it. - You use
subas the user identifier, not the email or the name.
Personal data
- You only request the strictly necessary scopes; sensitive scopes are justified.
- Documents (identity document…) are stored encrypted, with a defined retention period, and deleted when it is reached.
- A
delayed_sharing.revokeevent triggers your deletion or anonymization rules. - Logs contain no personal data (name, birth date, social security number, document content).
- Your DPO or legal counsel has validated the processing (legal basis, information to individuals, register).
Webhook
- The endpoint is HTTPS and public.
- The signature is verified on the raw body, before any parsing, with a constant-time comparison; the key is base64-decoded.
- An event with an invalid signature gets
401and is not processed. - The endpoint answers within a few seconds (
204) and processes in the background. - Events are deduplicated on
id, in persistent storage with expiry. - Processing is idempotent: replaying it breaks nothing.
Resilience
- All outgoing calls have a timeout.
- Delayed sharing API errors are handled by
code: retry (with increasing delay) only on00001and00010, none on the others. - The discovery and JWKS are cached, with a JWKS reload if the signing key changes.
- An alert exists on sign-in, signature and webhook failures.
Going to production
- A new access request for the production environment: new
client_id,client_secret, callback and webhook URLs. - Production URLs (provided by A3BC) replace the sandbox ones by configuration, without changing the code.
- An end-to-end test was played in the sandbox, including: consent refused, invalid
state, replayed webhook, invalid signature, revoked consent.