Authsome
1.x
Docs/Authsome/MFA Plugin
Open

Reading4 min
Updated31 Jul 2026
Sourcev1/plugins/mfa.mdx

The mfa plugin adds multi-factor authentication to Authsome. It supports TOTP (Time-based One-Time Passwords) for authenticator apps, SMS-based OTP as a second factor, and recovery codes for account recovery when the primary MFA method is unavailable.

Setup01

import (
    "github.com/xraph/authsome"
    "github.com/xraph/authsome/plugins/mfa"
)

eng, err := authsome.NewEngine(
    authsome.WithStore(store),
    authsome.WithSMSSender(smsBridge),       // Required for SMS MFA
    authsome.WithPlugin(mfa.New(mfa.Config{
        Issuer: "My App",
    })),
)

Configuration02

OptionTypeDefaultDescription
Issuerstring"AuthSome"Name displayed in authenticator apps (Google Authenticator, Authy, etc.)

Implemented interfaces03

InterfacePurpose
PluginBase plugin identity ("mfa")
OnInitCaptures SMS sender, Chronicle, Relay, hooks, logger, and ceremony store
RouteProviderRegisters all MFA endpoints under /v1/auth/mfa
MigrationProviderContributes mfa_enrollments and mfa_recovery_codes tables

TOTP enrollment04

TOTP (RFC 6238) is the recommended MFA method. It works with any authenticator app that supports the otpauth:// URI scheme.

Step 1: Start enrollment

POST /v1/auth/mfa/enroll

{"method": "totp"}

Response:

{
  "id": "amfa_01j9...",
  "method": "totp",
  "secret": "JBSWY3DPEHPK3PXP",
  "otpauth_url": "otpauth://totp/My%20App:[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=My%20App"
}

The otpauth_url can be rendered as a QR code for the user to scan with their authenticator app. The secret is displayed as a manual entry fallback.

Step 2: Verify enrollment

POST /v1/auth/mfa/verify

{"code": "123456"}

The user enters the 6-digit code from their authenticator app. On first successful verification, the enrollment is marked as verified and recovery codes are generated.

Response:

{
  "verified": true,
  "method": "totp",
  "recovery_codes": [
    "a1b2c3d4e5",
    "f6g7h8i9j0",
    "k1l2m3n4o5"
  ]
}

Recovery codes are shown only once. The user must store them securely.

SMS MFA05

SMS OTP provides a second factor using text messages. It requires an SMS bridge to be configured.

Enroll via SMS

POST /v1/auth/mfa/enroll

{"method": "sms", "phone": "+14155551234"}

The plugin sends an initial verification code to the provided phone number.

Send SMS code

POST /v1/auth/mfa/sms/send

{"phone": "+14155551234"}

Response:

{
  "sent": true,
  "expires_in_seconds": 300,
  "phone_masked": "***1234"
}

Verify SMS code

POST /v1/auth/mfa/sms/verify

{"code": "123456"}

MFA challenge flow06

During sign-in, if the user has MFA enrolled, the engine requires an MFA challenge before issuing a full session.

POST /v1/auth/mfa/challenge

{"code": "123456"}

Response:

{
  "challenge_passed": true,
  "method": "totp"
}

The challenge validates the TOTP code against the user's enrolled secret. On success, the session is upgraded to full access.

Recovery codes07

Recovery codes are generated when MFA is first verified. Each code is one-time use and bcrypt-hashed before storage.

Verify a recovery code

POST /v1/auth/mfa/recovery/verify

{"code": "a1b2c3d4e5"}

Response:

{
  "challenge_passed": true,
  "codes_remaining": 7
}

Regenerate recovery codes

POST /v1/auth/mfa/recovery/regenerate

Generates a fresh set of recovery codes, replacing all existing codes. Requires an active MFA enrollment.

Response:

{
  "codes": ["x1y2z3...", "a4b5c6...", "..."]
}

Disable MFA08

DELETE /v1/auth/mfa/enrollment

Removes the MFA enrollment for the authenticated user. Recovery codes are not automatically deleted.

Checking MFA status09

The plugin exposes a HasMFA method for programmatic checks:

mfaPlugin := mfa.New(mfa.Config{Issuer: "My App"})
// ... register and start engine ...

hasMFA := mfaPlugin.HasMFA(ctx, userID)

This checks both TOTP and SMS enrollments.

API routes10

MethodPathDescription
POST/v1/auth/mfa/enrollStart MFA enrollment (TOTP or SMS)
POST/v1/auth/mfa/verifyVerify TOTP code to confirm enrollment
POST/v1/auth/mfa/challengeVerify TOTP code during sign-in challenge
DELETE/v1/auth/mfa/enrollmentDisable MFA for the authenticated user
POST/v1/auth/mfa/recovery/verifyVerify a recovery code
POST/v1/auth/mfa/recovery/regenerateGenerate new recovery codes
POST/v1/auth/mfa/sms/sendSend an SMS verification code
POST/v1/auth/mfa/sms/verifyVerify an SMS code

Observability11

The MFA plugin emits audit events to Chronicle, webhook events to Relay, and hook events on the global bus for:

  • auth.mfa.enrolled -- MFA enrollment started

  • auth.mfa.verified -- MFA enrollment confirmed

  • auth.mfa.challenged -- MFA challenge passed

  • auth.mfa.disabled -- MFA enrollment removed

  • auth.mfa.recovery_used -- Recovery code consumed

  • auth.mfa.recovery_regenerated -- Recovery codes regenerated