Multi-Factor Authentication

Sphere supports multiple MFA methods: TOTP (authenticator apps), OTP (email codes), magic links, and WebAuthn (passkeys). Users can enable multiple methods simultaneously for maximum flexibility and security.

When MFA is enabled, the login endpoint returns a 202 response with an mfa_token instead of a full token set. The client must then verify the MFA challenge using one of the endpoints below before receiving access tokens.


GET/auth/api/v1/auth/mfa/status

Get MFA status

Retrieve the current MFA configuration for the authenticated user. Returns which methods are enabled and their details.

Request

GET
/auth/api/v1/auth/mfa/status
curl https://your-sphere.example.com/auth/api/v1/auth/mfa/status \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response

{
  "data": {
    "enabled": true,
    "methods": ["totp", "webauthn"],
    "totp": {
      "enabled": true,
      "confirmed_at": "2026-01-15T10:30:00Z"
    },
    "webauthn": {
      "enabled": true,
      "credentials": [
        {
          "id": "abc123def456",
          "name": "MacBook Pro Touch ID",
          "created_at": "2026-02-01T14:20:00Z",
          "last_used_at": "2026-02-24T08:15:00Z"
        }
      ]
    }
  }
}

POST/auth/api/v1/auth/mfa/verify

Verify MFA challenge

Complete the MFA verification step during login. After receiving a 202 response from the login endpoint with an mfa_token, submit the verification code for the chosen MFA method. On success, returns the full token set.

Required attributes

  • Name
    mfa_token
    Type
    string
    Description

    The MFA token received from the login endpoint's 202 response.

  • Name
    method
    Type
    string
    Description

    The MFA method being used. One of totp, otp, or recovery_code.

  • Name
    code
    Type
    string
    Description

    The verification code from the authenticator app (TOTP), email (OTP), or a recovery code.

Request

POST
/auth/api/v1/auth/mfa/verify
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/verify \
  -H "Content-Type: application/json" \
  -d '{
    "mfa_token": "mfa_abc123def456...",
    "method": "totp",
    "code": "123456"
  }'

Response

{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "def50200a1b2c3d4e5f6...",
    "token_type": "Bearer",
    "expires_in": 3600
  },
  "meta": {
    "services": {
      "auth": "https://your-sphere.example.com/auth",
      "core": "https://your-sphere.example.com/core",
      "chat": "https://your-sphere.example.com/chat",
      "voip": "https://your-sphere.example.com/voip",
      "drive": "https://your-sphere.example.com/drive",
      "activity": "https://your-sphere.example.com/activity",
      "usermanager": "https://your-sphere.example.com/usermanager",
      "notes": "https://your-sphere.example.com/notes",
      "mail": "https://your-sphere.example.com/mail"
    }
  }
}

POST/auth/api/v1/auth/mfa/totp/setup

Setup TOTP

Begin the TOTP (Time-based One-Time Password) setup process for the authenticated user. Returns a shared secret, a QR code URL for scanning with an authenticator app, and a provisioning URI. The setup is not complete until the user confirms it with a valid TOTP code via the confirm endpoint.

This endpoint requires authentication and accepts no request body.

Request

POST
/auth/api/v1/auth/mfa/totp/setup
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/totp/setup \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response

{
  "data": {
    "secret": "JBSWY3DPEHPK3PXP",
    "qr_code_url": "data:image/png;base64,iVBORw0KGgo...",
    "provisioning_uri": "otpauth://totp/Sphere:admin%40acme.local?secret=JBSWY3DPEHPK3PXP&issuer=Sphere"
  }
}

POST/auth/api/v1/auth/mfa/totp/confirm

Confirm TOTP setup

Complete the TOTP setup by verifying a code from the user's authenticator app. This confirms that the user has successfully configured their authenticator and activates TOTP as an MFA method. Returns a set of one-time recovery codes that the user should store securely.

Required attributes

  • Name
    code
    Type
    string
    Description

    A valid 6-digit TOTP code from the user's authenticator app.

Request

POST
/auth/api/v1/auth/mfa/totp/confirm
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/totp/confirm \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"code": "123456"}'

Response

{
  "data": {
    "recovery_codes": [
      "a1b2c3d4e5",
      "f6g7h8i9j0",
      "k1l2m3n4o5",
      "p6q7r8s9t0",
      "u1v2w3x4y5",
      "z6a7b8c9d0",
      "e1f2g3h4i5",
      "j6k7l8m9n0"
    ]
  },
  "message": "TOTP has been enabled successfully."
}

DELETE/auth/api/v1/auth/mfa/totp

Disable TOTP

Disable TOTP for the authenticated user. Requires the user's current password for security confirmation. If TOTP is the user's only MFA method, MFA will be fully disabled.

