= Resetting The Account =
The account may be reset in two circumstances: when the user changes their password, and when the user forgets their password. In both cases, the client first obtains an "accountResetToken". This token is then used to change the SRP Verifier and either reset or replace the wrap(kB) value.
== Changing the Password ==
When the user wishes to change their password, we use an SRP-based protocol to protect both old and new passwords(i.e. This puts they still know the old password through ), they first use the same code as /session/auth/start+finish, but uses a different pair of API endpoints: /password/change/auth/start and finish SRP protocol safely obtain an "authToken". They they use the "/password/change/auth/finish . The value returned by auth/finish contains start" API to exchange the authToken for an "accountResetToken" instead of the sessionToken, and the response is protected with a different set of derived keyskeyFetchToken.
This API is only used when the user knows their old password[[File: if they have forgotten the password, use the "/password/forgot" API belowPICL-IdPAuth-encrypt-passwordChange.png|Server encrypts passwordChange response]]
[[File:PICL-IdPAuthThe accountResetToken will be used below to set the new password safely. The keyFetchToken should be used first, to obtain kB, so the subsequent account reset can replace wrap(kB) with a new value. This allows the password-encryptchanging client to retain their class-passwordChangeB data.png|Server encrypts passwordChange response]]
The accountResetToken will be used below to set the new password safely. This token Requiring an authToken proves that the user has provided the correct account password recently. When the account is reset, all active sessions and tokens will be cancelled (disconnecting all devices from the account). The client should immediately establish a new session as described above.
Note that this This API requires a sessionTokenis only used when the user knows their old password: if they have forgotten the password, so use the client must have previously logged in"/password/forgot" APIs below.
== Handling a Forgotten Password ==
When the user has forgotten their password, they can use one of their "recovery methods" to obtain an accountResetToken. For now, this means we send a random code to the email address associated with their account. The user must copy this code from the email into their client, whereupon the client will get an accountResetToken that can be delivered to the API below.
Note that, since the forgotten-password client never learns kB, any class-B data will be lost. This is necessary to protect class-B data from attackers who can read the users's email but do not know the account password (including those who compromise the IdP and the keyserver itself). When using /account/reset below, they will supply set wrap(kB) to a string of all zeros, which means the server should generate a new random wrap(kB) (just as it does during account creation).
The /password/forgot/send_code API is used to ask the server to send a recovery code. This takes a recovery method, which for now is just an email address. This API is unauthenticated (after all, the user who has forgotten their password knows nothing but their email address). The server marks the corresponding account as "pending recovery", allocates a random forgotPasswordToken for the account, creates a recovery code, and sends the code (with instructions) via email. The API returns forgotPasswordToken to the client.
forgotPasswordToken can be used three times before it is exhausted. If the user guesses incorrectly this often, the client must call send_code again to get a new token and code. Each account has at most one token+code active at a time.
The recovery code is initially a random 8-digit decimal number. If an attacker tries to sign in as someone else, hits the "forgot my password" button, then submits a guess to /password/forgot/verify_code, they will have a 1-in-100-million chance of success. If the server detects too many wrong guesses, it should increase the length of new codes. Another defensive technique is to require that users click an email link before being given the code: the server is told when the link is clicked, so the code will not be enabled until the email has been read. It remains to be seen whether this will be sufficient.
The exact thresholds are TBD, but a nominal goal is to keep the chances of any attack succeeding to below 1-in-a-million per year. To achieve this, we can tolerate 100 verify_code failures in a single year before we must increase the length of the code.
* stretchParams
* mainSaltmainKDFSalt
* srpSalt