question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AmplifySignUp doesn't detect values of text fields after initial submission failure

See original GitHub issue

Before opening, please confirm:

JavaScript Framework

React

Amplify APIs

Not applicable

Amplify Categories

Not applicable

Environment information

# Put output below this line

System:
    OS: macOS 11.5.1
    CPU: (8) x64 Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
    Memory: 944.93 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.15.5 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.14 - /usr/local/bin/npm
  npmPackages:
    @aws-amplify/ui-react: ^1.2.8 => 1.2.8 
    @popperjs/core: ^2.9.2 => 2.9.3 
    @testing-library/jest-dom: ^5.11.4 => 5.14.1 
    @testing-library/react: ^11.1.0 => 11.2.7 
    @testing-library/user-event: ^12.1.10 => 12.8.3 
    autoprefixer: ^9.8.6 => 9.8.6 
    aws-amplify: ^4.2.2 => 4.2.2 
    bootstrap: ^5.0.2 => 5.1.0 
    bootstrap-icons: ^1.5.0 => 1.5.0 
    husky: ^7.0.0 => 7.0.1 
    lerna: ^4.0.0 => 4.0.0 
    node-sass: ^6.0.1 => 6.0.1 
    prettier: ^2.3.2 => 2.3.2 
    pretty-quick: ^3.1.1 => 3.1.1 
    react: ^17.0.2 => 17.0.2 
    react-dom: ^17.0.2 => 17.0.2 
    react-scripts: 4.0.3 => 4.0.3 
    redux-logger: ^3.0.6 => 3.0.6 
    workbox-background-sync: ^5.1.3 => 5.1.4 
    workbox-broadcast-update: ^5.1.3 => 5.1.4 
    workbox-cacheable-response: ^5.1.3 => 5.1.4 
    workbox-core: ^5.1.3 => 5.1.4 
    workbox-expiration: ^5.1.3 => 5.1.4 
    workbox-google-analytics: ^5.1.3 => 5.1.4 
    workbox-navigation-preload: ^5.1.3 => 5.1.4 
    workbox-precaching: ^5.1.3 => 5.1.4 
    workbox-range-requests: ^5.1.3 => 5.1.4 
    workbox-routing: ^5.1.3 => 5.1.4 
    workbox-strategies: ^5.1.3 => 5.1.4 
    workbox-streams: ^5.1.3 => 5.1.4 

Describe the bug

When using a custom AmplifyAuthenticator and trying to sign up, if registration fails because only one of the fields was wrong, the user updates the field in the form to fix it. Because the user is only updating one field it always throws Password cannot be empty or Email cannot be empty. The only way to overcome that is to modify both email and password fields before submitting. If the user only modifies one field the form always fails.

Expected behavior

When a user fixes the form and clicks submit again the form should call the Cognito API to create the user.

Reproduction steps

  1. Go to Sign Up page
  2. Fill out sign up form with incorrect data (email already been used or incorrect password policy)
  3. Submit and wait for failure
  4. Fix only one of the text inputs (email or password)
  5. Submit
  6. If email was updated it says password is empty (it is not). If password is updated it says email is empty (it is not)
  7. Update both fields and submit
  8. Submission now works

Code Snippet

Wrapping App.jsx with custom withAuthenticator

Code for withAuthenticator.jsx

import { useEffect, useState } from 'react'
import { Auth, appendToCognitoUserAgent } from '@aws-amplify/auth'
import { Hub, Logger } from '@aws-amplify/core'
import {
  AmplifyContainer,
  AmplifyAuthenticator,
  AmplifyAuthContainer,
  AmplifySignIn,
  AmplifySignUp,
  AmplifyConfirmSignIn,
  AmplifyConfirmSignUp,
  AmplifyForgotPassword,
  AmplifyRequireNewPassword,
  AmplifyTotpSetup,
  AmplifyVerifyContact
} from '@aws-amplify/ui-react'
import {
  UI_AUTH_CHANNEL,
  TOAST_AUTH_ERROR_EVENT,
  AuthState,
  onAuthUIStateChange
} from '@aws-amplify/ui-components'

import Toast from '../Toast'

const logger = new Logger('withAuthenticator')

function applyStylesToShashowComponent(querySelector) {
  const style = document.createElement('style')
  style.innerHTML = '.button { border-radius: 0.25rem!important; }'
  const host = document.querySelector(querySelector)
  host.shadowRoot.appendChild(style)
}

