supabase-rb-rb
Auth

Get Authenticator Assurance Level

Inspect AAL1 / AAL2 state from the current session JWT.

Decode the current session's access token and report the user's authenticator assurance level (AAL). Use it to gate sensitive UI behind AAL2 ("user has stepped up with MFA") or to detect when a user has enrolled a factor but hasn't yet challenged it (current_level == "aal1", next_level == "aal2").

This method does NOT raise when there's no session — it returns a Struct with nil levels and an empty methods array. That lets you call it on every page load without rescuing.

Signature

supabase.auth.mfa.get_authenticator_assurance_level

Takes no arguments.

Parameters

This method has no parameters.

Returns

Returns
Supabase::Auth::Types::AuthMFAGetAuthenticatorAssuranceLevelResponse

A Struct with three fields:

  • :current_level"aal1", "aal2", or nil (no session). Pulled from the aal claim in the active JWT.
  • :next_level"aal2" if the user has any verified factor enrolled (i.e. they could step up), otherwise the same as current_level. A next_level higher than current_level is your cue to prompt the user to challenge their factor.
  • :current_authentication_methods — Array of Supabase::Auth::Types::AMREntry, each with :method (e.g. "password", "otp", "totp") and :timestamp. Sourced from the amr claim in the JWT.

Example — gate a sensitive action behind AAL2

aal = supabase.auth.mfa.get_authenticator_assurance_level

if aal.current_level != "aal2"
  if aal.next_level == "aal2"
    # User has a factor enrolled but hasn't challenged it in this session.
    redirect_to "/mfa/challenge"
  else
    # User hasn't enrolled MFA at all.
    redirect_to "/mfa/setup"
  end
end

Example — show the user how they signed in

aal = supabase.auth.mfa.get_authenticator_assurance_level

aal.current_authentication_methods.each do |entry|
  case entry.method
  when "password" then puts "Signed in with password at #{Time.at(entry.timestamp)}"
  when "otp"      then puts "Verified email OTP at #{Time.at(entry.timestamp)}"
  when "totp"     then puts "Stepped up with TOTP at #{Time.at(entry.timestamp)}"
  end
end

Example — safe to call without a session

# Even if the user is signed out, this returns a Struct rather than raising.
aal = supabase.auth.mfa.get_authenticator_assurance_level

aal.current_level                    # => nil
aal.next_level                       # => nil
aal.current_authentication_methods   # => []

Invalid amr entries (e.g. missing method) are silently dropped via .compact. In practice GoTrue always emits well-formed amr entries, so the difference only matters with hand-forged tokens.

On this page