Skip to main content

Account Recovery Guide

Overview

Users regularly lose or upgrade their devices, which can be a problem in the FIDO space as the credential is tied to the device. We strongly recommend encouraging your users to register multiple devices, though there may be cases where this cannot happen.

Account recovery is a sensitive operation, so you want to ensure only your legitimate end user is able to regain access to their account. We recommend that you validate the end user’s identity before allowing them to regain access. Depending on your application type, there would be varying levels of security required for this. You can use the flow outlined in this document to generate a magic link, which would allow the end user to regain access if they have access to their email. However, for more high risk account types (e.g. banking), you would want to have a more rigorous process to verify their identity. This may be something like a document verification and selfie flow, or the same procedure originally used to create the account.

The account recovery flow requires a backend API call, therefore it is recommended to leverage the LoginID server SDK. However, the LoginID APIs can be called directly if required.

At a high level, this flow consists of two main components: generation of a pre-authorized code and using that code to add a new authenticator to the existing account. Afterwards, the user can go in and revoke any credentials which are no longer valid if desired.

Prerequisites

  • Create an application on LoginID Dashboard
  • Download Client SDK
  • Download Server SDK (optional)

With Server SDK

Step 1: Get user_id

The code generation functionality requires the user_id rather than the username. In the case where you have not stored the user_id, you can call the below SDK method to get the user_id.

Server SDK: .getUserID(username)

The response is the user’s profile information (including the user_id) for the provided username.

Step 2: Generate Code

Once you have the user_id, you must generate a code. This code is what allows the customer to regain access to their account, as it lets them register a new credential. To understand which code_type is best for your use case, please see our guide on choosing a code type.

Server SDK: .generateCode(purpose, code_type, username, authorized)

note

For the Account Recovery flow, the authorized parameter must be set to true.

This returns a code of the specified type as well as its expiry time.

Step 3: Notify User

LoginID does not send the code to the user, as we understand it is important for you to maintain direct contact with your clients. Depending on your desired user experience, you can use the code returned in Step 2 in a variety of ways. For account recovery, this is frequently done over the phone by a customer service representative, or through an email.

Step 4: Add New Credential

The pre-authorized code can now be used to add a new device as an authenticator, enabling the user to regain access to their account. The user has the option to specify a credential name for their new device at this point. If no credential name is specified, a default name will be populated based on the user agent.

Client SDK: .addFido2Credential(user_id, code, code_type, credential_name)

This returns a jwt containing the id_token. At this point, the user is now authenticated on the new device and that device has been added as an authenticator.


Calling APIs Directly

Step 1: Retrieve user_id

The code generation functionality requires the user_id rather than the username. In the case where you have not stored the user_id, you can call the below endpoint to get the user_id.

The required scope of the service token for this request is users.retrieve

Request:

POST /api/native/manage/users/retrieve

Header:

Authorization: Bearer {authorization_token}

Body:

{
"username": "string"
}

The response is the user’s profile information (including the user_id) for the provided username.

Step 2: Generate Code

Once you have the user_id, you must generate a code. This code is what ties the new device and existing device together. To understand which code_type is best for your use case, please see our guide on choosing a code type.

note

For the Account Recovery flow, the authorized parameter must be set to true.

The scope of the authorization token is codes.generate

Request:

POST /api/native/codes/{type}/generate

Header:

Authorization: Bearer {authorization_token}

Body:

{
  "client_id": <dashboard-generated client_id>,
  "user_id": <user_id_to_be_authenticated>,
  "purpose": "add_credential",
  "authorize": <bool>
}

Where:

  • client_id: generated on the LoginID dashboard
  • user_id: ID of an already registered user. In this case it would be the user_id of the person trying to temporarily authenticate
  • purpose: the reason for generating a code. In this case it would always be add_authenticator
  • authorize: Whether the request to generate the code is pre-authorized. In this case it would be true to allow the user to add their new device

Response:

{
  "code": <string>,
  "expires_at": <ISO8061 timestamp>
  "is_authorized": false
}

Step 3: Notify User

LoginID does not send the code to the user, as we understand it is important for you to maintain direct contact with your clients. Depending on your desired user experience, you can use the code returned in Step 2 in a variety of ways.

Step 4: Initiate Addition of New Authenticator

The authorized code can now be used to add the new device as an authenticator. The user has the option to specify a credential name for their new device at this point. If no credential name is specified, a default name will be populated based on the user agent.

The scope of the authorization token is credentials.add

Request:

POST /credentials/fido2/init/code

Authorization:

Authorization: Bearer {authorization_token}

Body:

{
  "client_id": "string",
  "user_id": "string",
  "authentication_code": {
    "code": <code from Step 1 as string>,
    "type": <type from Step 1 as string>
  }
}
note

This call should be made by the front end, but requires an authorization token.

The response will be the standard registration initialization payload (i.e. same as /register/init).

Step 5: Credential Addition Completion

Once the credential addition flow has been initialized, the user has the ability to enter a custom device name. After entering the device name, this would be submitted on the /credentials/fido2/complete call. The payload structure follows the same pattern as the normal registration flow.

After a successful credential addition, similar to the registration flow, a JWT will be returned indicating the successful registration of the new authenticator.