supabase-rb-rb
Auth

Create and verify a challenge

Challenge and verify an MFA factor in one call.

Shortcut that combines mfa.challenge and mfa.verify into a single call. Useful for TOTP, where you already have the user's code in hand and don't need a separate "send the SMS" step. The challenge ID is generated internally and threaded into verify automatically.

A live session is required — the inner challenge call raises Supabase::Auth::Errors::AuthSessionMissing if the user is signed out.

Signature

supabase.auth.mfa.challenge_and_verify(params)

params is a hash. Pass it as a literal or use Ruby's hash-literal shorthand.

Parameters

NameTypeRequiredDescription
factor_idStringRequiredThe ID of the enrolled factor to challenge + verify.
codeStringRequiredThe one-time code the user supplied — for TOTP, the 6-digit code from their authenticator app.
channelStringOptionalPhone factors only. Forwarded to the inner challenge — "sms" or "whatsapp".

Returns

Returns
Supabase::Auth::Types::AuthMFAVerifyResponse

Same shape as mfa.verify: :access_token, :token_type, :expires_in, :refresh_token, :user. The local session is updated and MFA_CHALLENGE_VERIFIED is dispatched.

Example — TOTP verify in one call

# Most common use: user already has a 6-digit code from their authenticator app.
verify = supabase.auth.mfa.challenge_and_verify(
  factor_id: factor_id,
  code: "123456"
)

verify.access_token   # => upgraded JWT (aal2)

Example — equivalent two-step form

# These two snippets are equivalent:

# Combined:
supabase.auth.mfa.challenge_and_verify(factor_id: factor_id, code: code)

# Explicit:
challenge = supabase.auth.mfa.challenge(factor_id: factor_id)
supabase.auth.mfa.verify(
  factor_id: factor_id,
  challenge_id: challenge.id,
  code: code
)

Example — phone factor with channel

# Note: this still makes TWO HTTP calls (challenge then verify), so the user
# must already have received the SMS/WhatsApp code from a prior challenge —
# or the inner challenge will send a new one and you'll need to wait for it.
verify = supabase.auth.mfa.challenge_and_verify(
  factor_id: phone_factor_id,
  channel: "sms",
  code: user_supplied_code
)

:channel is forwarded to the inner challenge call. If you want the channel selection, pass it; otherwise leave it off and the default is "sms".

On this page