> ## Documentation Index
> Fetch the complete documentation index at: https://docs.authsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing authenticators when integrating Authsignal with Amazon Cognito

> Learn how to let users enroll and manage different authenticators when integrating Authsignal with Amazon Cognito.

In the [previous guide](/integrations/aws-cognito/getting-started) we demonstrated how to enroll the user's first authenticator as part of a combined sign-up/sign-in flow.

This guide will cover the implementation steps for letting users enroll and manage multiple different authentication methods when integrating Authsignal with Amazon Cognito.

## Github example code

<CardGroup cols="2">
  <Card icon="github" horizontal title="Cognito lambdas" href="https://github.com/authsignal/cognito-lambdas" />

  <Card icon="github" horizontal title="React Native mobile app" href="https://github.com/authsignal/cognito-mobile-sms-example" />
</CardGroup>

## Enrolling more authenticators

Once the user has enrolled their first authentication method and has signed in, we want to give them the option to enroll more authentication methods.

As an example, we'll demonstrate how to let users enroll **email OTP** as a second authentication method - but the implementation approach will be similar for all authentications methods.

<Tip>
  While authentication methods can be enrolled in any sequence, it's recommended to only let users
  enroll [passkeys](/integrations/aws-cognito/passkeys) after they've first enrolled a method like
  email or SMS OTP, so users always have a fallback option in cases where their passkey \[isn't
  available.
</Tip>

### Lambda integration

<Tabs>
  <Tab title="Custom UI">
    To authorize binding the new authentication method to the user, we will create an **authenticated API endpoint** which our app can call once they've signed in.

    This endpoint will use a [JWT Authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html) to authenticate using the Cognito access token.
    It will return a short-lived **Authsignal token** which we'll use in the following step.

    ```ts theme={null}
    export const handler = async (event: APIGatewayProxyEventV2WithJWTAuthorizer) => {
      const { token: authsignalToken } = await authsignal.track({
        userId: event.requestContext.authorizer.jwt.claims.sub,
        action: "addAuthenticator",
        attributes: {
          scope: "add:authenticators",
        },
      });

      return {
        authsignalToken,
      };
    };
    ```
  </Tab>

  <Tab title="Pre-built UI">
    To authorize binding the new authentication method to the user, we will create an **authenticated API endpoint** which our app can call once they've signed in.

    This endpoint will use a [JWT Authorizer](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html) to authenticate using the Cognito access token.
    It will return a short-lived **Authsignal pre-built UI URL** which we'll use in the following step.

    ```ts theme={null}
    export const handler = async (event: APIGatewayProxyEventV2WithJWTAuthorizer) => {
      const { url: prebuiltUiUrl } = await authsignal.track({
        action: "manageAuthenticators",
        userId: event.requestContext.authorizer.jwt.claims.sub,
        attributes: {
          // Only required for redirect mode
          redirectUrl: "https://yourapp.com/callback",
        },
      });

      return {
        prebuiltUiUrl,
      };
    };
    ```
  </Tab>
</Tabs>

### App integration

<Tabs>
  <Tab title="Custom UI">
    1. Call our endpoint to obtain the Authsignal token.

    ```ts theme={null}
    // Replace with your API endpoint URL
    const apiEndpointUrl = "https://abcd1234.execute-api.us-west-1.amazonaws.com/authenticators";

    const authsignalToken = await fetch(apiEndpointUrl, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${cognitoAccessToken}`,
      },
    })
      .then((res) => res.json())
      .then((json) => json.authsignalToken);
    ```

    2. Enroll the email OTP authenticator using a Client SDK.

    <CodeGroup>
      ```ts Web theme={null}
      // 1. Set the token obtained from your API endpoint
      authsignal.setToken(token);

      // 2. Send the user an OTP code via email
      await authsignal.email.enroll({ email: "user@example.com" });

      // 3. Verify the code inputted by the user to complete the enrollment
      const response = await authsignal.email.verify({ code: "123456" });
      ```

      ```swift iOS theme={null}
      // 1. Set the token obtained from your API endpoint
      authsignal.setToken(token)

      // 2. Send the user an OTP code via email
      await authsignal.email.enroll(email: "user@example.com")

      // 3. Verify the code inputted by the user to complete the enrollment
      let response = await authsignal.email.verify(code: "123456")
      ```

      ```kotlin Android theme={null}
      // 1. Set the token obtained from your API endpoint
      authsignal.setToken(token)

      // 2. Send the user an OTP code via email
      authsignal.email.enroll(email = "user@example.com").get()

      // 3. Verify the code inputted by the user to complete the enrollment
      val response = authsignal.email.verify(code = "123456").get()
      ```

      ```ts React Native theme={null}
      // 1. Set the token obtained from your API endpoint
      await authsignal.setToken(token);

      // 2. Send the user an OTP code via email
      await authsignal.email.enroll({ email: "user@example.com" });

      // 3. Verify the code inputted by the user to complete the enrollment
      const response = await authsignal.email.verify({ code: "123456" });
      ```

      ```dart Flutter theme={null}
      // 1. Set the token obtained from your API endpoint
      await authsignal.setToken(token);

      // 2. Send the user an OTP code via email
      await authsignal.email.enroll(email: "user@example.com");

      // 3. Verify the code inputted by the user to complete the enrollment
      const response = await authsignal.email.verify(code: "123456");
      ```
    </CodeGroup>

    For more information on how to use other authentication methods refer to our [Web SDK](/sdks/client/web/setup) and [Mobile SDK](/sdks/client/mobile/setup) documentation.
  </Tab>

  <Tab title="Pre-built UI">
    1. Call our endpoint to obtain the Authsignal pre-built UI URL.

    ```ts theme={null}
    // Replace with your API endpoint URL
    const apiEndpointUrl = "https://abcd1234.execute-api.us-west-1.amazonaws.com/authenticators";

    const prebuiltUiUrl = await fetch(apiEndpointUrl, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${cognitoAccessToken}`,
      },
    })
      .then((res) => res.json())
      .then((json) => json.prebuiltUiUrl);
    ```

    2. Launch the pre-built UI URL (optionally using the Authsignal Web SDK).

    ```ts theme={null}
    authsignal.launch(prebuiltUiUrl, { mode: "redirect" });
    ```

    For more information refer to our [documentation on launching the pre-built UI](/implementation-options/prebuilt-ui/presentation-modes).
  </Tab>
</Tabs>

## Removing authenticators

<Tabs>
  <Tab title="Custom UI">
    The Authsignal Server SDK can be used within your authenticated API endpoint to get the user's currently enrolled authenticators and to remove an authenticator by its ID.

    The example code below demonstrates how to remove the user's email OTP authenticator by using the Authsignal Server SDK inside an API endpoint which is authenticated using a JWT authorizer.

    ```ts theme={null}
    export const handler = async (event: APIGatewayProxyEventV2WithJWTAuthorizer) => {
      const userId = event.requestContext.authorizer.jwt.claims.sub;

      // Get the user's currently enrolled authenticators
      const authenticators = await authsignal.getAuthenticators({ userId });

      // Find the email OTP authenticator ID
      const emailOtpAuthenticator = authenticators.find((a) => a.verificationMethod === "EMAIL_OTP");

      // Remove the email OTP authenticator
      await authsignal.deleteAuthenticator({
        userId,
        userAuthenticatorId: emailOtpAuthenticator.userAuthenticatorId,
      });
    };
    ```

    For more information refer to our [Server SDK documentation](/sdks/server/overview).
  </Tab>

  <Tab title="Pre-built UI">
    The Authsignal pre-built UI also supports removing authenticators when launched in settings mode.

    For more information refer to our [pre-built UI documentation](/implementation-options/prebuilt-ui/overview).
  </Tab>
</Tabs>

## Next steps

* [Passkeys](/integrations/aws-cognito/passkeys)
* [Adaptive MFA](/integrations/aws-cognito/rules)
