Describe the bug
When logging into an app using aws-amplify-react
, the user is prompted to verify their email address every time they log in. This persists whether or not email verification is enabled in the user pool configuration.
To Reproduce
I'm not sure if there's an easy way to reproduce this. I stood up one version of the stack and it worked fine, but then when standing up another version with the same configuration I suddenly saw the problem. No amount of messing with the parameters so far has allowed me to fix the issue. It's possible this is a configuration issue on my end; if so I'd appreciate advice on how to further debug, since I feel like I'm up against a wall.
Here are the relevant user pool parameters (trimmed of any parameters that are just references to resource names):
{
"allowUnauthenticatedIdentities": false,
"thirdPartyAuth": false,
"autoVerifiedAttributes": [
"email"
],
"mfaConfiguration": "OFF",
"mfaTypes": [
"SMS Text Message"
],
"smsAuthenticationMessage": "Your authentication code is {####}",
"smsVerificationMessage": "Your verification code is {####}",
"emailVerificationSubject": "Your verification code",
"emailVerificationMessage": "Your verification code is {####}",
"defaultPasswordPolicy": true,
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": [],
"requiredAttributes": [
"email"
],
"userpoolClientGenerateSecret": true,
"userpoolClientRefreshTokenValidity": 30,
"userpoolClientReadAttributes": [
"email"
],
"userpoolClientSetAttributes": false,
"useDefault": "manual",
"authSelections": "identityPoolAndUserPool",
}
Expected behavior
I'd expect that once a user has the attribute email_verified
, they wouldn't have to verify their email again.
Desktop (please complete the following information):
Additional context
I don't know which service this bug might be appearing in. Here are the versions I have installed of all Amplify packages:
aws-amplify
: 1.1.19
aws-amplify-react
: 2.1.7
@aws-amplify/cli
: 0.1.45
I recognize that some of these are now outdated, but I wanted to avoid upgrading them for fear of having to migrate the project.
@jeancochrane - To debug this, try setting a log level. In index.js or similar entry you can do: window.LOG_LEVEL = 'DEBUG';
. This will turn on Amplify's logger. Then (after reproducing the issue), look for an entry like [DEBUG] 57:38.864 Authenticator - authenticator state change verifyContact
. You can then see the CognitoUser data being used the component(s). There is a property called 'unverified' which contains the unverified attributes. What do you see there?
I'm just trying to isolate whether this is an issue with the response from Cognito or an issue with the component.
Thanks for the debug instructions @haverchuck! Will give that a try when I have a free minute and let you know what the output says.
Interestingly, the CognitoUser
object in the debug output says that the email address is unverified:
{
"username": "jeancochrane",
"unverified": {email: "${email}"}
"verified": {},
...
}
However, when I grab the userPoolId
from the pool
attribute and use the AWS CLI to list-users
, the user has a truthy value for email_verified
:
$ aws cognito-idp list-users --user-pool-id ${user_pool_id}
{
"Users": [
{
"Username": "jeancochrane",
"Attributes": [
{
"Name": "sub",
"Value": "${sub}"
},
{
"Name": "email_verified",
"Value": "true"
},
{
"Name": "phone_number_verified",
"Value": "true"
},
{
"Name": "phone_number",
"Value": "${phone}"
},
{
"Name": "email",
"Value": "${email}"
}
],
"UserCreateDate": 1550509449.43,
"UserLastModifiedDate": 1550511030.237,
"Enabled": true,
"UserStatus": "CONFIRMED"
},
...
]
}
@jeancochrane - This does look like some sort of configuration issue. Could you please:
a) Post the client code you are using for authentication (unless you are just using an unmodified version of the aws-amplify-react Authenticator component)
b) a screen shot of your user pool settings in the Cognito console (feel free to redact senstive values)
c) your aws-exports key/values (again, with anything sensitive redacted)
This will help us dig into it further.
Sure thing! I've replaced potentially sensitive values with ${variable_notation}
below.
a) Post the client code you are using for authentication (unless you are just using an unmodified version of the aws-amplify-react Authenticator component)
I believe this is the component in question:
import withAuthenticator from './components/with-authenticator'
const ConnectedApplication = withAuthenticator(withRouter(
connect(mapStateToProps, actions)(Application)), true,
[
<CustomSignIn override={SignIn} />,
<ConfirmSignIn />,
<ConfirmSignUp />,
<ForgotPassword />,
<Loading />,
<RequireNewPassword />,
<TOTPSetup />,
<VerifyContact />
], null, CustomAuthenticatorTheme)
Here's a gist containing the implementation of withAuthenticator
: https://gist.github.com/jeancochrane/4bcc7faeaa6b615e5f4e52619a77fc4f
There are a few custom components passed in here that mostly adjust styling. I can post code for any of them that seem like they might be possible culprits. My colleague who's handling the frontend code believes that it isn't a frontend configuration issue, however, since authentication works as expected for the staging stack but not the production stack.
b) a screen shot of your user pool settings in the Cognito console (feel free to redact senstive values)
I'll do you one better, here's the output of describe-user-pool
:
{
"UserPool": {
"Id": "${user_pool_id}",
"Name": "${user_pool_name}",
"Policies": {
"PasswordPolicy": {
"MinimumLength": 8,
"RequireUppercase": false,
"RequireLowercase": false,
"RequireNumbers": false,
"RequireSymbols": false
}
},
"LambdaConfig": {},
"LastModifiedDate": 1550510694.585,
"CreationDate": 1550257417.659,
"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"
}
}
],
"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": "OPTIONAL",
"EstimatedNumberOfUsers": 3,
"EmailConfiguration": {},
"SmsConfiguration": {
"SnsCallerArn": "${sns_rol_arn}",
"ExternalId": "${role_external_id}"
},
"UserPoolTags": {},
"AdminCreateUserConfig": {
"AllowAdminCreateUserOnly": true,
"UnusedAccountValidityDays": 7
},
"Arn": "${user_pool_arn}"
}
}
c) your aws-exports key/values (again, with anything sensitive redacted)
const awsmobile = {
"aws_project_region": "us-east-1",
"aws_cognito_identity_pool_id": "us-east-1:${id_pool_uuid}",
"aws_cognito_region": "us-east-1",
"aws_user_pools_id": "us-east-1_${user_pool_id}",
"aws_user_pools_web_client_id": "${user_pool_client_id}",
"aws_user_files_s3_bucket": "${s3_bucket_name}",
"aws_user_files_s3_bucket_region": "us-east-1"
};
Let me know if you need any more info to help debug!
@jeancochrane I'm working on trying to reproduce this (so far without luck). You say that this works on your staging stack but not on your production stack. Are you using the Amplify CLI and/or console to manage these environments? Do you see any differences between the two user pools?
Also - were these users created via self registration and the SignUp component, or were they created by an admin in the Cognito console? If the latter, which options were selected on the creation modal?
Are you using the Amplify CLI and/or console to manage these environments? Do you see any differences between the two user pools?
We're using Amplify CLI to manage both environments. As far as I can tell, the user pools are close to identical -- the only differences are A) some minor differences in the password requirements and B) users in the production stack (the one seeing the unexpected behavior) cannot create their own accounts, while users in the staging stack can.
Were these users created via self registration and the SignUp component, or were they created by an admin in the Cognito console? If the latter, which options were selected on the creation modal?
I've tried creating users both ways, with no luck. Here's what the options look like in the creation modal:
I'm working on trying to reproduce this (so far without luck).
Thanks for giving it a try! I understand if you can't reproduce -- part of my frustration is that the working stack is essentially identical to the malfunctioning stack in terms of its exposed configs, so I expected that reproducing would be difficult. Mostly I was wondering if you had any idea of further things I could try to inspect. If not, I think the next step for us is to tear down and recreate the production stack from scratch and see if we get the same behavior.
@jeancochrane I tried to reproduce the problem using withAuthenticator
component like this.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Amplify from 'aws-amplify';
import { withAuthenticator } from 'aws-amplify-react';
import config from './aws-exports';
Amplify.configure(config);
Amplify.Logger.LOG_LEVEL = 'DEBUG';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
}
export default withAuthenticator(App, true);
When I created the user without confirming the email, I see the Account recovery requires verified contact information screen. By selecting the email radio button and verifying the code that is sent to the email change the status of the user and never ask for that again.
I think the problem could be on the userPoolId, can you double check the userPoolId
that is on CognitoUser
object.
@elorzafe The user pool ID in the CognitoUser
object matches the one I'm expecting to see in the console, and when I run aws congito-idp list-users
with the pool ID I can confirm that the attribute email_verified
for my user is set to "true"
.
I'll give it a try using the component that you posted, just to rule out that it's a frontend issue.
I tried to stand up a new version of the stack and unfortunately was able to reproduce this problem. What version of the CLI are you using? Take note that we're pinned to 0.1.45
since we didn't want to incur the breaking changes in 1.x
.
Finally got to the bottom of this! Turns out it was a configuration error on my end -- during the CLI wizard, I neglected to set UserPoolClient.ReadAttributes
to include email_verified
. In the CLI, this corresponds to the following steps in amplify add auth
:
? Do you want to specify the user attributes this app can read and write? Yes
? Specify read attributes: (Press <space> to select, <a> to toggle all, <i> to invert selection)
◯ Updated At
◯ Website
◯ Zone Info
❯◯ Email Verified?
◯ Phone Number Verified?
◯ Address
◯ Birthdate
(Move up and down to reveal more choices)
Thanks for your debugging assistance @haverchuck and @elorzafe, I appreciate it!
@jeancochrane I am glad you issue was solved. Good catch!
I just got hit with this. For those that need to fix this:
amplify/backend/auth/$cognitofolder/parameters.json
userpoolClientReadAttributes
array and add email_verified
amplify push
Is there a use case where the *_verified
attributes shouldn't be returned? At the least, it seems like the CLI wizard should try and talk you out of disabling them as read attributes (and describe the consequences).
Related issue? #3607
Most helpful comment
Finally got to the bottom of this! Turns out it was a configuration error on my end -- during the CLI wizard, I neglected to set
UserPoolClient.ReadAttributes
to includeemail_verified
. In the CLI, this corresponds to the following steps inamplify add auth
:Thanks for your debugging assistance @haverchuck and @elorzafe, I appreciate it!