Kgn-web
Kgn-web

Reputation: 7555

How to mark email as unique key in AWS Cognito

I am using AWS Cognito for User Management Below is how my configuration looks like

enter image description here

Now with this configuration, this makes email as mandatory & allow valid email address.

But I need to make email as a unique key.

How & where I can do the same in AWS Cognito?

Thanks!

Upvotes: 7

Views: 6250

Answers (2)

Kieron McKenna
Kieron McKenna

Reputation: 115

Even with setting email to unique and as a sign in alias, it will allow users to sign up with the same email.

Once they confirm that email with the new account, that account will then be the one that gets logged in with said email. However both will still be confirmed, which was not ideal for my situation.

I implemented a pre sign-up trigger (in Typescript) to throw an error if a user with that email already exists:

import { PreSignUpTriggerHandler } from "aws-lambda";
import { ListUsersCommand } from "@aws-sdk/client-cognito-identity-provider";
import { CognitoIdentityProviderClient } from "@aws-sdk/client-cognito-identity-provider";

const cognitoClient = new CognitoIdentityProviderClient({})

export const handler: PreSignUpTriggerHandler = async (event) => {
  const {
    userPoolId,
    request: { userAttributes }
  } = event;
  const email = userAttributes["email"];

  const comm = new ListUsersCommand({
    UserPoolId: userPoolId,
    Filter: `email = "${email}"`
  });

  const { Users } = await cognitoClient.send(comm);

  if (Users && Users.length > 0) {
    throw Error("Email already in use");
  }

  return event;
};

You also need to give the lambda adequate permissions for the cognito ListUsers command. As a bonus, heres that lambda implemented in the CDK, but this can be done with whatever you're using. I'm not sure how this would be done with the console unfortunately.

const preSignUpLambdaTrigger = new NodejsFunction(
    construct,
    "PreSignUpTrigger",
    {
      entry: "ENTRY TO HANDLER ABOVE",
      timeout: Duration.seconds(30)
    }
  );

const userPool = new cognito.UserPool(
    construct,
    `UserPool`,
    {
      standardAttributes: {
        email: {
          mutable: false,
          required: true
        }
      },
      signInAliases: {
        email: true,
        username: true
      },
      lambdaTriggers: {
        preSignUp: preSignUpLambdaTrigger
      }
    }
  );


  preSignUpLambdaTrigger.role?.attachInlinePolicy(
    new Policy(construct, "PreSignUpLambdaPolicy", {
      statements: [
        new PolicyStatement({
          actions: ["cognito-idp:ListUsers"],
          resources: [userPool.userPoolArn]
        })
      ]
    })
  );

Obviously customise to your needs, but this prevents an email from being signed up twice.

The inline policy is used to prevent a circular dependency between the lambda and the user pool, which caused me some headache.

Upvotes: 3

Sándor Bakos
Sándor Bakos

Reputation: 503

At the Email address or phone number section select the Allow email address, and now the email address going to be your unique key, at the required field the you still need to provide the phone email and name fields.

Of course in that case the username cannot be the phone number. But it is still required.

Upvotes: -1

Related Questions