Closed 5t33 closed 1 year ago
Hi @5t33
Is the email address the login method for your user pool or do you have another method and the email is just an attribute? I tried this out and it seems to be working as expected with a user pool set up to login by username with email address as an attribute.
I noticed that it never filled in the unverified key, rather it kept the old email as verified until I successfully completed the verifyCurrentUserAttributeSubmit
step, then showed the new email as the verified one.
Hi 👋 Closing this as we have not heard back from you. If you are still experiencing this issue and are in need of assistance, please feel free to comment and provide us with any information previously requested by our team members so we can re-open this issue and be better able to assist you.
Thank you!
@tannerabread sorry, we moved on to other things and I haven't checked back in.
Here's the Terraform configuration for my Cognito:
resource "aws_cognito_user_pool" "users" {
provider = aws.terraform_role
username_attributes = [
"email",
]
auto_verified_attributes = [
"email",
]
username_configuration {
case_sensitive = false
}
mfa_configuration = "OFF"
name = "users_${var.environment}"
tags = {
Environment = var.environment
}
account_recovery_setting {
recovery_mechanism {
priority = 1
name = "verified_email"
}
}
admin_create_user_config {
allow_admin_create_user_only = false
invite_message_template {
email_message = "Your username is {username} and temporary password is {####}. "
email_subject = "Your temporary password"
sms_message = "Your username is {username} and temporary password is {####}. "
}
}
device_configuration {
challenge_required_on_new_device = true
device_only_remembered_on_user_prompt = false
}
email_configuration {
email_sending_account = "DEVELOPER"
from_email_address = local.no_reply_email
reply_to_email_address = local.no_reply_email
source_arn = local.sending_email_arn
}
password_policy {
minimum_length = 8
require_lowercase = false
require_numbers = false
require_symbols = false
require_uppercase = false
temporary_password_validity_days = 3
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "email"
required = true
string_attribute_constraints {
max_length = "2048"
min_length = "0"
}
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "name"
required = false
string_attribute_constraints {
max_length = "2048"
min_length = "0"
}
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "user_type"
required = false
string_attribute_constraints {
max_length = "2048"
min_length = "0"
}
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "plan"
required = false
string_attribute_constraints {
max_length = "256"
min_length = "1"
}
}
schema {
attribute_data_type = "String"
developer_only_attribute = false
mutable = true
name = "is_test_user"
required = false
string_attribute_constraints {
max_length = "256"
min_length = "1"
}
}
verification_message_template {
default_email_option = "CONFIRM_WITH_LINK"
email_message_by_link = "Please click the link below to verify your email address. {##Verify Email##} "
email_subject = "Your verification code"
email_subject_by_link = "Your ${var.org_name} verification link"
}
}
resource "aws_cognito_user_pool_client" "users_web" {
provider = aws.terraform_role
allowed_oauth_flows = []
allowed_oauth_flows_user_pool_client = false
allowed_oauth_scopes = []
callback_urls = []
explicit_auth_flows = [
"ALLOW_REFRESH_TOKEN_AUTH",
"ALLOW_USER_SRP_AUTH",
// "ALLOW_USER_PASSWORD_AUTH",
// "USER_PASSWORD_AUTH"
]
logout_urls = []
name = "${var.org_name}-web-${var.environment}"
prevent_user_existence_errors = "ENABLED"
read_attributes = [
"email",
"name",
"custom:user_type",
"custom:is_test_user",
"updated_at",
]
refresh_token_validity = 30
supported_identity_providers = []
user_pool_id = aws_cognito_user_pool.users.id
write_attributes = [
"email",
"name",
"custom:user_type",
"custom:is_test_user",
"updated_at",
]
}
email is the username
I do not have experience with terraform, but tried again with a new app with only this functionality and am seeing the same results as I did previously.
I only get the verified object with information, and the unverified remains empty. Then when the new email is verified it switches the email that is shown in the verified object.
As you are using terraform and I used the CLI, can you confirm if these settings are the same in your Cognito user-pool? I tried to read through your terraform config following the docs and I do not see anything wrong, but maybe I'm missing something.
It's also worth asking since you are creating the resources by terraform how the config looks for Amplify? Since I created mine with the CLI, it ends up looking like this:
Amplify.configure({
"aws_project_region": "us-east-1",
"aws_cognito_identity_pool_id": "us-east-1:xxxxxx",
"aws_cognito_region": "us-east-1",
"aws_user_pools_id": "us-east-1_xxxxxx",
"aws_user_pools_web_client_id": "xxxxxx",
"oauth": {},
"aws_cognito_username_attributes": [
"EMAIL"
],
"aws_cognito_social_providers": [],
"aws_cognito_signup_attributes": [
"EMAIL"
],
"aws_cognito_mfa_configuration": "OFF",
"aws_cognito_mfa_types": [
"SMS"
],
"aws_cognito_password_protection_settings": {
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": []
},
"aws_cognito_verification_mechanisms": [
"EMAIL"
]
})
After configuring, I created an App.js like:
import logo from "./logo.svg";
import "./App.css";
import { Auth } from "aws-amplify";
import { verifiedContact } from "./test.ts";
function App() {
async function signUp() {
try {
const { user } = await Auth.signUp({
username: "test1@gmail.com",
password: "testtest",
});
console.log(user);
} catch (error) {
console.log("error signing up:", error);
}
}
async function confirmSignUp() {
try {
await Auth.confirmSignUp("test1@gmail.com", "123456");
} catch (error) {
console.log("error confirming sign up", error);
}
}
async function signIn() {
try {
const user = await Auth.signIn("test1@gmail.com", "testtest");
} catch (error) {
console.log("error signing in", error);
}
}
async function signOut() {
try {
await Auth.signOut();
} catch (error) {
console.log("error signing out: ", error);
}
}
async function updateUserAttributes() {
const user = await Auth.currentAuthenticatedUser();
console.log(user.attributes);
const newUser = await Auth.updateUserAttributes(user, {
email: "test2@gmail.com",
});
console.log({newUser})
}
async function verifyCurrentUserAttributeSubmit() {
const response = await Auth.verifyCurrentUserAttributeSubmit('email', '654321')
console.log({response})
}
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>
<button onClick={signUp}>Sign Up</button>
<button onClick={confirmSignUp}>Confirm Sign Up</button>
<button onClick={signIn}>Sign In</button>
<button onClick={signOut}>Sign Out</button>
<button onClick={updateUserAttributes}>Update User Attributes</button>
<button onClick={verifyCurrentUserAttributeSubmit}>Verify Current User Attribute Submit</button>
<button onClick={verifiedContact}>Verified Contact</button>
</header>
</div>
);
}
export default App;
With the buttons I set up, I did the following process:
Hey @tannerabread
First I'd like to thank you for your help and apologize for my inconsistent communication. This is a side project for me and there's a lot to do so I have limited time. I took a look at the sign up experience page and did notice some inconsistencies with what yours showed. It looks like I need to enable "Verifying attribute changes".
You're welcome! No worries about the communication I'm here to help when you have time.
Does that solve your issue or were you just pointing out the inconsistency? If you were trying to keep that as disabled I will try my user pool with disabled as well and see if I get the same results
So I was just curious to see if I would experience the same bug, but when I try it with that option disabled, I get what would be expected.
Steps/Flow I see:
verifiedContact
function (shows new email as unverified, verified is blank)verifyCurrentUserAttributeSubmit
verifiedContact
again (shows new email as verified, unverified is blank)Hi @5t33 were you ever able to solve this? I wasn't positive if the tweak in the Cognito console solved your issue or not.
Someone suggested to me that if the above doesn't solve your issue, try to get the user by bypassing the cache as well, e.g.
Auth.currentAuthenticatedUser({ 'bypassCache': true });
@5t33, we'll close this issue out for now since we have not heard back from you. If you are still experiencing this, please feel free to reply back and provide any information previously requested and we'd be happy to re-open the issue.
Thank you!
Hey there,
Unfortunately I had to get into the weeds on another task again so I left this issue for now, but I'm back for a bit of troubleshooting.
I did try to update the field shown above and it did not help. Here's the screen shot:
While I could give Auth.currentAuthenticatedUser({ 'bypassCache': true });
a shot... I don't have a lot of hope because it happens even with users who have logged in for the first time (and just verified their email).
Here's a user I just created (and verified):
and the response from verifiedContact:
I'm going to poke around at that config @tannerabread mentioned above and see if there are any discrepancies with my set up. Barring that, we're still in dev and haven't shipped yet so I might delete and re-create with the new config to see if it's an "on-create" type thing.
I'm also wondering if it has something to do with the discrepancy between "username" and "email". Here's my sign up user function:
export const signUpUser = (signUpData: SignUpData): Promise<any> => {
userSignUpParams.forEach((field: string) => {
if (isNil(signUpData[field as keyof SignUpData])) {
throw new MissingSignUpFormDataError(field);
}
});
const fields = {
username: signUpData.email,
password: signUpData.password,
attributes: {
name: signUpData.name,
email: signUpData.email,
'custom:is_test_user': 'false',
'custom:user_type': 'user'
}
};
As you can see, the "username" field is being set as the email, because that's what they use to log in. Is it possible I need to send "username" back to verifyCurrentUserAttributeSubmit
for the verification step?
Wow I figured it out!
After poking around the UI a bit I noticed the "Attribute read and write permissions" section of the client UI. After inspecting the permissions of the client we use for our web app, I noticed that it did not have permissions set for the "email_verified" field.
In the UI I wasn't able to add the write permission for the field to the client, but after adding the read perm, the verification output returned correctly - at least for the newly created user. I have yet to try changing a user's email. Anyway, for completeness, here's the terraform config I changed:
read_attributes = [
"email",
"email_verified",
...
]
Well, ironically, this is only an issue in the event that a user starts the process (hits submit) but never actually validates the new email. That was kind of the whole point of the check. But, the change that @tannerabread suggested (enabled verify attribute change) made that completely unnecessary because the attribute remains the same until verification is complete.
Well I guess I learned something.
Thanks for your help @tannerabread and @cwomack
Before opening, please confirm:
JavaScript Framework
React
Amplify APIs
Authentication
Amplify Categories
auth
Environment information
Describe the bug
I have a form to allow users to update their account information in a settings page. It's a bit circuitous but it uses this Amplify auth function:
Once this function is called, my code shows a view that requests the verification code which is sent to the users email when an email is updated.
That calls this function with the code and the new email:
Now, there's a chance that the user doesn't complete this step. So, I have a use effect hook which calls the following function:
And if the user's email isn't verified it asks the user to verify (by re-sending the code and opening the "input code" form).
However, this function always returns unverified for the email, even after the verifyCurrentUserAttributeSubmit returns success. The email is verified in the AWS console (where is wasn't immediately after being changed).
Expected behavior
I expect the "unverified" block of the VerifiedContact function to no longer contain the email address after returning success after being called with "email" and the provided code.
Reproduction steps
I hopefully explained this in the steps above, but more explicitly:
Code Snippet
Log output
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
No response