AWS Cognito - PostSignUp Trigger Not Working - amazon-web-services

i have a post signup trigger setup to store the user details in DynamoDb table. This works fine when the user signs up on their own through the front-end but the trigger is never invoked if the user is created through AdminCreateUser API. Our assumption was after the newly added user gets an email with a temporary password and logins through the front-end, Cognito will invoke the postsignup trigger.
Is that an expected behavior? And also, how do we address this issue?

Although that's counter intuitive, seems that's the expected behavior.
Post Confirmation trigger is not invoked when a user is created via AdminCreateUser API.
Workaround could be to to use Post Authentication trigger and during processing of the fired event to check if cognito:user_status is FORCE_CHANGE_PASSWORD.
When a user is created using AdminCreateUser, status of the new user is set to FORCE_CHANGE_PASSWORD. Once user logs in and changes temporary password, status is changed to CONFIRMED.
Downside is that trigger is invoked after every login.

Related

Disallow user login if email_verified is false

When a user registers for my application I handle the request through an API and send an email containing a verification link. When the link is clicked it updates the email_verified attribute to true. This is working as expected.
The problem I'm having is that a user is allowed to login even when the attribute email_verified is set to false.
I'm using amplify to login the user. How can I block user login if the email has not been verified?
I found out the answer to this myself. I was registering the user with a custom lambda function which creates the user using adminCreateUser. This API automatically sets the UserStatus to CONFIRMED which is the field that is used to determine whether a user can log in or not. I was working on the assumption that it was the email_verified field which determined this, which was incorrect.
I fixed this by instead using the signUp function of the API which instead creates the user in an UNCONFIRMED state and doesn't allow login until the sign up is confirmed.

Unable to confirm the user registration via AWS SDK

The AWS documentation for JS SDK says:
Force Change Password
The user account is confirmed and the user can sign in using a temporary password, but on first sign-in, the user must change his or her password to a new value before doing anything else.
User accounts that are created by an administrator or developer start in this state.
But if for such a user I try to call forgotPassword method of SDK, it errors saying something like: Password cannot be reset in the current state.
SO how can I complete the registration of a user (created by admin in IAM) from my website. Which is the SDK method that should be called ?
Setting up an Auto Verify Lambda Trigger on the Pre Sign Up Trigger will allow for the user to be a confirmed state, which may get you to the point you are looking for?
Lambda -> Node.js
Give it an appropriate Title
Place the below value in the code:
exports.handler = (event, context, callback) => {
// Confirm the user
event.response.autoConfirmUser = true;
// Set the email as verified if it is in the request
if (event.request.userAttributes.hasOwnProperty("email")) {
event.response.autoVerifyEmail = true;
}
// Return to Amazon Cognito
callback(null, event);
};
Save
Then Select newly created trigger in General Settings -> Triggers -> Pre sign-up
We can do this,
I previously answered mongodb to aws cogniton migration question.
Go through step by step. I explained that the user's created by admin need to change the password(forgot password) but there's still another way to do it. Checkout my answer,
Some content from my answer,
AdminCreateUser:
Create a new user profile by using the AWS Management Console or by calling the AdminCreateUser API. Specify the temporary password or allow Amazon Cognito to automatically generate one.
Specify whether provided email addresses and phone numbers are marked as verified for new users. Specify custom SMS and email invitation messages for new users via the AWS Management Console.
Specify whether invitation messages are sent via SMS, email, or both.
After successful user creation,
authenticate user using same user credentials Use: SDK calls InitiateAuth(Username, USER_SRP_AUTH)
After success of initateAuth, amazon Cognito returns the PASSWORD_VERIFIER challenge with Salt & Secret block.
Use RespondToAuthChallenge(Username, , PASSWORD_VERIFIER)
Amazon Cognito returns the NEW_PASSWORD_REQUIRED challenge along with the current and required attributes.
The user is prompted and enters a new password and any missing values for required attributes.
Call RespondToAuthChallenge(Username, , ).
After successful password change user can be able to login using same credentials which admin created.
Refer: Unable to confirm the user registration via aws

How to add user to own database during registration in a 'transactional' way?

