Security Best Practices
Building a secure integration with ChainIT requires more than just implementing the OAuth flow. Follow these best practices to protect your application, your users, and your data.
1. Always Use PKCE for IDP
PKCE (Proof Key for Code Exchange) is an extension to the Authorization Code flow that prevents authorization code injection attacks.
- Mandatory: ChainIT requires PKCE for all IDP applications.
- Method: Always use the
S256code challenge method. - Why? It ensures that only the application that initiated the login can exchange the authorization code for a token, even if the code is intercepted.
2. Secure Secret Management
Your clientSecret is the master key for your application. If leaked, an attacker can impersonate your backend and access your organization's data.
- Never Expose in Client-Side Code: Never include secrets in JavaScript, mobile apps, or public repositories.
- Use Environment Variables: Store secrets in
.envfiles (added to.gitignore) or system environment variables. - Use a Secret Manager: For production, use a dedicated service like AWS Secrets Manager, HashiCorp Vault, or Azure Key Vault.
- Rotate Secrets Regularly: If you suspect a leak, regenerate your
clientSecretimmediately in the Developer Portal. For low-downtime rollouts, use a grace period when rotating.
3. Audience Validation
When your backend receives a token, always verify that the aud (Audience) claim contains your application's clientId.
- Why? An attacker could obtain a token intended for another application and try to use it against your API. Validating the audience ensures the token was issued specifically for your service.
4. Validate Token Signatures
Never trust a token's payload without verifying its signature.
- Access tokens (RS256): Fetch public keys from your org’s JWKS URL and verify the signature.
- ID tokens (RS256): Verify against the same JWKS URL as access tokens. Do not use your
clientSecretto verify ID tokens. - Algorithm enforcement: Configure your JWT library to accept only
RS256for both access and ID tokens, and reject any token presenting a differentalg(especiallynoneorHS256). - Refresh tokens: Treat them as opaque secrets — they are not JWTs; never try to “decode” them as such.
5. Implement Token Hardening
- Short-Lived Access Tokens: Use the shortest practical expiration time (e.g., 1 hour) to minimize the impact of a leaked token.
- Secure Refresh Token Storage: If your application uses refresh tokens, store them in a secure, server-side database or encrypted mobile storage.
- Revoke Tokens on Logout: Call the Revocation Endpoint when a user logs out to invalidate their session.
6. Whitelist Allowed Origins
Register every web origin that hosts your ChainIT integration in URL White Listing (CORS).
- Why? Origin whitelisting prevents unauthorized websites from making API calls or embedding your OAuth flow using your
clientId. Without it, an attacker could copy your client ID and credentials into their own site and impersonate your application. - How: Add each origin — production, staging, local dev — under URL White Listing (CORS) when creating or editing your application in the Developer Portal.
- Rule: Never use a bare
*wildcard. The portal rejects it. - Note: Origins must match exactly — protocol (
https://vshttp://), host, and port all count.
For IDP applications, the allowed origins list controls CORS for API calls, while callback/redirect URLs control where the OAuth authorize endpoint redirects the user. Both must be configured correctly. See the full origin whitelisting guide.
7. HTTPS Only
Ensure all communication with ChainIT and your own backend happens over HTTPS. Access tokens transmitted over plain HTTP can be easily intercepted by "man-in-the-middle" attacks.