aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.44k stars 2.13k forks source link

AmplifyAuthenticator - unable to reset password #6839

Closed cwinters8 closed 4 years ago

cwinters8 commented 4 years ago

Describe the bug Using AmplifyAuthenticator and a user created through the Cognito console. Following the example here to set up client side authentication. The user was in FORCE_CHANGE_PASSWORD state, and when attempting to sign in, the auth state changes to resettingpassword then immediately changes back to signin. I was able to get the user into CONFIRMED state, and then logging in worked as expected. However, after putting the user in RESET_REQUIRED state the issue returns.

I would like to work through this problem and use the provided UI components instead of using the Auth API directly but if I can't get past this it's a show stopper.

To Reproduce Steps to reproduce the behavior:

  1. Create a user via Cognito User Pools console
  2. Try to sign in using AmplifyAuthenticator
  3. Auth state changes to resettingpassword then immediately back to signin

The same behavior is seen when trying to do a 'forgot password' operation as well, except the state changes to forgotpassword then back to signin.

Expected behavior I expected after initial sign in to be prompted to reset the user's password.

Code Snippet Relevant code:

import React, {useState, useEffect} from 'react';
import {
  AmplifyAuthenticator,
  AmplifyGreetings,
  AmplifySignIn
} from '@aws-amplify/ui-react';
import {AuthState, onAuthUIStateChange} from '@aws-amplify/ui-components';
// Amplify is configured in the parent component

const AdminDashboard = props => {
  const [authState, setAuthState] = useState();
  const [user, setUser] = useState();

  useEffect(() => {
    return onAuthUIStateChange((nextAuthState, authData) => {
      setAuthState(nextAuthState);
      setUser(authData);
      console.log('user data:', authData);
      console.log('auth state:', nextAuthState);
    });
  }, []);

  // <Authenticated /> component omitted for brevity

  const Authenticator = () => {
    return (
      <div className='container'>
        <div className='header' />
        <div className='body'>
          <AmplifyAuthenticator>
            <AmplifySignIn
              slot='sign-in'
              usernameAlias='email'
              hideSignUp={true}
              className='authenticator'
            />
          </AmplifyAuthenticator>
        </div>
      </div>
    )
  }

  return authState === AuthState.SignedIn && user ? <Authenticated /> : <Authenticator />
}

export default AdminDashboard;

Screenshots image

What is Configured? If applicable, please provide what is configured for Amplify CLI:

const awsmobile = { "aws_project_region": "us-west-2", "aws_appsync_graphqlEndpoint": "http://10.0.0.244:20002/graphql", "aws_appsync_region": "us-west-2", "aws_appsync_authenticationType": "API_KEY", "aws_appsync_apiKey": "da2-fakeApiId123456", "aws_cognito_identity_pool_id": "us-west-2:c1b76b35-2043-477c-ac7d-8b9f1072b92f", "aws_cognito_region": "us-west-2", "aws_user_pools_id": "us-west-2_mMLC50fsw", "aws_user_pools_web_client_id": "6njc6kkd4nv3s6uld81agvp67d", "oauth": {} };

export default awsmobile;


