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
887 stars 281 forks source link

AmplifyForgotPassword does not detect pre-populated value #299

Closed kjallbring closed 2 years ago

kjallbring commented 3 years ago

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Authentication

Amplify Categories

auth

Environment information

``` # Put output below this line System: OS: macOS Mojave 10.14.6 CPU: (8) x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz Memory: 4.11 GB / 16.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 16.6.2 - /usr/local/bin/node Yarn: 1.22.11 - /usr/local/bin/yarn npm: 7.20.3 - /usr/local/bin/npm Browsers: Brave Browser: 91.1.25.70 Safari: 14.1.2 npmPackages: @appbaseio/reactivesearch: ^3.21.0 => 3.21.0 @aws-amplify/ui-react: ^1.2.9 => 1.2.9 @craco/craco: ^6.1.2 => 6.1.2 @elastic/datemath: ^5.0.2 => 5.0.3 @elastic/eui: ^35.1.0 => 35.1.0 @testing-library/jest-dom: ^5.11.4 => 5.12.0 @testing-library/react: ^11.1.0 => 11.2.7 @testing-library/user-event: ^12.1.10 => 12.8.3 aws-amplify: ^4.2.3 => 4.2.3 craco-esbuild: ^0.3.2 => 0.3.2 moment: ^2.29.1 => 2.29.1 react: ^17.0.2 => 17.0.2 react-csv-downloader: ^2.7.0 => 2.7.0 react-dom: ^17.0.2 => 17.0.2 react-router-dom: ^5.2.0 => 5.2.0 react-scripts: ^4.0.3 => 4.0.3 web-vitals: ^1.0.1 => 1.1.2 npmGlobalPackages: @aws-amplify/cli: 4.51.1 aws-cdk: 1.8.0 npm: 7.20.3 ```

Describe the bug

I use the AmplifyForgotPassword component both for non authenticated users ("forgot" password) and for authenticated users ("reset" password). I recently upgraded to the latest version of Amplify, since the issue with duplicate formFields had recently been fixed.

Related PRs: https://github.com/aws-amplify/amplify-js/pull/8633/commits/b1a50cb287846ef185ffecfc2d28551b2d02a895 https://github.com/aws-amplify/amplify-js/pull/6211/commits/22051cb9dc9a4b4c0fd1b3fb5b66c72df5eb6f5f

When I pre-populate the username (email) field for authenticated users ("reset" password), it shows up in the form, but results in a 400 response from Cognito saying that the username was not specified.

One of the reasons that I want to pre-populate the username field is that if the users enters a non-existent email by mistake, Cognito returns a 400 response, but no error message is visible in the UI.

When I try to pre-populate the username (email) for unauthenticated users (using a hard-coded email address), it results in the field being empty. The pre-population is not honored. I don't really care about this scenario so much, since it doesn't make any sense. I included it as an FYI.

I have attached a number of screenshots from the app in the Additional information and screenshots section

Expected behavior

When I pre-populate the username (email) field for authenticated users ("reset" password), it should populate the form (it does), and result in a success response from Cognito, since the the username was specified.

Reproduction steps

When I use it for authenticated users ("reset" password), I pre-populate the username (email) field by assigning the email to the value prop. However, when the user clicks the SEND CODE button, nothing happens in the UI. I can see that the network call to Cognito returns a 400 response, indicating that the field was not populated.

If the field is blank initially (no pre-population), and the user clicks the SEND CODE button, a warning message appears: Please fill out this field

If I pre-populate, the UI seems to be aware of it. but an empty value is sent to Cognito.

Code Snippet

// Put your code below this line.

/* App.js code below */

import './App.css';
import React from 'react';
import {
    AmplifyForgotPassword,
    AmplifyAuthenticator, AmplifySignIn,
} from '@aws-amplify/ui-react';
import { AuthState, onAuthUIStateChange } from '@aws-amplify/ui-components';
import '@elastic/eui/dist/eui_theme_light.css'
import {Home} from './components/pages/Home'

export const App = () => {
    const [authState, setAuthState] = React.useState();
    const [user, setUser] = React.useState();

    React.useEffect(() => {
        return onAuthUIStateChange((nextAuthState, authData) => {
            setAuthState(nextAuthState);
            setUser(authData)
        });
    }, []);

    return authState === AuthState.SignedIn && user ? (
        <Home user={user}/>
    ) : (
        <AmplifyAuthenticator usernameAlias="email">
            <div className={"App"} slot={"sign-in"}>
                <AmplifySignIn
                    headerText="Login"
                    hideSignUp
                    usernameAlias="email"/>
            </div>
            <div className={"App"} slot={"forgot-password"}>
                <AmplifyForgotPassword
                    headerText="Reset your password"
                    usernameAlias="email"
                    formFields={[
                        {
                            type: "username",
                            label: "Email",
                            placeholder: "Enter your email address",
                            value: "henrik@test.com",
                            required: true,
                            inputProps: { 'data-test': 'forgot-password-username-input' }
                        }]}
                />
            </div>
        </AmplifyAuthenticator>
    );
}
export default App;

/* components/pages/Home.js code below */

import React from 'react';
import {AmplifySignout, AmplifyForgotPassword} from '@aws-amplify/ui-react';

const Home = ({user}) => {
    return (
        <div>
            <AmplifyForgotPassword
                headerText="Reset your password"
                usernameAlias="email"
                formFields={[
                    {
                        type: "username",
                        label: "Email",
                        placeholder: "Enter your email address",
                        value: user?.attributes?.email,
                        required: true,
                        inputProps: { 'data-test': 'forgot-password-username-input' },
                        // handleInputChange: AmplifyForgotPassword.handleFormFieldInputChange('username'),
                        // handleSend: (event) => {}
                    }]}
            />
            <AmplifySignout/>
        </div>
    );
}

export default Home;

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

Username is pre-populated. Error response from Cognito. No message in the UI.

Screen Shot 2021-08-13 at 8 49 32 PM

Warning message when the Username is NOT pre-populated

Screen Shot 2021-08-15 at 12 46 28 PM

Non-existent email gets a 400 response, but nothing is visible in the UI

Screen Shot 2021-08-13 at 8 53 44 PM

Second screen shown when valid email has been submitted

Screen Shot 2021-08-13 at 8 50 56 PM
advissor commented 3 years ago

The same thing happens with ConfirmSignup , when pre-populating the email

Use case :

@chrisbonifacio @kjallbring do you know about a possible workaround?

Like, is it possible to pass the "value" into the Auth state somehow? As it seems it is now aware of the value

When updating even a single string in "email" for example, it is bind'ed correctly and getting recognized.

Looks like this is same as https://github.com/aws-amplify/amplify-js/pull/6211

kjallbring commented 3 years ago

I think this code is invoked when passing in value.

But I suspect it does not trigger an event, so this code is NOT called.

And that causes userInput to be null/undefined here

ericclemmons commented 2 years ago

From what I'm reading, this should be addressed in our @next release via:

  1. Continuing support for pre-populating email between screens
  2. 🐛 Pre-populated values in the form should always be passed along
eddiekeller commented 2 years ago

Hi @kjallbring , this shouldn't be an issue any longer in our new version of the authenticator. Take a look at our docs here on how to get started with it - https://ui.docs.amplify.aws/ui/getting-started/installation?platform=react

Going to close this issue for now since this issue shouldn't be present in the new authenticator, but please open a new ticket if it still doesn't work for you.