Step-up Authentication max age and token lifespan

Hi erveryone,

we need to implement step-up authentication for some security relevant/sensitive actions.
We read the docs and watched https://www.youtube.com/watch?v=yLCBMQIqwAc (thanks to dasniko). But we would like to ask you if we understand it correctly:

Lets assume this authentication flow setup:
LoA 1: username password form, max age 10h
LoA 2: OTP form, max age 1 min

Together with an access token lifespan of 5 minutes.

Now the user wants to perfom some risky action. Our single page application triggers a login with an ACR “gold” mapped to LoA 2. The user authenticates with username/password and otp and is issued a token with acr: “gold” which is valid for 5 Minutes.
Our SPA gets this token and sends it to our backend which checks for the risky REST-endpoint, if acr:“gold” is in the token (and the usual other verifications on signature, expiration, audience, scopes).
Everything is fine.

2 minutes later (which is more than the max age of 1 minute of LoA 2) the user again wants to perform such an action. The token is still valid for 3 minutes, so the user/the SPA could reuse this token*.
The backend again verifies the token and accepts it, although LoA 2 is expired.

Did we miss something that prevents this behaviour? If not how can we mitigate this?

Thanks for your help :slight_smile:

*) Of course, our SPA would again trigger a login requesting the required ACR/LoA, but maybe the user does not use our SPA and calls our APIs directly or an attacker has stolen the access token and reuses that.

First, thanks for watching my video! :pray::blush:

You did nothing wrong.
Indeed you have to adjust your expiration times properly.

In your case, when the LOA 2 is just valid for 1 minute, it is still contained in a token which has its own expiration time. And a JWT may be used as long as it is not expired.
The validity of the LOA is “just” (:see_no_evil:) for issueing new tokens. So, if Keycloak issues a new access token for your client after this 1 minute, the acr claim is again reset to “silver”.

If you need more proper values in your tokens, you should align your lifetimes. Either set the LOA 2 expiration to 5 minutes, like your access token lifespan, or, set the access token lifespan to only 1 minutes (which is also more secure, as it has less time to be misused, just in case).

2 Likes

Hi, thanks for your answer.

I agree with you that reducing token lifespan or increasing maxAge would have been a good and easy solution. Unfortunately our product owners did not allow this.

We came up with

  • a custom CookieAuthenticator and ConditionalLoaAuthenticator adding a client session note “level-of-authentication-expires-at” with a value computed from the configured maxAge and the authTime stored in the loa-map
  • a mapper mapping this note to a token claim acr_exp
  • some additional logic in our frontends and backends to do the usual token validity checks and if acr is required, then also check if acr claim has the required value and acr_exp <= now

Highly customized and non-standard… have fun in the future when code is changing…

When PO think they know how security works… :man_facepalming:
(no, no prejudice, seen this more than a lot of times)