* If applicable, provide more configuration data, for example for Amazon Cognito, run `aws cognito-idp describe-user-pool --user-pool-id us-west-2_xxxxxx` (Be sure to remove any sensitive data)
 ```json
{
    "UserPool": {
        "Id": "us-west-2_mMLC50fsw",
        "Name": "lgbtqhealthdirectory9b89d791_userpool_9b89d791-dev",
        "Policies": {
            "PasswordPolicy": {
                "MinimumLength": 8,
                "RequireUppercase": false,
                "RequireLowercase": false,
                "RequireNumbers": false,
                "RequireSymbols": false,
                "TemporaryPasswordValidityDays": 7
            }
        },
        "LambdaConfig": {
            "CustomMessage": "arn:aws:lambda:us-west-2:920670260300:function:lgbtqhealthdirectory9b89d791CustomMessage-dev",
            "PostConfirmation": "arn:aws:lambda:us-west-2:920670260300:function:lgbtqhealthdirectory9b89d791PostConfirmation-dev"
        },
        "LastModifiedDate": "2020-09-20T16:06:30.461000-07:00",
        "CreationDate": "2020-09-20T16:06:30.461000-07:00",
        "SchemaAttributes": [
            {
                "Name": "sub",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": false,
                "Required": true,
                "StringAttributeConstraints": {
                    "MinLength": "1",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "given_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "family_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "middle_name",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "nickname",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "preferred_username",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "profile",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "picture",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "website",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "email",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": true,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "email_verified",
                "AttributeDataType": "Boolean",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false
            },
            {
                "Name": "gender",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "birthdate",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "10",
                    "MaxLength": "10"
                }
            },
            {
                "Name": "zoneinfo",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "locale",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "phone_number",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "phone_number_verified",
                "AttributeDataType": "Boolean",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false
            },
            {
                "Name": "address",
                "AttributeDataType": "String",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "StringAttributeConstraints": {
                    "MinLength": "0",
                    "MaxLength": "2048"
                }
            },
            {
                "Name": "updated_at",
                "AttributeDataType": "Number",
                "DeveloperOnlyAttribute": false,
                "Mutable": true,
                "Required": false,
                "NumberAttributeConstraints": {
                    "MinValue": "0"
                }
            }
        ],
        "AutoVerifiedAttributes": [
            "email"
        ],
        "UsernameAttributes": [
            "email"
        ],
        "SmsVerificationMessage": "Your verification code is {####}",
        "EmailVerificationMessage": "Your verification code is {####}",
        "EmailVerificationSubject": "Your verification code",
        "VerificationMessageTemplate": {
            "SmsMessage": "Your verification code is {####}",
            "EmailMessage": "Your verification code is {####}",
            "EmailSubject": "Your verification code",
            "DefaultEmailOption": "CONFIRM_WITH_CODE"
        },
        "MfaConfiguration": "OFF",
        "EstimatedNumberOfUsers": 2,
        "EmailConfiguration": {
            "EmailSendingAccount": "COGNITO_DEFAULT"
        },
        "SmsConfiguration": {
            "SnsCallerArn": "arn:aws:iam::920670260300:role/sns9b89d791124630-dev",
            "ExternalId": "lgbtqh9b89d791_role_external_id"
        },
        "UserPoolTags": {},
        "AdminCreateUserConfig": {
            "AllowAdminCreateUserOnly": false,
            "UnusedAccountValidityDays": 7
        },
        "Arn": "arn:aws:cognito-idp:us-west-2:920670260300:userpool/us-west-2_mMLC50fsw"
    }
}
Environment ``` $ npx envinfo --system --binaries --browsers --npmPackages --npmGlobalPackages System: OS: macOS Mojave 10.14.6 CPU: (4) x64 Intel(R) Core(TM) i5-5350U CPU @ 1.80GHz Memory: 105.62 MB / 8.00 GB Shell: 3.2.57 - /bin/bash Binaries: Node: 14.10.1 - /usr/local/bin/node Yarn: 1.22.5 - /usr/local/bin/yarn npm: 6.14.8 - /usr/local/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Browsers: Chrome: 85.0.4183.102 Firefox: 80.0.1 Firefox Developer Edition: 77.0 Safari: 14.0 npmPackages: @apollo/client: ^3.2.0 => 3.2.0 @aws-amplify/ui-components: ^0.8.4 => 0.8.4 @aws-amplify/ui-react: ^0.2.21 => 0.2.21 @react-hook/window-size: ^3.0.7 => 3.0.7 @reduxjs/toolkit: ^1.4.0 => 1.4.0 @testing-library/jest-dom: ^4.2.4 => 4.2.4 @testing-library/react: ^9.5.0 => 9.5.0 @testing-library/user-event: ^7.2.1 => 7.2.1 aws-amplify: ^3.2.0 => 3.2.0 aws-appsync-auth-link: ^2.0.3 => 2.0.3 graphql: ^15.3.0 => 15.3.0 react: ^16.13.1 => 16.13.1 react-beautiful-dnd: ^13.0.0 => 13.0.0 react-dom: ^16.13.1 => 16.13.1 react-icons: ^3.11.0 => 3.11.0 react-loader-spinner: ^3.1.14 => 3.1.14 react-modal: ^3.11.2 => 3.11.2 react-redux: ^7.2.1 => 7.2.1 react-router-dom: ^5.2.0 => 5.2.0 react-scripts: 3.4.3 => 3.4.3 react-select: ^3.1.0 => 3.1.0 npmGlobalPackages: @aws-amplify/cli: 4.29.2 eslint-plugin-react: 7.14.3 eslint: 5.16.0 express: 4.17.1 jest: 26.0.1 jshint: 2.10.2 mongo-hacker: 0.0.16 netlify-lambda: 1.6.3 nodemon: 1.19.2 npm: 6.14.8 npx: 10.2.0 reload: 2.4.0 run-p: 0.0.0 serve: 10.1.2 taskbook: 0.1.1 typescript: 3.6.3 ```
cwinters8 commented 4 years ago

I was able to find a workaround for the original problem. I pass a function to the handleAuthStateChange property, and set the auth state and user data in that function. So the issue seems to be with onAuthUIStateChange.

  const handleAuthChange = (authState, userData) => {
    console.log(authState, userData);
    setAuthState(authState);
    setUser(userData);
  }

  const Authenticator = () => {
    return (
      <div className='container'>
        <div className='header' />
        <div className='body'>
          <AmplifyAuthenticator handleAuthStateChange={handleAuthChange}>
            <AmplifySignIn
              slot='sign-in'
              usernameAlias='email'
              hideSignUp={true}
              className='authenticator'
            />
          </AmplifyAuthenticator>
        </div>
      </div>
    );
  }

I found another problem when I try to do a forgot password - I get a 400 error when the client is apparently trying to make a POST request to https://cognito-idp.us-west-2.amazonaws.com/ image

manueliglesias commented 4 years ago

Hi @cwinters8

On your original code, it will work fine if you hoist your <Authenticator /> and <Authenticated /> components like so:


import React, {useState, useEffect} from 'react';
import {
  AmplifyAuthenticator,
  AmplifySignIn,
  AmplifySignOut
} from '@aws-amplify/ui-react';
import {AuthState, onAuthUIStateChange} from '@aws-amplify/ui-components';

// Amplify is configured in the parent component
import Amplify from "aws-amplify";
import awsConfig from "./aws-exports";
Amplify.configure(awsConfig);

const Authenticator = () => {
  return (
    <div className='container'>
      <div className='header' />
      <div className='body'>
        <AmplifyAuthenticator>
          <AmplifySignIn
            slot='sign-in'
            usernameAlias='email'
            hideSignUp={true}
            className='authenticator'
          />
        </AmplifyAuthenticator>
      </div>
    </div>
  )
};

const Authenticated = ({user} : any) => (<>Hi {user.username}<AmplifySignOut /></>)

const AdminDashboard = (props: any) => {
  const [authState, setAuthState] = useState<AuthState>();
  const [user, setUser] = useState<any>();

  useEffect(() => {
    return onAuthUIStateChange((nextAuthState, authData) => {
      setAuthState(nextAuthState);
      setUser(authData);
      console.log('user data:', authData);
      console.log('auth state:', nextAuthState);
    });
  }, []);

  // <Authenticated /> component omitted for brevity

  return authState === AuthState.SignedIn && user ? <Authenticated user={user} /> : <Authenticator />
}

export default AdminDashboard;
manueliglesias commented 4 years ago

Hoisting the components seem to take care of the "Reset Password" issue you were facing.

I'll be closing this issue, please feel free to create a new one if you run into a different problem.

github-actions[bot] commented 3 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.