Now let’s go ahead and implement the handleSubmit and handleConfirmationSubmit functions and connect it up with our AWS Cognito setup.

Change indicator Replace our handleSubmit and handleConfirmationSubmit functions in src/containers/Signup.tsx with the following.

async function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  setIsLoading(true);
  try {
    const newUser = await Auth.signUp({
      username: fields.email,
      password: fields.password,
    });
    setIsLoading(false);
    setNewUser(newUser);
  } catch (e) {
    onError(e);
    setIsLoading(false);
  }
}

async function handleConfirmationSubmit(
  event: React.FormEvent<HTMLFormElement>
) {
  event.preventDefault();
  setIsLoading(true);
  try {
    await Auth.confirmSignUp(fields.email, fields.confirmationCode);
    await Auth.signIn(fields.email, fields.password);
    userHasAuthenticated(true);
    nav("/");
  } catch (e) {
    onError(e);
    setIsLoading(false);
  }
}

Change indicator Also, include the Amplify Auth, onError, and ISignUpResult type in our header.

import { Auth } from "aws-amplify";
import { onError } from "../lib/errorLib";
import { ISignUpResult } from "amazon-cognito-identity-js";

Let’s use the right type for the new user object.

Change indicator Replace the const [newUser, setNewUser] line with.

const [newUser, setNewUser] = useState<null | ISignUpResult>(null);

Let’s install the npm package.

Change indicator Run the following in the packages/frontend/ directory.

$ pnpm add --save-dev amazon-cognito-identity-js

The flow here is pretty simple:

  1. In handleSubmit we make a call to signup a user using Auth.signUp(). This creates a new user object.

  2. Save that user object to the state using setNewUser.

  3. In handleConfirmationSubmit use the confirmation code to confirm the user with Auth.confirmSignUp().

  4. With the user now confirmed, Cognito now knows that we have a new user that can login to our app.

  5. Use the email and password to authenticate exactly the same way we did in the login page. By calling Auth.signIn().

  6. Update the App’s context using the userHasAuthenticated function.

  7. Finally, redirect to the homepage.

Now if you were to switch over to your browser and try signing up for a new account it should redirect you to the homepage after sign up successfully completes.

Redirect home after signup screenshot

A quick note on the signup flow here. If the user refreshes their page at the confirm step, they won’t be able to get back and confirm that account. It forces them to create a new account instead. We are keeping things intentionally simple but here are a couple of hints on how to fix it.

  1. Check for the UsernameExistsException in the handleSubmit function’s catch block.

  2. Use the Auth.resendSignUp() method to resend the code if the user has not been previously confirmed. Here is a link to the Amplify API docs.

  3. Confirm the code just as we did before.

Give this a try and post in the comments if you have any questions.

Now while developing you might run into cases where you need to manually confirm an unauthenticated user. You can do that with the AWS CLI using the following command.

aws cognito-idp admin-confirm-sign-up \
   --region <COGNITO_REGION> \
   --user-pool-id <USER_POOL_ID> \
   --username <YOUR_USER_EMAIL>

Just be sure to use your Cognito USER_POOL_ID and the email address you used to create the account.

Next up, we are going to create our first note.