reactive-interaction-gateway icon indicating copy to clipboard operation
reactive-interaction-gateway copied to clipboard

Support for automatic public key rotation

Open lofim opened this issue 6 years ago • 4 comments

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

lofim avatar Jun 05 '19 20:06 lofim

Thanks for the well-written report - great idea! 👍

kevinbader avatar Jun 06 '19 07:06 kevinbader

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 avatar Jun 06 '19 20:06 arana3

@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 :)

kevinbader avatar Jun 07 '19 09:06 kevinbader

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.

arana3 avatar Jun 10 '19 19:06 arana3