4. Login with Recovery Code
Login with Recovery Code
Recovery codes provide an emergency access method when you cannot use your standard Multi-Factor Authentication (MFA) methods. This scenario demonstrates how to authenticate using a recovery code when MFA is enabled on your account.
Key benefits:
Emergency access when standard MFA factors are unavailable
One-time use codes that are consumed after successful authentication
Alternative authentication path that still maintains security
Prerequisites
This scenario assumes:
1. The user has active MFA on their account
2. Recovery codes have been generated beforehand
Recovery codes must be generated in advance. Each recovery code can only be used once and is consumed after successful authentication.
Recovery codes should be stored securely. They are intended for emergency use only when you cannot access your primary MFA methods.
Step 1 - Login with MFA-enabled account
Authenticate with your username and password to obtain a session token. Since your account has MFA enabled, the token will be returned in a locked state.
This initial authentication verifies your first factor (something you know - your password)
The returned token will be locked and requires additional verification
Instead of using standard MFA factors, we'll use a recovery code in the next step
Endpoint
POST /login
Request
POST /login
Content-Type: application/json
{
"name": "mary.griffin@circularo.com",
"password": "#32Password1!",
"returnToken": true
}
Response
{
"logged": true,
"isUnlocked": false,
"token": "53gFlKxiYkb0DUyc8lEjtzLxbsJrr7JWgj8y1md9gpn9n8kjnGeVpWc7SLNUbfWn",
...
}
The response contains the following important properties:
token - Located at
tokenin the response.The authentication token that should be included in subsequent API requests. This token identifies your session and provides access to authorized resources.
Example value:
53gFlKxiYkb0DUyc8lEjtzLxbsJrr7JWgj8y1md9gpn9n8kjnGeVpWc7SLNUbfWn
Note: The token is locked initially. To access other endpoints, unlocking is required.
Step 2 - Unlock the session token using a recovery code
When you cannot access your standard MFA methods (email, SMS, or authenticator app), you can use a recovery code to unlock your session token.
Recovery codes are emergency backup codes that you should have generated and stored securely before needing them.
Each recovery code can only be used once. After successful authentication, the code is consumed and cannot be used again.
Endpoint
POST /login/recovery
Request
POST /login/recovery?token=53gFlKxiYkb0DUyc8lEjtzLxbsJrr7JWgj8y1md9gpn9n8kjnGeVpWc7SLNUbfWn
Content-Type: application/json
{
"recoveryCode": "729435"
}
Response
{
"remainingRecoveryCodes": 3,
...
}
Your session token is now unlocked using the recovery code. The recovery code has been consumed and cannot be used again.
Step 3 - Test the session token by retrieving available documents (Optional)
This endpoint demonstrates how to use your unlocked session token to perform an actual operation - in this case, searching for available documents in the system.
The session token is passed in the query parameters
The search operation returns documents the authenticated user has access to
This pattern applies to all token protected API endpoints - include your session token in each request
This is a practical example of how to use your session token for API operations. Do not call this endpoint if you don't wish to perform a search operation.
Endpoint
POST /search
Request
POST /search?token=53gFlKxiYkb0DUyc8lEjtzLxbsJrr7JWgj8y1md9gpn9n8kjnGeVpWc7SLNUbfWn
Content-Type: application/json
{
"from": 0,
"size": 10
}
Response
{
"from": 0,
"total": 224,
"results": [
{
"documentId": "01f9af91-6678-4cb0-a53b-d9ecf843e129",
...
},
...
],
"users": {
...
},
...
}
The search operation was successful, demonstrating that your session token is now fully unlocked and working correctly.
The response includes a list of documents that the authenticated user has access to.
Step 4 - Terminate the session (Optional)
Invalidates the current session token, effectively logging the user out of the system. This is an important security practice to prevent unauthorized access after a session is no longer needed.
Invalidates the token provided in the request
Prevents the token from being used for any future API requests
Should be called when a session is no longer needed
Does not affect other active sessions for the same user
This endpoint only invalidates the specific token provided in the request. Other active sessions for the same user will remain valid.
Endpoint
GET /logout
Request
GET /logout?token=53gFlKxiYkb0DUyc8lEjtzLxbsJrr7JWgj8y1md9gpn9n8kjnGeVpWc7SLNUbfWn
The session has been successfully terminated. The token is now invalid and cannot be used for further API requests.
Recovery Code Login Summary
Recovery codes provide an emergency authentication method when standard MFA factors are unavailable:
Recovery codes must be generated in advance
Each recovery code can only be used once and is consumed after successful authentication
Recovery codes should be stored securely and used only in emergency situations
Example Recovery Code Login Flow
See our OpenAPI documentation to learn about the full set of API endpoints and parameters.
Please use proper exception handling and function decomposition in your own code. The code is provided for illustrative purposes only and is not intended for production use.
// Recovery Code Login flow
const URL = "https://sandbox.circularo.com";
const API_PATH = "/api/v1";
const name = "YOUR_NAME/EMAIL";
const password = "YOUR_PASSWORD";
const recoveryCode = "YOUR-RECOVERY-CODE"; // One of your pre-generated recovery codes
let token;
try {
// Step 1: Login to get locked session token
const loginResponse = await fetch(`${URL}${API_PATH}/login`, {
method: 'POST',
body: JSON.stringify({ name, password, returnToken: true }),
headers: { 'Content-Type': 'application/json' }
});
if (!loginResponse.ok) {
throw new Error(`Login failed: ${loginResponse.status} ${loginResponse.statusText}`);
}
const loginData = await loginResponse.json();
if (!loginData.logged) {
throw new Error('Authentication failed');
}
token = loginData.token;
// Step 2: Unlock the token with a recovery code
if (!loginData.isUnlocked) {
console.log('MFA required: Using recovery code for authentication');
const recoveryResponse = await fetch(`${URL}${API_PATH}/login/recovery?token=${token}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
recoveryCode: recoveryCode
})
});
if (!recoveryResponse.ok) {
throw new Error(`Recovery code authentication failed: ${recoveryResponse.status} ${recoveryResponse.statusText}`);
}
const recoveryData = await recoveryResponse.json();
console.log(`Authentication successful. Recovery code consumed. ${recoveryData.remainingRecoveryCodes} recovery codes remaining.`);
}
// Step 3: Use the token for operations (illustrative purpose)
const searchResponse = await fetch(`${URL}${API_PATH}/search?token=${token}`, {
method: 'POST',
body: JSON.stringify({ from: 0, size: 10 }),
headers: { 'Content-Type': 'application/json' }
});
if (!searchResponse.ok) {
throw new Error(`Search failed: ${searchResponse.status} ${searchResponse.statusText}`);
}
const searchResults = await searchResponse.json();
// Step 4: Logout when done
const logoutResponse = await fetch(`${URL}${API_PATH}/logout?token=${token}`);
if (!logoutResponse.ok) {
throw new Error(`Logout failed: ${logoutResponse.status} ${logoutResponse.statusText}`);
}
console.log('Successfully logged out');
} catch (error) {
console.error('Error in authentication flow:', error.message);
// Always try to logout if we have a token, even if other operations failed
if (token) {
try {
const logoutResponse = await fetch(`${URL}${API_PATH}/logout?token=${token}`);
if (!logoutResponse.ok) {
throw new Error(`Logout failed: ${logoutResponse.status} ${logoutResponse.statusText}`);
}
} catch (logoutError) {
console.error('Failed to logout:', logoutError.message);
}
}
}