Prerequisites
The main idea of this project is to create application which manages user's profiles and its bunch of back-end and front-end are configured
via configuration of back-end. So if certain properties are changed on back-end side, then front-end is changed in appropriate way
to match configuration of back-end. One of such configured flows is Login flow which is described in this documentation.
There are two possible login flows: one-step login and several steps login. The flow depends on property
systemBehaviorConfigurations/multifactorAuthentication/multifactorAuthSystemEnabled. Hence, if it's set to true,
then several step login flow is chosen for the system (both on front-end and back-end sides). Otherwise, one-step
login is performed. Also login as one-step action performed in case of using third-parties (Google, Facebook etc.)
Firstly, login via third-parties is described.
Login via third-party (Google, Facebook etc.)
An ability to login into the system can be performed in several different ways depending on configuration of back-end.
Default configuration allows to perform login:
- via email;
- via phone number;
- via Google;
- via Facebook;
- via Okta;
- via Twitter.
Login via third-parties (Facebook, Google etc.) can be disabled for the system. In such case
there are no appropriate buttons on front-end and also back-end doesn't process requests for appropriate endpoints.
To disable desired option, e.g. Facebook, an appropriate property must be set to desired value in application.yaml
in section systemBehaviorConfiguration/oauth2. For Facebook it's systemBehaviorConfiguration/oauth2/facebook
and the value false.
As mentioned above, such changes lead to changing of system's behavior both on front-end and back-end sides.
Changes on front-end | Changes on back-end |
---|---|
If login option (facebook, google etc.) disabled, then an appropriate button disappears from login page | If login option (facebook, google etc.) disabled, then endpoint for appropriate option (e.g. /api/v1/login/facebook) isn't registered and exposed, so an attempt to reach it leads to error with the message "No handler." |
Listed login options can be enabled or disabled in any combinations.
If you want to add another third-party for login flow, please, refer to the article sign in/up with social networks.
Endpoint's path for a third-party has the following pattern: /api/v1/login/thirdParty'sName.
These endpoints are created and exposed by Spring, but redirect URI can be configured via application.yaml.
Several steps login flow
The main difference between one-step login and several steps login is requirement to provide a one-time tokens
for user's enabled MFA (multi-factor authentication) options for additional security. So, if user has enabled MFA
for email, then only one-time token which is sent to user's email should be provided, if both email and phone number
MFA enabled, then two one-time tokens should be provided by user to complete login operation.
Login flow: the 1st step
To choose several steps login, login operation must be performed via email or phone number. Also, application.yaml must have the following configuration:
... systemBehaviorConfigurations: multifactorAuthentication: multifactorAuthSystemEnabled: true ...
Path: /api/v1/login
Request and response structures
If login via email/phone number are chosen, then request must have the following structure:
{ "userKey": "email/phone number", "password": "user password" }
In such case, response contains listed below information:
{ "processingId": "processing ID of the operation", "email": "user's email", "phoneNumber": "user's phone number", "enabledMfaSteps": { "emailVerificationEnabled": true|false, "phoneNumberVerificationEnabled": true|false, "googleAuthenticatorVerificationEnabled": true|false } }
Login flow: the 2nd step
Path: /api/v1/token/login
The next step in several steps login flow is to request from the system one-time tokens for user's enabled MFA options.
So, depending on enabled MFA options request and response have the following structures:
{ "destination": "EMAIL|PHONE_NUMBER", "processingId": "processing ID from the previous step" }
{ "destination": "user's email or phone number, depends on destination chosen in request", "expiration": "30 MINUTES" }
After requesting and getting one-time tokens for all enabled MFA options, the final step of login can be performed.
Login flow: the 3rd step
Path: /api/v1/login/verification
This step is final action which should be performed to successfully finish several steps login flow.
On that step one-time tokens for all user's enabled MFA options which the user has got must be provided.
The request and response have structures, listed below. Note, that MFA option is disabled for user, then
null must be passed as its value.
{ "userKey": "user key entered on the first step", "processingId": "processing ID from the first step", "oneTimeTokens": { "emailToken": "email one-time token"|null, "smsToken": "phone number one-time token"|null, "googleAuthenticatorToken": "google authenticator one-time token"|null } }
{ "accessToken" : "access token", "refreshToken": "refresh token" }
As access and refresh tokens are handled by front-end, then for user after the last step follows redirect to main page.
One-step login flow
If additional security isn't required, then one-step login flow can be chosen.
For that MFA should be disabled for the system. In such case login flow is changed
to one-step login.
NOTE 1: If you want to have a one-step login flow in the system, then MFA should
be disabled for the whole system which affects other operations and makes them
less secure, especially User key (email and phone number) recovery flow.
NOTE 2: Login via third-parties is configured separately from MFA, so it can be
performed in both cases.
So application.yaml should be configured as following:
... systemBehaviorConfigurations: multifactorAuthentication: multifactorAuthSystemEnabled: false ...
If login is performed via email or phone number with the following configuration,
then only one action should be performed for login.
Path: /api/v1/login
{ "userKey": "email/phone number", "password": "user password" }
{ "accessToken" : "access token", "refreshToken": "refresh token" }
NOTE: As you can see, endpoint with the same path ("/api/v1/login") has different responses
depending on system configuration. It's achieved due to custom logic of @RegisterEndpointCondition
annotation, which allows to map different method to the same path depending on configuration.
If you have any questions regarding login flow or any other questions, feel free to contact Diakonov Serhii (s.dyakonov@knubisoft.com) or Kostenko Vadym (v.kostenko@knubisoft.com)
Add Comment