This extension allows for recovery credentials to be registered with an RP,
which can be used for account recovery in the case of a lost/destroyed main
authenticator. This is done by associating one or more backup authenticators
with the main authenticator, the latter of which is then able to provide
additional credentials for account recovery to the RP without involving the
backup authenticators. The mechanism of setting this up is outside of the scope
of this extension, however a state counter is defined as follows:
Let state be initialized to 0. Performing a device reset re-initializes
state to 0. When the set of registered backup authenticators for the device
changes (eg. on adding/removing a backup authenticator, including adding the
first backup authenticator) state is incremented by one.
The state counter is stored by the main authenticator, and allows the RP to
automatically detect when the set of registered recovery credentials needs to be
updated.
NOTE: The choice to make registration of recovery credentials explicit is deliberate, in an attempt to ensure that the user deliberately intends to do so and understands the implications.
recovery
Registration and Authentication
partial dictionary AuthenticationExtensionsClientInputs {
RecoveryExtensionInput recovery;
}
dictionary RecoveryExtensionInput {
required RecoveryExtensionAction action;
sequence<PublicKeyCredentialDescriptor> allowCredentials;
}
enum RecoveryExtensionAction {
"state",
"generate",
"recover"
}
The values of action have the following meanings. X indicates that the value
is applicable for the given WebAuthn operation:
| Value | create() | get() | Description |
|---|---|---|---|
| state | X | X | Get the state counter value from the main authenticator. |
| generate | X | Regenerate recovery credentials from the main authenticator. | |
| recover | X | Get a recovery signature from a backup authenticator, to replace the main credential with a new one. |
None required, except creating the authenticator extension input from the client extension input.
If the client implements support for this extension, then when action is
"generate", the client SHOULD notify the user of the number of recovery
credentials in the response.
None.
The client extension input encoded as a CBOR map.
If action is
-
"state",set the extension output to the CBOR encoding of
{"action": "state", "state": <state counter>}. -
"generate",generate one recovery credential for each associated backup authenticator, formatting these as a CBOR array of attested credential data byte arrays. Set the extension output to the CBOR encoding of
{"action": "generate", "state": <state counter>, "creds": <list of recovery credentials>}. -
"recover",locate a usable recovery credential from the credential IDs in
allowCredentialsin the extension input.-
If no usable credential is found, do not include the extension in the output.
-
If a usable credential is found,
-
Let
credbe the found credential. -
Let
authenticatorDataWithoutExtensionsbe the authenticator data that will be returned from this registration operation, but without theextensionspart. TheEDflag inauthenticatorDataWithoutExtensionsMUST be set even thoughauthenticatorDataWithoutExtensionsdoes not include extension data. -
Let
sigbe a signature overauthenticatorDataWithoutExtensions || clientDataHashusingcred. -
Set the extension output to the CBOR encoding of
{"action": "recover", "credId": <credential ID of cred>, "sig": <sig>, "state": <state counter>}.
-
-
A CBOR map with contents as defined above.
dictionary RecoveryExtensionOutput {
required RecoveryExtensionAction action;
required int state;
sequence<ArrayBuffer> creds;
ArrayBuffer credId;
ArrayBuffer sig;
}
-
The RP MUST be very explicit in notifying the user when recovery credentials are registered, and how many, to avoid any credentials being registed without the user's knowledge. If possible, the client SHOULD also display the number of backup authenticators associated with the main authenticator.
-
The RP SHOULD clearly display information about registered recovery credentials, just as it does with standard credentials.
-
The same security considerations apply to recovery credentials as to standard credentials.
-
Although recovery credentials are issued by the main authenticator, they can only ever be used by the backup authenticator.
-
Recovery credentials are scoped to a specific RP ID, and the RP SHOULD also associate them with a specific main credential.
-
Recovery credentials can only be used in registration ceremonies where the recovery extension is present, with
action == "recover". -
A main authenticator should ensure that the recovery credentials it issues on behalf of a backup authenticator are authentic.
An RP supporting this extension SHOULD include the extension the action = "state" value whenever performing standard registration or authentication
ceremony. There are two cases where the response indicates that the RP should
initiate recovery credential registration (action "generate"), which are:
- Upon successful
create(), ifstate> 0. - Upon successful
get(), ifstate>old_state, whereold_stateis the previous value forstatethat the RP has seen for the used credential.
To initiate recovery credential registration, the RP performs a get()
operation with action = "generate". Upon a successful response, the returned
list of recovery credentials is stored, associated with the main credential.
Any prior recovery credentials for that main credential are replaced.
If the user initiates device recovery, the RP performs the following procedure:
-
Ask the user which credential to recover. Let
mainCredbe the chosen credential. -
Let
allowCredentialsbe a list of the credential descriptors of the recovery credentials associated withmainCred. IfallowCredentialsis empty, abort this procedure with an error. -
Initiate a
create()operation with the extension input:"recovery": { "action": "recover", "allowCredentials": <allowCredentials as computed above> } -
Wait for the response from the client. If the operation fails, abort this procedure with an error.
-
Let
publicKeybe the public key for the recovery credential identified by the credential IDcredIdin the extension output. -
Let
authenticatorDataWithoutExtensionsbe the authenticator data in the PublicKeyCredential response, but without the extensions part. TheEDflag inauthenticatorDataWithoutExtensionsMUST be set even thoughauthenticatorDataWithoutExtensionsdoes not include the extension outputs. -
Using
publicKey, verify thatsigin the extension output is a valid signature overauthenticatorDataWithoutExtensions || clientDataHash. -
Finish the registration ceremony as usual. This means a new credential has now been registered using the backup authenticator.
-
Revoke
mainCredand all recovery credentials associated with it. -
If
statein the extension output is greater than 0, the RP SHOULD initiate recovery credential registration (action = "generate") for the newly registered credential.
As an alternative to proceeding to register a new credential for the backup authenticato, the RP MAY choose to not replace the lost credential with the new one, and instead disable 2FA or provide some other means for the user to access their account. In either case, the associated main credential SHOULD be revoked and no longer usable.