I am trying to use AWS Cognito for my app.
I can register the users successfully to AWS Cognito, but I want to be able to also store them in my database (with my own API), too, as part of the sign-up process.
I saw that I could use a trigger function like Post confirmation, but as far as I understand, if saving the user to my database fails, then the user will still be created in the Cognito user pool.
I want to treat the sign-up process in a transactional way, so that if saving the user in my database fails, then the entire process fails.
So, it would look something like this:
Aws Cognito Sign Up -> Send_to_database_trigger ----fails----> user is not created
\---success--> user is created
Is there any way to achieve what I want? Thanks.
You can use the Pre Sign-up Lambda Trigger.
It gets the username and all the user attributes in the event and if it fails the user won't be signed up in Cognito.
In your case, you will save your user to your database in this trigger (after other possible validations) and will fail if saving to your database has failed. This way you can be sure that if a user exists in Cognito it also exists in your database.
If you need to save the sub then you can implement both Pre Sign-up and Post Confirmation and update your database record with the sub in the Post Confirmation trigger.

AWS Cognito - run another lambda after migration lambda has run

Cognito has a migration lambda that allows us to confirm a user in our db. They send the email and PW to Cognito, the lambda fires, we verify matches, and the user is entered into Cognito.
At this point - behind the scenes - Cognito generates a username of some kind (UUID). The problem is, I need a way to get this username into our existing database, because our systems going forward will no longer rely on email and instead rely on this username.
Ideal flow:
Sign In
Migration Succeeds
Cognito generates username
Username is sent to our server.
Now because we have email set to auto-verified, no post-confirmation lambda can be called. The only way I see to do this with Cognito as-is is to either:
Ask users who already exist in our system to confirm their email again. This is a non-starter
Create a post-auth lambda, check user login count through a custom attribute, and if 0 (or if not already registered with the service, etc.) migrate the username to the new service.
If there is any other way to do this, please let me know.
After the user migration lambda is called your pre sign-up lambda will be called, assuming you have implemented it. The parameters received by your lambda will include username with the value being the UID you referenced. Parameters will also include user attributes containing email. You can use this information to update your database.
I did not want to add the PreSignup trigger, its a complicated way of doing it if you already rely on PostConfirmation, and if the majority of new users won't be migrations. My use case has a frontend initiate the signup process as well, which I use here.
Instead, I set a Cognito attribute on the new user during the UserMigration trigger. It could be 'user_migration': <oldUserSub>, or however you want to mark it. Just make sure you allow this property within the Cognito user pool settings.
When the UserMigration trigger returns, this information is now accessible through verifying the IdToken, or found in the JWT on the frontend if you're using that. So, when the user is migrated into Cognito and the response gets back to the Cognito client on the frontend, I can now recognize this user needs to be migrated into my personal database. Seeing this, I'll call a new endpoint on my backend to handle this. This new endpoint does exactly what PostConfirmation would typically do.
Then just delete the 'user_migration' property from the Cognito user, return the new user data to the frontend and everything should be set up.
You can use Pre sign-up trigger. In order to detect if the trigger event came from your migration trigger, you can check at the trigger_source value from the event object. In my case (i'm using migration trigger) the value is PreSignUp_AdminCreateUser. By knowing the value of trigger_source you can differentiate if it was migrated or regular user. You can also check the user attributes to know whether the email or phone is verified or not.
Here's my sample code on python:
def lambda_handler(event, context):
trigger_source = event.get('triggerSource')
user_attributes = request.get('userAttributes')
email_verified = user_attributes.get('email_verified')
if trigger_source == 'PreSignUp_AdminCreateUser' and email_verified == 'true':
# create user on db

Check for expired account for users created by adminCreateUser in AWS Cognito

I have a Lambda function which creates users using adminCreateUser Cognito function. My app is basically an invite only app where the admin can only invite certain users. Everything is working great so far, and I am able to resend invitation email notifications as well. However, I am trying to figure out how I can find out if a user created by adminCreateUser method has "expired" i.e. the user has not accepted the invite and changed the temporary password.
When the admin creates a user using adminCreateUser the status is FORCE_CHANGE_PASSWORD by default. When the user with this status attempts to Log in using the temporary password (from the verification email), Cognito sends a challenge back in the challengeName attribute of NEW_PASSWORD_REQUIRED, based on which the user is forced to change their password through the application and upon successful reset the status would change to CONFIRMED in Cognito for that user. This is working great so far, but I also need to handle scenario where the invited user never really changed their password by attempting to log into the application.
Now, I have set the - "How quickly should user accounts created by administrators expire if not used?" - to 7 days (default). What would be the status of the user account after 7 days if the user doesn't reset their password? I tried to find out from the documentation but it's not clear what the status of the user account would be in this situation.
NOTE: This is not about Token expiration in the client but rather expiration of an account created via the adminCreateUser method.
Annjawn,
According below link: "After the account expires, the user cannot log in to the account until the administrator updates the user's profile by updating an attribute or by resending the password to the user"
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-admin-create-user-policy.html
All tthe best,
Guto