Skip to Content
MuoCeon Docs
Third-party OAuth IntegrationPermissions and security

Authentication strength and step-up

Use acr_values and max_age to require stronger authentication.

For some operations "the user has signed in" is not enough — deleting data, changing security settings, viewing sensitive information all need confirmation that it is the user right now. MuoCeon expresses authentication strength with ACR (Authentication Context Class Reference), and lets you require a minimum level in the authorization request.

Two strength levels

LevelURNMeaningTypically achieved by
AAL1urn:muoceon:acr:aal1Baseline authenticationKnowledge factors such as a password or recovery code
AAL2urn:muoceon:acr:aal2Possession-factor authenticationpasskey, or an authenticator on the device

The check is "meets or exceeds", not exact equality: after signing in with a passkey, requesting aal1 is satisfied as well.

How to require a higher strength

Add two parameters to the authorization request:

&acr_values=urn:muoceon:acr:aal2
&max_age=300
  • acr_values is an ordered preference list (space-separated); the server picks the highest level it can satisfy. Send only the level below which you will not accept.
  • max_age is the maximum accepted authentication age in seconds. max_age=300 means "authentication must have happened within 5 minutes"; max_age=0 demands immediate re-authentication — do not use it unless genuinely required.

What happens when strength is insufficient

This is the part of the flow that is most transparent to third parties:

  1. The user's current strength is insufficient, or the authentication age exceeds the limit;
  2. The consent UI receives 401 INSUFFICIENT_USER_AUTHENTICATION, and the consent ticket is not consumed;
  3. The user is taken to the step-up page and completes stronger authentication (for example inserting a passkey);
  4. Afterwards they return to the consent UI with the original parameters and confirm again;
  5. The callback you finally receive is identical to the normal flow — it merely arrives a few dozen seconds later.

Do not implement step-up yourself

The step-up page, tickets and assertions are internal MuoCeon mechanisms. All you do is declare the requirement in the authorization request; the consent UI handles the retry. If you build compensation such as "wait a moment and retry the authorization" in your callback, you will end up submitting an already-successful authorization twice.

acr and auth_time in the token

Tokens carry the facts of this authentication so you can make a second judgement:

{
  "acr": "urn:muoceon:acr:aal2",
  "auth_time": 1760000000
}
  • acr: the level actually reached in this authentication.
  • auth_time: when the authentication happened, as a Unix timestamp in seconds.

For high-sensitivity endpoints, do an explicit server-side check: acr meets the requirement and auth_time is recent enough. A token being valid is not the same as the user having authenticated just now.

When to require AAL2

ScenarioRecommendation
Read-only display of username, emailNot required; AAL1 suffices
Changing account security settings, deleting dataRequire aal2 plus a small max_age
Long-term offline access (offline_access)Require aal2 at first authorization, then rely on refresh tokens
Background batch jobsDo not use an interactive flow; consider a machine client

Over-requiring sharply reduces consent rates

A user without a passkey will be stuck on the step-up page by acr_values=aal2. Unless the business genuinely needs it, do not require AAL2 for ordinary sign-in.

On this page