reactive-interaction-gateway
reactive-interaction-gateway copied to clipboard
Support for automatic public key rotation
The only way to set public key for JWT token verification is currently done by setting JWT_SECRET_KEY during RIG startup.
However, it is recommend to rotate the keys in a certain time interval (Okta does it every 3 months). It can become quite annoying to setup automation for rotating the key when it requires a restart of the entire server.
The key is usually exposed via a JWKS endpoint in a standard format where the verifier (RIG) can fetch the latest valid version of the key.
JWKS URIs of major identity providers:
- Cognito: https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
- OAuth0: https://YOUR_DOMAIN/.well-known/jwks.json
- Okta: https://{app-id}.okta.com/oauth2/v1/keys
- Azure: https://login.microsoftonline.com/common/discovery/keys
I am proposing the implementation of functionality similar to node-jwks-rsa that could be used for fetching the key periodically and caching it for a certain time.
RIG could introduce couple of config params for this behavior:
JWKS_ROTATION_ENABLED=true [optional, default false]
JWKS_URI=https://YOUR_DOMAIN/.well-known/jwks.json [required if ENABLE_JWKS is true]
JWKS_CACHE_RETENTION=120 (in minutes) [optional, default 60 mins]
The above would be an alternative to setting JWT_SECRET_KEY manually.
Resources:
- https://hexdocs.pm/joken_jwks/introduction.html (jwks elixir library)
- https://auth0.com/docs/jwks
- https://tools.ietf.org/html/rfc7517
- https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
- https://developer.okta.com/authentication-guide/tokens/validating-access-tokens/#retrieve-the-json-web-keys
Thanks for the well-written report - great idea! 👍
For this issue, do the changes occur in claims.ex or utils.ex (modifying / enhancing signer function)?
I can try to take this up and see where it goes.
@arana3 In RIG.JWT the secret key is taken from the configuration via config().jwt_conf. One idea could be to periodically change the environment variable that underlies it, which would update the jwt_conf in turn without touching the current code. But I'd have to look into this in more detail to see whether this is a viable solution or just a dirty hack. Alternatives would be: custom Confex adapter, custom ETS based implementation. Feel free to play around :)
Looks we have to do some sort of custom coding...
Using joken_jwks requires upgrade to Joken2, which in turn requires refactoring code. Joken 2 has breaking changes, affecting generate(), signer(), and validate().
I'm creating a new issue for upgrading to Joken2.