Login & Authentication
The Tango platform supports multiple authentication methods and two-factor authentication (2FA) providers. The authentication flow varies based on the endUserTwoFactorProvider value from frontendConfiguration.
Overview
The authentication system supports:
- Username/Password authentication with configurable username type (Email or Phone)
- Multi-Factor Authentication (MFA) with multiple provider options
- Token-based session management with refresh tokens
- Biometric and local authentication for mobile apps
Authentication Flow
Flow Decision Tree
Acronyms: fc = frontendConfiguration, q: = query, m: = mutation
Step 1: Get Frontend Configuration
Before initiating login, retrieve the system configuration to determine authentication methods and MFA providers using publicQueries.frontendConfiguration.
Response Properties:
| Property | Type | Description |
|---|---|---|
authMethod | String | Determines username type: "EMAIL" or "PHONE" |
endUserTwoFactorProvider | String | MFA provider type (see table below) |
forceEmailVerification | Boolean | Whether email verification is mandatory |
Two-Factor Authentication Providers:
| Provider | Description |
|---|---|
null | MFA is not enabled - No additional authentication required |
SMS | SMS-based OTP sent by backend - Code expires in a few minutes (delays possible) |
EMAIL | Email-based OTP sent by backend - Code expires in a few minutes |
AUTHENTICATOR | TOTP app (Google Authenticator, RFC 6238) - Code expires in 30 seconds |
BIOMETRIC | Biometric authentication - Frontend implementation |
ANYLOCALAUTH | PIN, pattern lock, etc. - Frontend implementation |
BIOMETRIC and ANYLOCALAUTH are handled entirely on the frontend. The backend doesn't send codes for these providers.
Step 2: Password Authentication
Authenticate the user with username and password using authentication.passwordAuth. If MFA is required, the response contains a tempToken and the user object will be null.
Response Properties:
| Property | Type | Description |
|---|---|---|
isAuthSuccessful | Boolean | ⚠️ DEPRECATED - Whether initial authentication succeeded |
isTfaEnabled | Boolean | ⚠️ DEPRECATED - Whether 2FA is enabled for this user |
tempToken | String | Temporary token for MFA operations (if 2FA required) |
refreshToken | String | Long-lived token for session refresh (if 2FA not required) |
user | EndUserType | User details (if 2FA not required) |
isAuthSuccessful and isTfaEnabled are deprecated. If the user object is null, MFA is required and you must proceed with the appropriate MFA flow.
Step 3: MFA Flow by Provider Type
Based on frontendConfiguration.endUserTwoFactorProvider, follow the appropriate flow:
null - No MFA:
passwordAuthreturns theuserobject and login is complete
BIOMETRIC or ANYLOCALAUTH:
- Handle local authentication on frontend (biometric/PIN/pattern)
- Call
passwordAuthafter successful local auth - Login is complete -
userobject returned
SMS or EMAIL:
- Call
passwordAuth- code is sent automatically - Extract
tempTokenfrom response (userwill benull) - User enters code received via SMS/Email
- Call
codeAuthwith the code to complete login - Optional: Use
sendCodeto resend if code not received
Send the tempToken from passwordAuth response in the Authorization header for sendCode.
AUTHENTICATOR:
- Call
passwordAuth - Extract
tempTokenfrom response (userwill benull) - Call
isTwoFactorKeyConfiguredto check if MFA is set up - If configured: User enters code from authenticator app → call
codeAuth - If not configured: Setup flow (see Setup Authenticator section below)
Send the tempToken from passwordAuth response in the Authorization header for isTwoFactorKeyConfigured and setupTwoFactorKey.
Additional Flows
Setup Authenticator
If isTwoFactorKeyConfigured returns false, set up MFA before completing login:
Use authentication.setupTwoFactorKey to generate a new authenticator key.
Response from setupTwoFactorKey:
| Property | Type | Description |
|---|---|---|
authenticatorKey | String | Base32 secret key for manual entry |
formattedKey | String | QR code URL (otpauth://) for scanning |
Implementation Steps:
- Display QR code from
formattedKeyor showauthenticatorKeyfor manual entry - User scans QR code with authenticator app (Google Authenticator, Authy, etc.)
- User enters the 6-digit code from the app
- Call
codeAuthwith the code to verify setup and complete login
Code Authentication
Use authentication.codeAuth to verify the MFA code and complete login for all provider types (SMS, EMAIL, AUTHENTICATOR).
Response:
refreshToken: Store this for session managementuser: Authenticated user details withauthToken
Reset Authenticator
If the user loses access to their authenticator app, use this flow to reset it. Only available for the AUTHENTICATOR provider.
Step 1: Request Reset
Use authentication.requestAuthenticatorReset to request a reset code.
Send the tempToken from passwordAuth response in the Authorization header.
Returns: Boolean - true if reset code was sent
Behavior:
- Sends verification code via email or SMS (based on
frontendConfiguration.authMethod)
Step 2: Reset with Verification Code
Use authentication.resetAuthenticator with the verification code to reset the authenticator.
No authentication token required for this mutation.
Response: Same as setupTwoFactorKey - new QR code and secret key
Implementation Steps:
- User enters verification code received via SMS/Email
- Display new QR code from response
- User scans QR code with authenticator app
- User enters code from app
- Call
codeAuthto verify and complete login
Session Management
The successful login response includes a refreshToken. Use authentication.refresh to obtain new auth tokens without re-authenticating.
Important:
- Store
refreshTokensecurely (encrypted storage) - Use
deviceIdto track user sessions - Refresh before
authTokenexpires
Token Usage Summary
| Mutation/Query | Token Required | Token Type |
|---|---|---|
passwordAuth | ❌ No | - |
isTwoFactorKeyConfigured | ✅ Yes | tempToken |
setupTwoFactorKey | ✅ Yes | tempToken |
sendCode | ✅ Yes | tempToken |
codeAuth | ✅ Yes | tempToken |
requestAuthenticatorReset | ✅ Yes | tempToken |
resetAuthenticator | ❌ No | - |
refresh | ❌ No | Uses refreshToken parameter |
Error Handling
Common error scenarios:
- Invalid credentials:
passwordAuthreturns error - Invalid MFA code:
codeAuthreturns error - Expired temp token: Re-initiate login from
passwordAuth - Expired auth token: Call
refreshmutation withrefreshToken - Expired refresh token:
refreshmutation returns error - restart the Authentication Flow - MFA not configured: Setup required before completing login
- Code send failure: Retry using
sendCodeor contact support
Best Practices
- Secure token storage: Store
refreshTokenandauthTokenin encrypted storage - Device ID tracking: Use consistent
deviceIdfor session management - App version tracking: Always send
appVersionfor monitoring - tempToken lifecycle:
tempTokenis only valid during MFA operations - don't store permanently - QR code display: For AUTHENTICATOR, show both QR code and manual key
- Code expiry handling: AUTHENTICATOR codes expire in 30 seconds, SMS/EMAIL in a few minutes
- Frontend providers: Handle
BIOMETRICandANYLOCALAUTHentirely on frontend
Implementation Checklist
- Fetch
frontendConfigurationbefore login - Detect
authMethod(EMAIL or PHONE) for username input - Call
passwordAuthwith credentials - Check
endUserTwoFactorProvidertype - For AUTHENTICATOR: Check if
isTwoFactorKeyConfigured - If not configured: Call
setupTwoFactorKeyand display QR code - For SMS/EMAIL: Code sent automatically (optional
sendCodeto resend) - For BIOMETRIC/ANYLOCALAUTH: Implement frontend authentication
- Call
codeAuthwith user-provided code - Store
refreshTokenandauthTokensecurely - Implement
refreshmutation for token renewal - Handle MFA reset flow for lost authenticator
- Handle all error scenarios
- Test with all provider types