3. Login with MFA
Multi-Factor Authentication (MFA) Login
Multi-Factor Authentication (MFA) provides an additional layer of security for your Circularo account by requiring a second verification step after entering your password. This scenario demonstrates how to authenticate when MFA is enabled on your account.
Key benefits:
Enhanced security through multi-factor verification
Protection against unauthorized access even if your password is compromised
Support for multiple authentication factors including email, SMS, and authenticator apps
Prerequisites
This scenario assumes the user has active MFA on their account. Users can activate MFA either themselves using the Preferences -> Security settings, or it can be enforced by an administrator.
When MFA is enabled, you'll need to complete both authentication steps before you can access protected resources.
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
You'll need to complete the MFA challenge before you can use the token
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": "L9Gyrr8JswCjh6Vm4iDMrKt1kDOKLyWwbFrWPemRUYZBQiFqzCIYjVpeep7gI9RP",
...
}
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:
L9Gyrr8JswCjh6Vm4iDMrKt1kDOKLyWwbFrWPemRUYZBQiFqzCIYjVpeep7gI9RP
Note: The token is locked initially. To access other endpoints, unlocking is required.
Step 2 - Unlock the session token
In the previous step, MFA was invoked and dispatched. Assuming the "email" was configured as the MFA factor in the user account, an email containing the verification code was sent.
Utilize the received code in this call to unlock your session token.
Other MFA provider options include "sms" for text message verification and "totp" for time-based one-time passwords from authenticator apps.
Endpoint
POST /login/unlock
Request
POST /login/unlock?token=L9Gyrr8JswCjh6Vm4iDMrKt1kDOKLyWwbFrWPemRUYZBQiFqzCIYjVpeep7gI9RP
Content-Type: application/json
{
"factors": [
{
"factor": "email", //MFA factor, other options are \"sms\" and \"totp\"
"password": "271008"
}
]
}
Response
{
"isUnlocked": true,
"factors": [
{
"factor": "email",
"unlocked": true,
...
}
]
}
Your session token is now unlocked, allowing you to access protected resources and API endpoints.
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=L9Gyrr8JswCjh6Vm4iDMrKt1kDOKLyWwbFrWPemRUYZBQiFqzCIYjVpeep7gI9RP
Content-Type: application/json
{
"from": 0,
"size": 10
}
Response
{
"from": 0,
"total": 224,
"results": [
{
"documentId": "cac05412-ca16-449f-b472-bdc5d8202b7d",
...
},
...
],
"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=L9Gyrr8JswCjh6Vm4iDMrKt1kDOKLyWwbFrWPemRUYZBQiFqzCIYjVpeep7gI9RP
The session has been successfully terminated. The token is now invalid and cannot be used for further API requests.
MFA Login Summary
Multi-Factor Authentication provides enhanced security for your Circularo account:
Initial authentication requires your username and password
A second factor verification is required to unlock the session token
Once unlocked, the session token functions identically to a regular session token
Session tokens remain valid for 30 days by default after being unlocked
Example MFA 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.
// MFA Login flow
const URL = "https://sandbox.circularo.com";
const API_PATH = "/api/v1";
const name = "YOUR_NAME/EMAIL";
const password = "YOUR_PASSWORD";
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 MFA
if (!loginData.isUnlocked) {
console.log('MFA required: Token is locked and requires additional authentication');
// Obtain the MFA code from an email / SMS / authenticator app
const mfaCode = getMfaCode();
const unlockResponse = await fetch(`${URL}${API_PATH}/login/unlock?token=${token}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
factors: [{
factor: "email", // or "sms" or "totp"
password: mfaCode
}]
})
});
if (!unlockResponse.ok) {
throw new Error(`Unlock request failed: ${unlockResponse.status} ${unlockResponse.statusText}`);
}
const unlockData = await unlockResponse.json();
if (!unlockResponse.isUnlocked) {
//Token still not unlocked - there may be more factors to unlock, see the response for details
throw new Error(`Token not unlocked`);
} else {
//Token is unlocked and ready to be used now
}
}
// 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);
}
}
}