aws-amplify / amplify-ui

Amplify UI is a collection of accessible, themeable, performant React (and more!) components that can connect directly to the cloud.
https://ui.docs.amplify.aws
Apache License 2.0
872 stars 277 forks source link

Confirm email with link opens "enter confirmation code" view after signup #4912

Closed josefiniccms closed 8 months ago

josefiniccms commented 8 months ago

Before creating a new issue, please confirm:

On which framework/platform are you having an issue?

React

Which UI component?

Authenticator

How is your app built?

Next.js

What browsers are you seeing the problem on?

No response

Which region are you seeing the problem in?

No response

Please describe your bug.

We are currently using the Authenticator for one of our applications, after having had made our own components previously. We migrated to authenticator because it was the only thing that solved other critical bugs.

We use the same user pool for multiple applications and use verification via email. However, when we use Authenticator we are not able to override or disable the "Confirmation Code" view after signup. The link is correctly sent to the user, but having a text and input area where they are expecting to write a code is going to be very confusing for our users. We would want it to be possible to show a view prompting the users to verify by clicking the link in their email.

image

We have been unable to find anything in the documentation about how to do this, even though we've found many references to that verification link should be possible.

Any help on how to set this up or update to the package with easier customization of the confirmsignup screen, with more options to change what type of verification method is being used.

What's the expected behaviour?

We would want our users to be prompted to click the verification link in their email instead of enter their confirmation code.

Help us reproduce the bug!

dependencies: { "@aws-amplify/cli": "^12.1.1", "@aws-amplify/ui-react": "^6.1.1", "aws-amplify": "^6.0.7", "next": "^14.0.4", "react": "^18.2.0", }

aws-exports: { aws_project_region: "eu-central-1", aws_cognito_region: "eu-central-1", aws_user_pools_id: "eu-central-1_XXXXXXXXXXX", aws_user_pools_web_client_id: "XXXXXXXXXXXXXXXXXXXX", oauth: { domain: "XXXXXXX.com", scope: [ "phone", "email", "openid", "profile", "aws.cognito.signin.user.admin", ], redirectSignOut: "http://localhost:3000/", // localhost for development, our domain for production responseType: "code", }, aws_cognito_username_attributes: ["EMAIL"], aws_cognito_social_providers: ["GOOGLE", "APPLE"], aws_cognito_signup_attributes: ["GIVEN_NAME", "FAMILY_NAME", "EMAIL"], aws_cognito_mfa_configuration: "OFF", aws_cognito_mfa_types: [], aws_cognito_password_protection_settings: { passwordPolicyMinLength: 8, passwordPolicyCharacters: [ "REQUIRES_LOWERCASE", "REQUIRES_UPPERCASE", "REQUIRES_NUMBERS", ], },

Code Snippet

// Put your code below this line.
"use client";

import React, { useEffect } from "react";
import {
  Authenticator,
  Button,
  ColorMode,
  Heading,
  Image,
  Text,
  Theme,
  ThemeProvider,
  View,
  defaultDarkModeOverride,
  useAuthenticator,
  useTheme,
} from "@aws-amplify/ui-react";
import { Amplify } from "aws-amplify";
import awsmobile from "@/aws-exports";

Amplify.configure(awsmobile);

const components = {
  Header() {
    const { tokens } = useTheme();

    return (
      <View
        textAlign="center"
        padding={tokens.space.large}
        backgroundColor={"white"}
      >
        <Image alt="Our Logo" src="/logo.svg" />
      </View>
    );
  },

  Footer() {
    const { tokens } = useTheme();

    return (
      <View textAlign="center" padding={tokens.space.large}>
        <Text color={tokens.colors.neutral[80]}>
          Copyright &copy; 2022 Swimify &trade;
        </Text>
      </View>
    );
  },

  SignIn: {
    Header() {
      const { tokens } = useTheme();

      return (
        <Heading
          padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`}
          level={3}
        >
          Sign in to your account
        </Heading>
      );
    },
    Footer() {
      const { toForgotPassword } = useAuthenticator();

      return (
        <View textAlign="center">
          <Button
            fontWeight="normal"
            onClick={toForgotPassword}
            size="small"
            variation="link"
          >
            Reset Password
          </Button>
        </View>
      );
    },
  },
  SignUp: {
    Header() {
      const { tokens } = useTheme();

      return (
        <Heading
          padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`}
          level={3}
        >
          Create a new account
        </Heading>
      );
    },
    Footer() {
      const { toSignIn } = useAuthenticator();

      return (
        <View textAlign="center">
          <Button
            fontWeight="normal"
            onClick={toSignIn}
            size="small"
            variation="link"
          >
            Back to Sign In
          </Button>
        </View>
      );
    },
  },
  ForgotPassword: {
    Header() {
      const { tokens } = useTheme();
      return (
        <Heading
          padding={`${tokens.space.xl} 0 0 ${tokens.space.xl}`}
          level={3}
        >
          Enter Information:
        </Heading>
      );
    },
  }
};

const formFields = {
  signIn: {
    username: {
      placeholder: "Enter your email",
    },
  },
  signUp: {
    email: {
      order: 1,
      placeholder: "Enter your email",
      isRequired: true,
      label: "Email",
    },
    given_name: {
      label: "Given name",
      order: 2,
      isRequired: true,
      placeholder: "Enter your given name:",
    },
    family_name: {
      label: "Family name",
      placeholder: "Enter your family name:",

      order: 3,
      isRequired: true,
    },

    mobile: {
      label: "Mobile",
      order: 4,
      isRequired: true,
      placeholder: "+46701112233",
    },
    password: {
      label: "Password:",
      placeholder: "Enter your password:",
      isRequired: true,
      order: 5,
    },
    confirm_password: {
      label: "Confirm Password:",
      order: 6,
      isRequired: true,
      placeholder: "Confirm your password:",
    },
  },

  forgotPassword: {
    username: {
      placeholder: "Enter your email:",
    },
  },
  confirmResetPassword: {
    confirmation_code: {
      placeholder: "Enter your Confirmation Code:",
      label: "Confirmation Code",
      isRequired: false,
    },
    confirm_password: {
      placeholder: "Enter your Password Please:",
    },
  },
};

export function AuthenticationWrapper({
  children,
}: {
  children: React.ReactNode;
}) {

  return (
      <div className="w-full min-h-screen overflow-auto rounded-lg h-svh">
        <Authenticator
          components={components}
          formFields={formFields}
          className="w-full h-screen rounded-lg"
        >
          {children}
        </Authenticator>
      </div>
  );
}

Console log output

No response

Additional information and screenshots

No response

hbuchel commented 8 months ago

Hi @josefiniccms if I'm understanding correctly, you already have email link verification working and you don't want the confirmation code input form to show at all after a user does the initial sign up? You could get the authentication route from useAuthenticator and use that to show a custom view. Something like:

  const { route } = useAuthenticator(context => [context.route]);

  return route === 'confirmSignUp' ? <div>Custom sign up confirmation screen</div> :
    <Authenticator
        components={components}
        formFields={formFields}
        className="w-full h-screen rounded-lg"
      >
      {children}
    </Authenticator>

For useAuthenticator() to have the correct context, you would also need to wrap your application in <Authenticator.Provider></Authenticator.Provider> Details here

Would that work for your use case?

josefiniccms commented 8 months ago

Thank you! That seems to have worked wonderfully!

hbuchel commented 8 months ago

Great to hear! Closing this issue as that seems a suitable workaround; please feel free to re-open if you need further assistance.