User login


Request description

Endpoint: /users/login

Method: POST

{
  "Content-Type": "application/json"
}

Payload example

{
  "email": "mock@mock.com",
  "password": "mock-password"
}

Payload structure

interface ILoginPayload {
  email: string; //Email related to the user who performs the authentication
  password: string; //Password related to the user who performs the authentication
}

Responses

Authentication results are always returned with status 200. Check the isSuccess field to know whether the login succeeded. Only malformed requests return 400.

Correct response

Successful authentication

Describe a successful login action

200

Response body example:

{
  "isSuccess": true,
  "accessToken": "mock-access-token",
  "accounts": [
    {
      "id": "mock-organization-id~mock-user-id",
      "userId": "mock-user-id",
      "organizationId": "mock-organization-id",
      "userType": "ORGANIZATION_OWNER",
      "organizationName": "mock-organization-name",
      "isSelected": "true",
      "groupId": "mock-group-id",
      "companyStatus": "ACTIVE",
      "customSubdomain": "mock-custom-subdomain",
      "isMandatoryMFA": false
    }
  ],
  "userId": "mock-user-id",
  "fullName": "Mock User Name"
}
Response structure:
interface ILoginResponse {
  isSuccess: boolean;
  accessToken?: string;
  accounts?: IUserAccount[];
  userId?: string;
  fullName?: string;
}

interface IUserAccount {
  id: string;                   // Account identifier (organizationId~userId)
  userId: string;               // Unique user identifier
  organizationId: string;       // Organization identifier. Use it in Select account
  userType: UserType;           // User role in this organization
  organizationName: string;     // Organization name
  isSelected: "true" | "false"; // Whether this is the selected account. Sent as a string
  groupId: string;              // Group of the user in this organization
  companyStatus?: string;       // Organization status, e.g. "ACTIVE"
  customSubdomain?: string;     // Only present when the organization has a custom subdomain
  isMandatoryMFA: boolean;      // Whether the organization requires multi-factor authentication
}

type UserType = "ORGANIZATION_OWNER" | "ORGANIZATION_ADMIN" | "REGULAR";
Description: the account marked with isSelected: "true" is the organization the access token works with. To work with another organization, use Select account.


Additional authentication step required

Describe a login that needs an extra step before returning an access token

200

Response structure

type AuthenticationChallengeResponse = {
  isSuccess: true;
  isMFARequired?: true;          // Present when the user has multi-factor authentication enabled
  isNewPasswordRequired?: true;  // Present when the user must set a new password
  challengeName: "SOFTWARE_TOKEN_MFA" | "NEW_PASSWORD_REQUIRED";
  session: string;
  userId: string;
  email: string;
};
Description: no accessToken is returned. Users with multi-factor authentication enabled, or who must change their password, cannot be used to consume the Management API. Use a user without these requirements, or complete the pending step in the administration console first.


Wrong Authentication

Describe an unsuccessful login action

200

Response body example:

{
  "isSuccess": false,
  "errorMessage": "Invalid authentication",
  "errorType": "unauthorized",
  "remainingAttempts": 4
}
Response structure
type AuthenticationResponseType = {
  isSuccess: boolean,         // Specifies the authentication status
  errorMessage: string,       // Specifies the error message
  errorType: ErrorType,       // Specifies the error type
  remainingAttempts?: number  // Attempts left for this email before it is blocked (0 to 4)
}

enum ErrorType = {
  UNAUTHORIZED = "unauthorized"
}
Description: remainingAttempts is the number of login attempts left for the email, an integer from 0 to 4. It is omitted when it cannot be calculated. The response is the same whether the account exists, does not exist or is blocked by its organization. When the attempts are exhausted remainingAttempts is 0. This state lasts until a successful login, a password recovery or an unblock from the administration console, or until 24 hours after the last attempt. While it lasts, further attempts may be answered with the 429 response below. An account blocked by its organization must be unblocked from the administration console.

Additional notes:
1. The accessToken has a limited lifetime. Read its exp claim to know when it expires and authenticate again before that moment.
2. It must be ensured that the access credentials used belong to a user who is ready to use the platform.
3. You must ensure that the credentials belong to a user with the Organization Owner or Organization Admin role.
4. Every failed attempt counts towards the user's lockout limit. Do not retry automatically with the same credentials.

Wrong responses

Bad request

Describe an invalid request

400

Response structure

type AuthenticationResponseType = {
  isSuccess: boolean, // Specifies the authentication status
  errorMessage: string, // Specifies the error message
  errorType: LoginErrorType // Specifies the error type
}

enum LoginErrorType = {
  MISSING_REQUIRED_FIELDS = "missingRequiredFields", // email or password missing
  INVALID_REQUEST_FORMAT = "invalidRequestFormat"    // body is not valid JSON
}


Too many attempts

Describe a login rejected after too many failed attempts

429

Response body example:

{"isSuccess": false, "errorType": "TOO_MANY_ATTEMPTS"}
Description: returned after too many failed login attempts for the same email. When present, the Retry-After header indicates the seconds to wait before trying again.