Authentication with username, email and phone using AWS Cognito
Tags: aws, authentication, amplify, cognito
Published: 2022-05-10 17:42:59

AWS Amplify comes with authentication services that can be installed via the Amplify CLI as described [here](https://docs.amplify.aws/cli/auth/overview/).

But the problem with the options that CLI gives is that that one can choose only anyone one of the 4:

1. username
2. email
3. phone
4. email or phone (this will set to the first logged in option -> either email or phone)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/66stbxuv9kqpg1nf7wa6.png)
 
Now as an app developer we would like to give the following options to the user. Ability to login via email or phone (username doesn't makes sense anymore) always.

If Cognito is setup directly without using Amplify then it is possible to do this setup using these options:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8jb8cpdtp0gnypfyejv.png)
 
Amplify does give you an option to import an existing Cognito User Pool but then the lifecycle, settings and utilities are not available. So you lose some to get some.

But there is a feature that AWS has come up with that can give us best of both.

This feature is the [override](https://docs.amplify.aws/cli/auth/override/) option. This will generate an override.ts file that will allow one to get into the details of the Cognito options.

So for our requirement of enabling user to login with email and also with phone we would need to add this to the override.ts. And the file would look like this:

```
import { AmplifyAuthCognitoStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyAuthCognitoStackTemplate) {
    resources.userPool.aliasAttributes = ['email', 'phone_number',];
}
```
With this added, Amplify will build a Cognito User Pool that will have the right sign-in options:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1jq58cdgv9rk8en5mix.png)

So the sign up would work like this:
```
const response = await Auth.signUp({
      username: v4(),
      password: password,
      attributes: {
        email: email, //Pass this
        phone_number: phone,// or this
      },
    })
```
One can add the other attribute e.g. phone like this:
```
async function addPhone(phone: string) {
  try {
    const user = await Auth.currentAuthenticatedUser()
    const responseUpdate = await Auth.updateUserAttributes(user, {
      phone_number: phone,
    })
    console.log({responseUpdate})
  } catch (error) {
    console.error('error adding phone:', error)
  }
}
```
and login using phone like this:
```
async function loginPhone(phone: string) {
  try {
    const authUser = await Auth.signIn(phone, password)
    console.log({authUser})
  } catch (error) {
    console.error('error logging in:', error)
  }
}
```

Refer to the repo [here](https://github.com/bnjr/prototypes/blob/5408a3002b971c8775fc017616d73e6a86ac9122/src/components/create-user.tsx).
The following functions are available to test out the Cognito User Pool setup:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfdlb7f8hn8ttwmrzq3y.png)