Skip to main content

OAuth2 Key Rotation in AM 6.5

With OAuth2 being the defacto authorization model many of our customers use, we made a few improvements to how AM handles the use of secrets in v6.5 that is released later this year.  The nightly build features some neat improvements in the secrets management API.

The API has been overhauled, to make it simpler to use, simpler to integrate and more secure.  As you'd expect. A neat focus was on simplifying the use case of key rotation.  Rotation is an essential part of deployment models - either as a reaction to a breach (and implementing the 3 R's paradigm) or a simple best practice.  Here I'll show a simple demo for rotating an RSA key used to sign OAuth2 stateless access tokens.

Firstly few intro bits regarding the new Secrets Management setup.  We now have a new global configure option, for Secret Stores.

Here we see two out of the box key stores configured.  The basic Java keytore.jceks and a default-passwords-keystore used for bootstrapping access.

The default-keystore config, is useful for testing and dev, where you can quickly access the local file system based Java keystore.  The config for this is pretty straightforward.  The entrypass and storepass settings are de-referenced in the default-passwords-store, where these encrypted values are read from the filesystem to bootstrap access.

In production, many customers tho are likely to want to integrate with PKCS#11 fronted Hardware Security Modules (HSM's) or even a cloud vault.

Within the keystore configuration, there is a new mappings tab.  This tab is the interesting aspect with respect to rotation.  Here we can add in active and multiple secondary keys for specific purposes.  These purposes allow focused use of keys within the secrets API.  A general good practice is to have very focused use of key material, which is declared and can't be mis-configured.

Each secret id maps to the internal secrets API.  The active alias is the one currently in active circulation.  Clicking within an id, shows that other secondary alias's can be setup.  If for example, verification of an access_token fails with the active key, the secondary ones are tried.  Depending on what token type is presented to AM, if a JWT, AM can quickly match the kid in the header and map the appropriate secondary keys in the list.

The alias names are mapped into whatever is in the keystore.

So what does this mean in reality?  Well let me setup my OAuth2 provider to use the detault.rsa.sig.key signing alias for my stateless access_tokens.  Within the realm level OAuth2 service, click on the new Secrets tab.  This shows the default mappings come from my keystore.  On the Advanced tab, make sure to change the signing algorighm to be RS256.

After switching my provider to use stateless JWT's and not stateful server side tokens, I go through and issue myself a bearer token payload...with a nice access_token.

Lots of letters in that one.  Net-net, if I quickly decode the stateless access_token header, I see it was signed with a key id of the following:

If I now introspect the token against the ../oauth2/introspect endpoint, all is good and the token is good to go.

So, now I want to introduce a new signing key to the situation.  There are numerous ways to generate keys, so do this the way you feel is best.  I created a simple script, that creates a 2048 bit RSA private key, then imports into my AM ../openam/keystore.jceks file.

If I do a keytool -list on that keystore, I will see the my new key called newrsasigningkey:

So far so good.  I now simply update the mapping in my keystore config to use my new key and also make the new key my active key.

This basically means, that any new access_tokens being issued, will be signed with the new key,  and any inbound token that needs verifying, will try the new key first, then fall back to use the original test key second.  Simply allowing existing tokens signed with the old key to be validated correctly.

An access_token issued with the newrsasigningkey will have a new key id in the JWT header:

However, both the first and second access_tokens issued can be verified by the ../introspect endpoint.

Another neat bi-product, is that all of the configuration done via the UI above, could be done simply by using the native REST API's.  Easily viewable in the API explorer.  Simply copy and paste the necessary code widget into your app.

NB - worth noting, that when you create the new test key, make sure that the storepass entered via the keytool, matches that in the entrypass value in AM.


  1. Thanks for the post Simon, we are looking forward to 6.5 and Secret Stores!


Post a comment

Popular posts from this blog

WebAuthn Authentication in AM 6.5

ForgeRock AccessManagement 6.5 , will have out of the box integration for the W3C WebAuthn . This modern “FIDO2” standard allows cryptographic passwordless authentication – integrating with a range of native authenticators, from USB keys to fingerprint and facial recognition systems found natively in many mobile and desktop operating systems. Why is this so cool? Well firstly we know passwords are insecure and deliver a poor user experience. But aren’t there loads of strong MFA solutions out there already? Well, there are, but many are proprietary, require complex integrations and SDK’s and ultimately, don’t provide the level of agility that many CISO’s and application designers now require.  Rolling out a secure authentication system today, will probably only result in further integration costs and headaches tomorrow, when the next “cool” login method emerges. Having a standards based approach, allows for easier inter-operability and a more agile platform for chan

Implementing Zero Trust & CARTA within AM 6.x

There is an increasing focus on perimeterless approaches to security design and the buzzy "defensive security architectures".  This blog will take a brief look at implementing a contextual and continuous approach to access management, that can help to fulfil those design aspirations. The main concept, is to basically collect some sort of contextual data at login time, and again at resource access time - and basically look for differences between the two.  But why is this remotely interesting?  Firstly, big walls, don't necessarily mean safer houses.  The classic firewall approach to security.  Keeping the bad out and the good in.  That concept no longer works for the large modern enterprise.  The good and bad are everywhere and access control decisions should really be based on data above and beyond that directly related to the user identity, with enforcement as close as possible to the protected resource as possible. With Intelligent AuthX, we can start to collect an

Set Session Limits Using Context

Session limits typically cover 4 main items: total number of sessions a user can have at any one time, the max length of each session, the max idle time and max caching time. In an out of the box deployment in ForgeRock AM, these settings are configured via the session service.  However there are few tweaks than can be made to allow these settings to be run via a per user or per tree flow.  For example. think of the following scenario - user is logging via a device, location or network that has a higher risk rating.   Perhaps you would like to reduce session length on a BYOD device running an out of support version of Android to have a length of only 15 minutes.  If they switched back to their main trusted device, we can spin that back to 1hr. Another example, could be the spotting of a higher suspicion of bot activity for a particular user.  Maybe we need to set the entire quota limit to 1, to stop a bot spawning multiple sessions with the same credentials. This is all pretty trivial