github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/design/authnz/reset-password.md (about)

     1  ## Motivation
     2  - As a user I want to reset password so that I can continue working with my account
     3  
     4  ## Principles
     5  - password reset operation is secured by 6-digit verification code sent to the email
     6  - code is correct -> it is possible to reset password for an unlimited amount of times
     7  - code is wrong -> tries amount is limited to 3 times per hour per profile
     8  - passord is reset for `CDoc<registry.Login>`, not for `CDoc<sys.UserProfile>`
     9  - `c.registry.ResetPasswordByEmail` has no rate limits
    10  
    11  ## Functional design
    12  - `sys/registry/pseudoProfileWSID/q.sys.InitiateResetPasswordByEmail`
    13    - null auth
    14    - `loginApp/profileWSID/q.sys.InitiateEmailVerification` is called under the hood with `forRegistry` mark with system auth
    15  - `sys/refgistry/pseudoProfileWSID/q.registry.IssueVerifiedValueTokenForResetPassword`
    16    - null auth
    17    - `loginApp/profileWSID/q.sys.IssueVerfiedValueToken` is called under the hood with `forRegistry` mark with system auth
    18  - `sys/registry/pseudoProfileWSID/c.registry.ResetPasswordByEmail`
    19    - null auth
    20  
    21  ## Technical design
    22  Notes:
    23  - `c.registry.ResetPasswordByEmail` called at pseudo profile because `CDoc<registry.Login>` is located there
    24  - `q.sys.InitiateEmailVerification` should be called at login's app:
    25    - profileWSID exists at the login's app
    26    - we call `sys/registry/profileWSID/q.sys.InitiateEmailVerification`
    27    - we should get "workspace not inizalized error" **but** we do not because query processor currently does not checks that
    28    - we got "workspace is not initialized error" when `c.sys.SendEmailVerification` because command processor checks that
    29    - conclusion - should call `loginApp/profileWSID/q.sys.InitiateEmailVerification`
    30  - `q.sys.IssueVerifiedValueToken` should also be called at loginApp because it accepts a token issued for `loginApp`, not for `sys/registry`
    31  ```mermaid
    32  sequenceDiagram
    33  	participant u as User
    34  	participant pp as sys/regisry/<pseudo-profile-wsid>/c,q
    35    participant p as loginApp/<profile-wsid>/c,q
    36    participant m as loginApp/<profile-wsid>/Projector<Mailer>
    37  
    38  	u->>pp: q.sys.InitiateResetPasswordByEmail(appName, Email) (ACL none)
    39  	activate pp
    40      pp->>pp: find the login
    41      pp->>p: q.sys.InitiateEmailVerification(forRegistry) (with sys token)
    42      activate p
    43        p->>p: check rate limits
    44        p->>p: generate VerificationToken and VCode
    45        p--)m: Email with VCode
    46        activate m
    47        p->>pp: token for sys/registry/profileWSID
    48      deactivate p
    49      pp->>u: token for sys/registry/profileWSID, profileWSID
    50  	deactivate pp
    51  
    52    m--)u: Email with VCode
    53    deactivate m
    54  
    55    u->>pp: q.registry.IssueVerifiedValueTokenForResetPassword(VerificationToken, VCode, profileWSID) (ACL none)
    56    activate pp
    57      pp->>p: q.sys.IssueVerifiedValueToken(forRegistry) (with sys token)
    58      activate p
    59        p->>p: check rate limits
    60        p->>p: check code and issue verifiedValueToken
    61        p->>p: code ok -> reset rate limit
    62        p->>pp: verifiedValueToken for sys/registry/profileWSID
    63      deactivate p
    64      pp->>u: VerifiedValueToken for sys/registry/profileWSID
    65    deactivate pp
    66  
    67  	u->>pp: c.registry.ResetPasswordByEmail(verified Email, newPassword, appName) (ACL none)
    68  	activate pp
    69  		pp->>pp: read CDoc<registry.Login>, login = Email
    70  		pp->>pp: update CDoc<registry.Login>.pwdHash with newPassword
    71      pp->>u: 200ok
    72  	deactivate pp
    73  ```
    74  
    75  ## Limitations
    76  - //TODO issued Principal Tokens are kept valid after password reset
    77  - //TODO works only if Login == Email
    78  - //TODO it is possible to reset password for an unlimited amount of times when the verified value token is still valid (10 minutes)
    79  - //TODO WSID where the token is using must  be the same the token is issued for. To be done in [Check WSID on Verified Field value apply](https://dev.heeus.io/launchpad/#!25720)
    80  
    81  ## Appendix: Best practices
    82  ### Google
    83  - account with phone (not confirmed) and an alternative email
    84    - never logged in
    85      - via alternative email
    86        - enter the alternative email
    87          - wrong -> error
    88        - 6-digit code is sent to the alternative email
    89        - wrong code enter for 3 times -> "Too many retires. Try again later"
    90      - via phone
    91        - asked the telephone number
    92            -  wrong -> error
    93        -  6-digit code is sent via SMS
    94        -  3 times entered wrong -> Too many retries. Try again later
    95        -  "I don't have my phone" button pressed
    96            - enter the alternative email
    97              - wrong -> error
    98            - 6-digit code is sent to the email
    99            - Try another way button pressed -> "You did not provided enough info to restore".
   100    - logged in, then logged out
   101      - "Forgot password" button pressed
   102      - "Try anoter way" button pressed
   103      - "You could change the password because you have already log in on this device". Suggested to enter a new password w\o any codes
   104  - account w\o phone and alternative email
   105    - "forgot password" pressed for the account that has neither phone nor alternative email -> "failed to ensured that it is your account". Impossible reset the password.
   106  
   107  ### Amazon
   108  - aked for 6-digit code sent to the email, then suggested to enter a new password
   109  - wrong code entered for 10 times -> stop to ask the code, back to the form with email input box. I.e. the sent code becomes obsoleted after 10 tries.