Required attributes

  • Name
    password
    Type
    string
    Description

    The user's current password to confirm the action.

Request

DELETE
/auth/api/v1/auth/mfa/totp
curl -X DELETE https://your-sphere.example.com/auth/api/v1/auth/mfa/totp \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"password": "SecurePass123!"}'

Response (204 No Content)

// No response body

POST/auth/api/v1/auth/otp/send

Send OTP

Send a one-time password to the user's email address. The OTP is valid for a limited time (typically 10 minutes). This endpoint is public and does not reveal whether the email address exists in the system.

Required attributes

  • Name
    login
    Type
    string
    Description

    The email address to send the OTP to.

Request

POST
/auth/api/v1/auth/otp/send
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/otp/send \
  -H "Content-Type: application/json" \
  -d '{"login": "user@example.com"}'

Response

{
  "message": "If the account exists, a verification code has been sent."
}

POST/auth/api/v1/auth/otp/verify

Verify OTP

Verify a one-time password sent via email. On success, returns a full token set, completing the authentication flow.

Required attributes

  • Name
    login
    Type
    string
    Description

    The email address the OTP was sent to.

  • Name
    code
    Type
    string
    Description

    The 6-digit OTP code received via email.

Request

POST
/auth/api/v1/auth/otp/verify
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/otp/verify \
  -H "Content-Type: application/json" \
  -d '{
    "login": "user@example.com",
    "code": "123456"
  }'

Response

