ЕСОЗ - публічна документація

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 19 Current »

Specification

Apiary
POSTmithril/api/tokens
Scopeno scope

Purpose

Modification  existing WS: Create a user:

  • Add handling logic for return different type of tokens by 2FA_Statuses (2fa_access_token, access_token)
  • Add logic for process authorization 2 factor via OTP
  • Add logic for process resend OTP via create new token (grant_type = resend_otp)

Request parameters

Add handling logic for combinations of request parameters:

ONE OF:  

CREATE_2FA_TOKEN
- grant_type = "password"
- email
- password
- client_id
- scope = "app:authorize"

OR

AUTHORIZE_OTP
- grant_type = "authorize_2fa_access_token"
- token = 2fa_access_token
- otp 

OR

RESEND_OTP
- grant_type = "refresh_2fa_access_token" 
- token = 2fa_access_token

Peculiar properties of 2fa_access_token

 An 2FA flow feature implementation, we need restrict ability call WS: Approvals with `2fa_access_token`, and allow call WS: Approvals with `access_token ()`.

It means the following 

2FAReturn token_typescopes in token.details
Disableaccess_token

"scope": "app:authorize"

Enable 2fa_access_token

"scope": ""

Change `2fa_access_token`  →  `access_token`access_token"scope": "app:authorize"


Сase `CREATE_2FA_TOKEN` (grant_type = "password")

Purpose

Add handling logic for return different type of tokens by user 2FA Status.

  • if 2FA = disable, return access_token
  • if 2FA = enable, return 2fa_access_token , create & send OTP

Check ability login with invalid  password per same period.


Logic WS

  • Check login exist
    • If login exist
    • Get user by $.email
    • Validate user `is_blocked` flag
      • if is_blocked = TRUE
      • return 401 - "User blocked" 
    • Validate user.password = $.password
    • Check ability login (see section on page below) 
  • Get active 2FA item for non-blocked user by $.user_id

    SELECT *
    FROM authentication_factors AS 2FA
    	INNER JOIN user AS U
    		ON 2FA.user_id = U.id
    WHERE 
    	U.id = $.user_id
    		AND U.is_active = TRUE
    		AND U.is_blocked = FALSE
    		AND 2FA.is_active = TRUE
    • If exist 2FA active item with empty factor.  
      • Add to response `urgent.next_step` = REQUEST_FACTOR
      • create new & return 2fa_access_token + code 201
    • If  exist 2FA active item for user with non-empty factor - go to new process authentication with 2FA
      • invoke OTP timeout procedure
      • If successful - invoke proc `create_OTP()`
      • If OTP successful sending: add to response `urgent.next_step` = REQUEST_OTP
        • else: add to response `urgent.next_step` RESEND_OTP
      • create new & return 2fa_access_token + code 201
    • If not exist 2FA active item for user  go to standart process without 2FA
      • Add to response `urgent.next_step` = REQUEST_APPS 
      • create new &return access_token + code 201

Response

  • 201 if token successful create & return
  • 4xx in other case

Check ability login

Purpose 

We store fail attempts (existing user/login + invalid password) in array at `user.priv_settings.login_hstr` and validate count such logins above limit.

Logic 

  • Sort array `login_hstr[]` DESC by `time`
  • Get count() items with `type = "password"` from array for period from `now()` to `now() - MAX_FAILED_LOGINS_PERIOD`
  • IF count() >= MAX_FAILED_LOGINS THEN
    • return 401 error + message “You reached login attempts limit. Try again later”
  • ELSE
    • clear otp_hstr[] for `type = "password"`

Сase `AUTHORIZE_OTP` (grant_type = "authorize_2fa_access_token")

Purpose

Verify OTP & prolongation authentication process (return access_token for getting approvals) .

Logic WS

  • Validate token (2fa_access_token) for grant+_type "authorize_2fa_access_token" 
    • If invalid - return error 4xx 
  • Validate user id & user status
  • Validate user `is_blocked` flag
    • if is_blocked = TRUE
    • return 401 - "User blocked" 
  • Get active 2FA item for non-blocked user by $.user_id

    SELECT *
    FROM authentication_factors AS 2FA
    WHERE 
    	2FA.user_id = $.user_id
    		AND 2FA.is_active = TRUE
    • If not found - return 409 error "Not found 2FA data for user"
  • Extract type & factor from 2FA item for user
  • Invoke internal function `verify_OTP ( key, code)`, for 2FA.type = SMS, with params:
    • key = token + 2FA.faсtor
    • code = $.otp
  • Get result of call `verify_OTP()`  
  • If result = VERIFIED
    • Update user (set values) by $.user_id
      • users.priv_settings.otp_error_counter = 0

    • Update 2fa_access_token (set `tokens.details.used`=true)
    • Create & return new access_token (as a existing standart process without 2FA)
    • Return 201
  • If result = UNVERIFIED
    • Update user (set values) by $.user_id
      • Increment `users.priv_settings.otp_error_counter` (+1)
    • If `users.priv_settings.otp_error_counter` > USER_OTP_ERROR_MAX
      • Blocked user - update user (set values) by $.user_id
        • is_blocked = TRUE
        • block_reason = "Passed invalid OTP more than USER_OTP_ERROR_MAX"
        • updated_at = now()
    • return 401 error

Internal logic for `verify_OTP()`

  • Find 1 active OTP (status = NEW) for $.key
    • If not found - return 401 error "Invalid OTP"
    • If found -  increment  `attempts_count` (+1) for this OTP
      • If OTP.code = $.code - update OTP item:
        • OTP status  ( NEW → VERIFIED)
        • updated_at = now()
      • If (OTP.code <> $.code ) AND (OTP.attempts_count > USER_OTP_ERROR_MAX 
        • Update OTP item
          • status ( NEW → UNVERIFIED)
          • updated_at = now()

Response

  • 201 if OTP successful verifiyng, create & send 
  • 4xx in other case

Сase ` RESEND_OTP` (grant_type = "refresh_2fa_access_token")

Purpose

Refresh (create new) 2fa_access_token, create &send new OTP item for user via current 2FA factor.

Logic WS

  • Validate token (2fa_access_token) for grant_type = "refresh_2fa_access_token"
    • If invalid - return error 4xx 
  • Validate user id & user status
  • Validate user `is_blocked` flag
    • if is_blocked = TRUE
    • return 401 - "User blocked"  
  • Get active 2FA item for non-blocked user by $.user_id

    SELECT *
    FROM authentication_factors AS 2FA	
    WHERE 
    	2FA.user_id = $.user_id
    		AND 2FA.is_active = TRUE
    • If not found - return 409 error "Not found 2FA data for user"
  • Extract type & factor from 2FA item for user
  • Termionate 2fa_access_token 
  • Create & return new 2fa_access_token 
  • invoke OTP timeout procedure
  • If successful - Invoke internal function `create OTP (key)`, for 2FA.type = SMS, with params:
    • key = token + 2FA.faсtor
    • Get result of call `create OTP()` as `OTP_value` 
  • Sending (delivery) OTP via channel communication 
    • for 2FA.type = SMS - via SMS gateway API
      • mobile phone = 2FA.factor
      • SMS text = OTP_value 
  • Return 201

Internal logic for `create OTP()`

  • Processed OTP lists for $.key
    • Deactivate all active OTP items (NEW → CANCELED)
  • Create new OTP item
    • status = NEW
    • expired_at = now() + OTP_LIFETIME
    • value = generate number according OTP_LENGTH
    • updated_at = now()

Response

  • 201 if OTP successful create & send 
  • 4xx in other case
  • No labels