supabase-rb-rb
Auth

List all factors

List the current user's verified MFA factors.

Return the user's enrolled MFA factors grouped by type. Useful for building "Security" settings pages where the user can see which authenticators are active and remove ones they no longer use.

Unlike most other MFA methods, this call does not raise on a missing session — it routes through get_user, which returns nil for :user when there's no session. The returned arrays are simply empty in that case.

Only verified factors are included in the :totp and :phone arrays. Unverified factors still appear in :all, so you can use this method to spot stuck enrollments too.

Signature

supabase.auth.mfa.list_factors

Takes no arguments.

Parameters

This method has no parameters.

Returns

Returns
Supabase::Auth::Types::AuthMFAListFactorsResponse

A Struct with three arrays:

  • :all — every factor on the user, in any status (unverified, verified, etc.).
  • :totp — only factors with factor_type == "totp" AND status == "verified".
  • :phone — only factors with factor_type == "phone" AND status == "verified".

Each element is a Supabase::Auth::Types::Factor with :id, :friendly_name, :factor_type, :status, :created_at, :updated_at.

Example — render a settings UI

factors = supabase.auth.mfa.list_factors

puts "Authenticator apps:"
factors.totp.each do |f|
  puts "  - #{f.friendly_name || "(unnamed)"} (added #{f.created_at})"
end

puts "Phone numbers:"
factors.phone.each do |f|
  puts "  - #{f.friendly_name || "(unnamed)"}"
end

Example — guard against unverified leftovers

factors = supabase.auth.mfa.list_factors
stuck = factors.all.select { |f| f.status == "unverified" }

if stuck.any?
  # Optionally clean these up — they don't count toward AAL.
  stuck.each { |f| supabase.auth.mfa.unenroll(factor_id: f.id) }
end

Example — check if the user has any MFA configured

factors = supabase.auth.mfa.list_factors
mfa_enabled = factors.totp.any? || factors.phone.any?

unless mfa_enabled
  redirect_to "/security/setup-mfa"
end

Reads the user's factors from get_user and partitions them client-side; there is no dedicated GET /factors endpoint. Don't confuse this with auth.admin.mfa.list_factors(user_id:), which is a different surface — see the admin MFA reference for that one.

On this page