function withAuthenticator(Component, authenticatorProps) {
  const AppWithAuthenticator = props => {
    const [errorMessage, setErrorMessage] = useState(null)
    const [signedIn, setSignedIn] = useState(false)

    useEffect(() => {
      Hub.listen(UI_AUTH_CHANNEL, handleHubEvents)
      return () => {
        Hub.remove(UI_AUTH_CHANNEL, handleHubEvents)
      }
    })

    useEffect(() => {
      appendToCognitoUserAgent('withAuthenticator')
      const shadowComponents = [
        'amplify-sign-in',
        'amplify-sign-up',
        'amplify-confirm-sign-in',
        'amplify-confirm-sign-up',
        'amplify-forgot-password',
        'amplify-require-new-password',
        'amplify-totp-setup',
        'amplify-verify-contact'
      ]

      shadowComponents.forEach(applyStylesToShashowComponent)
      return checkUser()
    }, [])

    function checkUser() {
      setUser()

      return onAuthUIStateChange(authState => {
        if (authState === AuthState.SignedIn) {
          setSignedIn(true)
        } else if (authState === AuthState.SignedOut) {
          setSignedIn(false)
        }
      })
    }

    function handleHubEvents({ payload }) {
      setErrorMessage(null)
      logger.debug(payload)

      if (payload.event === TOAST_AUTH_ERROR_EVENT && payload.message) {
        setErrorMessage(payload.message)
      }
    }

    function onClickCloseError(e) {
      e.preventDefault()
      setErrorMessage(null)
    }

    async function setUser() {
      try {
        const user = await Auth.currentAuthenticatedUser()
        if (user) setSignedIn(true)
      } catch (err) {
        logger.debug(err)
      }
    }

    if (!signedIn) {
      return (
        <AmplifyContainer>
          <AmplifyAuthContainer>
            {errorMessage && (
              <Toast message={errorMessage} onClickClose={onClickCloseError} />
            )}
            <AmplifyAuthenticator
              {...authenticatorProps}
              {...props}
              usernameAlias={'email'}
              hideToast={true}
            >
              <AmplifySignIn slot={'sign-in'} usernameAlias={'email'} />
              <AmplifySignUp
                slot={'sign-up'}
                usernameAlias={'email'}
                formFields={[
                  {
                    type: 'email',
                    placeholder: 'Enter your email address'
                  },
                  {
                    type: 'password',
                    placeholder: 'Enter your new password',
                    hint: 'Must be 8 characters long, at least 1 capital letter, 1 lower case letter, 1 number and 1 symbol.'
                  }
                ]}
              />
              <AmplifyConfirmSignIn slot={'confirm-sign-in'} />
              <AmplifyConfirmSignUp
                slot={'confirm-sign-up'}
                usernameAlias={'email'}
              />
              <AmplifyForgotPassword
                slot={'forgot-password'}
                usernameAlias={'email'}
              />
              <AmplifyRequireNewPassword slot={'require-new-password'} />
              <AmplifyTotpSetup slot={'totp-setup'} />
              <AmplifyVerifyContact slot={'verify-contact'} />
            </AmplifyAuthenticator>
          </AmplifyAuthContainer>
        </AmplifyContainer>
      )
    }

    return <Component {...props} />
  }

  return AppWithAuthenticator
}

export default withAuthenticator

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

Amplify.configure({
  Auth: {
    identityPoolId: 'us-east-1:#######',
    region: 'us-east-1',
    userPoolId: 'us-east-1_#######',
    userPoolWebClientId: '#######',
    mandatorySignIn: false,
    authenticationFlowType: 'USER_SRP_AUTH'
  }
})

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

https://user-images.githubusercontent.com/3858265/129182560-00111fe5-d5bd-4ad0-958a-eb4bcc535c79.mov

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ericclemmonscommented, Nov 5, 2021

Confirmed this is fixed in @next:

https://user-images.githubusercontent.com/15182/140546236-f17facf0-4b5b-446a-91f6-4e84f1de2e11.mp4

This also works as expected for custom fields appended to the form:

https://ui.docs.amplify.aws/ui/components/authenticator?platform=react#sign-up-fields

Unfortunately, the architecture for the previous implementation around formFields basically wipes out values between renders, which is what caused this bug.

The new implementation respects existing values and correctly updates them.

0reactions
therobwatsoncommented, Nov 22, 2021

Thanks @ericclemmons ! Yes, your suggestion worked. Sorry, I’m getting used to the new syntax and it seems like my mishmash combo seemed to work in some nightly(?) @next build.

The following worked for me (using a fresh @next install, if it matters):

export default withAuthenticator(Component, {
  loginMechanisms:['email'],
  components: {
    SignUp: {
      FormFields() {
        return (
          <Authenticator.SignUp.FormFields />
        )
      }
    }
  }
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

No current user for authenticated user in Amplify
The error is literally saying No current user - you need to sign in using the supported identity provider. My solution to that:...
Read more >
The Complete Guide to User Authentication with the Amplify ...
In this post, you'll learn how to add authentication to your React application using both OAuth as well as username & password login....
Read more >
Troubleshooting Amplify identity and access
Use the following information to help you diagnose and fix common issues that you might encounter when working with Amplify and IAM. If...
Read more >
Authentication in React with AWS Cognito and Amplify
Authentication For React Apps Using AWS Amplify And Cognito ... add the following code, whereby we have a basic input with a submit...
Read more >
Build a React App with Authorization and Authentication
First, let's get on the same page with what authorization and authentication are: ... This tutorial will be bypassing teaching React and AWS...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found