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

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 8 Next »

Specification

Apiary
POSTmithril/api/tokens
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


С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 

Logic WS

  • Check login exist
    • If login exist
      • Get user by $.email
      • Validate user.password = $.password
      • If invalid -  Update user (set values) by $.user_id
        • Increment `users.priv_settings.login_error_counter` (+1)
        • If `users.priv_settings.login_error_counter` > USER_LOGIN_ERROR_MAX
          • Blocked user - update user (set values) by $.user_id
            • is_blocked = TRUE
            • block_reason = "OTP verify attempts more then USER_LOGIN_ERROR_MAX"
            • updated_at = now()
  • Validate user `is_blocked` flag
    • if is_blocked = TRUE
    • return 4xx - "User blocked"  (!!! TBD)
  • 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.  
      • !!! TBD - Need get factor from user (WS: Set2FA)
      • ....
    • If  exist 2FA active item for user with non-empty factor - go to new process authentication with 2FA
      • invoke proc `create_OTP()`
      • return 2fa_access_token + code 201
    • If not exist 2FA active item for user  go to standart process without 2FA
      • return access_token + code 201

Response

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

С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 4xx - "User blocked"  (!!! TBD)
  • 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 = 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 = "OTP verify attempts more then 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 409 error "Not found active OTP" - ??? or 401 ?
    • 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_countOTP_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 4xx - "User blocked"  (!!! TBD)
  • 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
  • Update 2fa_access_token (set `tokens.details.used`=true)
  • Create & return new 2fa_access_token 
  • Invoke internal function `create OTP (key)`, for 2FA.type = SMS, with params:
    • key = 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