This article describes, how to enable and use multi factor authentication (MFA) from the backend point of view.
Currently there is just one additional authentication factor implemented, making this effectively a two factor authentication (2FA).
We choose Google Authenticator, a "Time-based One-time Password" (TOTP) implementation.
Switching on MFA
As an authenticated user, that has editing rights to the targeted user
PUT {{baseUrl}}/users/{userid}/googleauth Body: {"enabled":true} Result
user dto: { ... "googleAuthEnabled": true, "googleAuthPending": true, ... }
The call of this endpoints sets above two flags for the user. They indicate, that from now on MFA is enabled, and that the "enrollment" is pending.
With "enabled": false you would switch it off, again. Both flags were then set to "false".
Switching on MFA for an already enabled user, would set both flags to "true", starting a new "enrollment".
Authenticating using MFA
After switching on the MFA, a shared secret has to be exchange during the first login process:
First MFA login, step 1:
In the first step, we login with user name and password:
POST {{baseUrl}}/app/auth Body: {"username":"example@azeti.net","password":"Welcome123"} Result A reduced app object: { ... "token" :"eyJh....", "nextAuthentications": [ "GOOGLE_AUTH" ], "secret": "M5EDV7WC2CMEWWPO" ... }
The above three fields of the returned object are needed to proceed:
token is not the regular authentication token, but a special factor-1 token. It can only be used to authenticatie for the endpoint, that we call in the next step.
nextAuthentications contains a list of names for the next authentication factor. Currently this list contains just the one implemented factor GOOGLE_AUTH.
secret is the shared secret, that is used as a key to create a new account in the google authenicator mobile app. This secret is only shown during "enrollment", when the "googleAuthPending" flag is set for that user.
After creating the account, the mobile app shows verification codes, that keep changing after a short time interval.
First MFA login, step 2:
We use the above factor-1 token, and the verification code, in this example "453453", that the mobile app currently shows for new account.
Header : X-Authorization: {{token}} POST {{baseUrl}}/app/mfauth Body: { "googleAuth": "453453"} Result Regular app object:
...
After this step, the user is successfully logged in, meaning, the returned token is a regular token.
The "googleAuthPending" flag for this user s now set to "false", googleAuthEnabled is still "true"
The following logins, step 1:
The MFA logins from now on don't exchange the secret anymore. Anything else works the same.
POST {{baseUrl}}/app/auth Body: {"username":"example@azeti.net","password":"Welcome123"} Result A reduced app object: { ... "token" :"eyJh....", "nextAuthentications": [ "GOOGLE_AUTH" ], "secret": null, ... }
The following logins, step 2:
We use the above factor-1 token, and the verification code, in this example "345645", that the mobile app currently shows.
Header : X-Authorization: {{token}} POST {{baseUrl}}/app/mfauth Body: { "googleAuth": "345645"} Result Regular app object:
...
After this step, the user is successfully logged in, meaning, the returned token is a regular token.