{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "def50200a1b2c3d4e5f6...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}

POST/auth/api/v1/auth/magic-link

Send a magic link to the user's email address for passwordless authentication. The link contains a one-time token that expires after a limited time. This endpoint is public and does not reveal whether the email address exists.

Required attributes

  • Name
    login
    Type
    string
    Description

    The email address to send the magic link to.

Request

POST
/auth/api/v1/auth/magic-link
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/magic-link \
  -H "Content-Type: application/json" \
  -d '{"login": "user@example.com"}'

Response

{
  "message": "If the account exists, a magic link has been sent."
}

POST/auth/api/v1/auth/magic-link/verify

Verify a magic link token received via email. On success, returns a full token set, completing the passwordless authentication flow.

Required attributes

  • Name
    token
    Type
    string
    Description

    The one-time token extracted from the magic link URL.

Request

POST
/auth/api/v1/auth/magic-link/verify
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/magic-link/verify \
  -H "Content-Type: application/json" \
  -d '{"token": "eyJpdiI6Ik1UQXlNek0wTlRZM09EazAi..."}'

Response

{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "def50200a1b2c3d4e5f6...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}

POST/auth/api/v1/auth/mfa/webauthn/register/options

Get WebAuthn registration options

Generate WebAuthn registration options for adding a new passkey to the authenticated user's account. Returns a publicKey object compatible with the Web Authentication API's navigator.credentials.create() method. The challenge is cached server-side with a 5-minute TTL and can only be used once.

This endpoint requires authentication and accepts no request body.

Request

POST
/auth/api/v1/auth/mfa/webauthn/register/options
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/webauthn/register/options \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response

{
  "data": {
    "publicKey": {
      "rp": {
        "name": "Sphere",
        "id": "your-sphere.example.com"
      },
      "user": {
        "id": "dXNlci0xMjM0NTY...",
        "name": "admin@acme.local",
        "displayName": "Admin User"
      },
      "challenge": "Y2hhbGxlbmdlLXJhbmRvbS1ieXRlcw...",
      "pubKeyCredParams": [
        { "type": "public-key", "alg": -7 },
        { "type": "public-key", "alg": -257 }
      ],
      "timeout": 300000,
      "attestation": "none",
      "authenticatorSelection": {
        "authenticatorAttachment": "platform",
        "residentKey": "preferred",
        "userVerification": "required"
      }
    }
  }
}

POST/auth/api/v1/auth/mfa/webauthn/register/verify

Complete WebAuthn registration

Complete the WebAuthn registration by submitting the attestation response from the browser's navigator.credentials.create() call. On success, the passkey is stored and WebAuthn is enabled as an MFA method. Returns the credential ID and recovery codes.

Required attributes

  • Name
    id
    Type
    string
    Description

    The credential ID returned by the authenticator (base64url-encoded).

  • Name
    rawId
    Type
    string
    Description

    The raw credential ID (base64url-encoded).

  • Name
    response
    Type
    object
    Description

    The attestation response object containing attestationObject and clientDataJSON (both base64url-encoded).

  • Name
    type
    Type
    string
    Description

    Always "public-key".

  • Name
    name
    Type
    string
    Description

    Optional human-readable name for the passkey (e.g., "MacBook Pro Touch ID").

Request

POST
/auth/api/v1/auth/mfa/webauthn/register/verify
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/webauthn/register/verify \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "id": "abc123def456...",
    "rawId": "abc123def456...",
    "response": {
      "attestationObject": "o2NmbXRkbm9uZWdhdHRT...",
      "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4u..."
    },
    "type": "public-key",
    "name": "MacBook Pro Touch ID"
  }'

Response

{
  "data": {
    "credential_id": "abc123def456...",
    "name": "MacBook Pro Touch ID",
    "recovery_codes": [
      "a1b2c3d4e5",
      "f6g7h8i9j0",
      "k1l2m3n4o5",
      "p6q7r8s9t0",
      "u1v2w3x4y5",
      "z6a7b8c9d0",
      "e1f2g3h4i5",
      "j6k7l8m9n0"
    ]
  },
  "message": "Passkey registered successfully."
}

POST/auth/api/v1/auth/mfa/webauthn/authenticate/options

Get WebAuthn authentication options

Generate WebAuthn authentication options for verifying a passkey during login. Returns a publicKey object compatible with the Web Authentication API's navigator.credentials.get() method. The challenge is cached server-side with a 5-minute TTL.

Required attributes

  • Name
    login
    Type
    string
    Description

    The user's email address. Used to look up registered passkeys.

Request

POST
/auth/api/v1/auth/mfa/webauthn/authenticate/options
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/webauthn/authenticate/options \
  -H "Content-Type: application/json" \
  -d '{"login": "admin@acme.local"}'

Response

{
  "data": {
    "publicKey": {
      "challenge": "cmFuZG9tLWNoYWxsZW5nZS1ieXRlcw...",
      "rpId": "your-sphere.example.com",
      "allowCredentials": [
        {
          "id": "abc123def456...",
          "type": "public-key",
          "transports": ["internal"]
        }
      ],
      "timeout": 300000,
      "userVerification": "required"
    }
  }
}

POST/auth/api/v1/auth/mfa/webauthn/authenticate/verify

Complete WebAuthn authentication

Complete WebAuthn authentication by submitting the assertion response from the browser's navigator.credentials.get() call. On success, returns a full token set.

Required attributes

  • Name
    id
    Type
    string
    Description

    The credential ID returned by the authenticator (base64url-encoded).

  • Name
    rawId
    Type
    string
    Description

    The raw credential ID (base64url-encoded).

  • Name
    response
    Type
    object
    Description

    The assertion response object containing authenticatorData, clientDataJSON, and signature (all base64url-encoded).

  • Name
    type
    Type
    string
    Description

    Always "public-key".

  • Name
    login
    Type
    string
    Description

    The user's email address used during the options step.

Request

POST
/auth/api/v1/auth/mfa/webauthn/authenticate/verify
curl -X POST https://your-sphere.example.com/auth/api/v1/auth/mfa/webauthn/authenticate/verify \
  -H "Content-Type: application/json" \
  -d '{
    "id": "abc123def456...",
    "rawId": "abc123def456...",
    "response": {
      "authenticatorData": "SZYN5YgOjGh0NBcPZHZg...",
      "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4u...",
      "signature": "MEUCIQDp7xBJhG..."
    },
    "type": "public-key",
    "login": "admin@acme.local"
  }'

Response

{
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh_token": "def50200a1b2c3d4e5f6...",
    "token_type": "Bearer",
    "expires_in": 3600
  },
  "meta": {
    "services": {
      "auth": "https://your-sphere.example.com/auth",
      "core": "https://your-sphere.example.com/core",
      "chat": "https://your-sphere.example.com/chat",
      "voip": "https://your-sphere.example.com/voip",
      "drive": "https://your-sphere.example.com/drive",
      "activity": "https://your-sphere.example.com/activity",
      "usermanager": "https://your-sphere.example.com/usermanager",
      "notes": "https://your-sphere.example.com/notes",
      "mail": "https://your-sphere.example.com/mail"
    }
  }
}

DELETE/auth/api/v1/auth/mfa/webauthn/{credentialId}

Remove a passkey

Remove a specific WebAuthn credential (passkey) from the authenticated user's account. If this is the user's last passkey and no other MFA methods are enabled, WebAuthn will be fully disabled as an MFA method.

URL parameters

  • Name
    credentialId
    Type
    string
    Description

    The ID of the WebAuthn credential to remove.

Request

DELETE
/auth/api/v1/auth/mfa/webauthn/{credentialId}
curl -X DELETE https://your-sphere.example.com/auth/api/v1/auth/mfa/webauthn/abc123def456 \
  -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."

Response (204 No Content)

// No response body

Was this page helpful?