Unable to confirm the user registration via AWS SDK - amazon-web-services

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

Related

How do I send a user pool user a custom email when invoking forgot_password

AWS Cognito IDP (Identity Provider) is a service AWS provides for managing users of your service via user pools. Cognito provides a variety of APIs and one can programmatically use Cognito via boto3, the Python wrapper for AWS.
The forgot_password method is used when a user has forgotten their password:
cog.forgot_password(ClientId=USER_POOL_CLIENT_ID, Username=req["username"])
This sends an email to a user with a six digit code that the user can use to change their password.
The thing is, I want the email to contain custom content along with the six digit code. I am certain this must be possible, that there must be a way to have templated content and use that templated content to send the user an email with custom content that also contains the six digit code.
Does anyone know, when invoking the forgot_password for AWS Cognito IDP using boto3 how I can send a custom email that contains the six digit code?
Thanks!
Amazon Cognito invokes custom triggers before sending an email or phone verification message or a multi-factor authentication (MFA) code, allowing you to customize the message dynamically.
You need to create a lambda function and use CustomMessage_ForgotPassword as triggerSource. For example:
if(event.userPoolId === "theSpecialUserPool") {
// Identify why was this function invoked
if(event.triggerSource === "CustomMessage_ForgotPassword") {
// Ensure that your message contains event.request.codeParameter. This is the placeholder for code that will be sent
event.response.emailSubject = "Forgot Password";
event.response.emailMessage = "Your customized text here" + event.request.codeParameter + " and your verification code";
}
// Create custom message for other events
}
Then integrate this lambda function with your cognito pool by doing the following:
AWS Console -> Cognito -> Pool -> General Settings -> Triggers -> Custom Message.
So every time that a user call forgot password your pool will trigger the above lambda instead of the default forgot password AWS cognito lambda.
Reference
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html

Cognito authentication with username or unique email via AWS Amplify

Amplify CLI authentication with Cognito user pools currently has two main modes, signin with username or with email. In the former case email uniqueness as a required user attribute is not being enforced.
Cognito service by itself supports the "Also allow sign in with verified email address" option (AWS Console, User Pool Attributes-section) but it can be set only upon user pool creation (i.e. can not be modified later - checkboxes are disabled). Is it possible to enforce no duplicate emails within the user pool while allowing users to authenticate with username or with email?
To summarize, my use case requires:
Verifying/enforcing email attribute uniqueness at the Cognito level when signing up users via Amplify's Auth.SignUp;
Keeping username-based login but allowing users to login with their email as well (that is, Auth.SignIn with email or username supplied as the username-argument).
When you add the user pool with amplify add auth choose 'Username' as the method with which you want users to sign in when prompted.
If you aren't prompted with this choice, you might need to try amplify add auth again but this time choose Manual configuration when prompted at the beginning.
Once you've completed the entire auth set up via amplify add auth, BEFORE you run amplify push for the first time, run amplify override auth.
This creates a new override.ts file which you can edit with AWS CDK code to customise your Cognito resources beyond the abilities the CLI allows.
You can find the override.ts file at:
amplify\backend\auth\<your_app_name>\override.ts
Inside the override file, add the following line into the empty function that's made for you:
resources.userPool.aliasAttributes = ['email'];
Now you can save the file, and run amplify push and hopefully your new user pool will show in the AWS Console that you've successfully configured it to allow user name and email sign in together.
You have to make sure you write the override code before amplify push or your user pool will be created in the cloud, and attempting to override this sign in functionality after the user pool has been created throws an error as it's read only.
If you find yourself in that position, you'll need to create a new user pool, you can't modify the existing one.

AWS Cognito sign up without password to get email confirmation link

I want to make a simple flow for registration app.
User sign up with only email -> The verification/registration link is sent to the email -> People register (putting in their password) on that link
I've googled anything but haven't found any way to make it with AWS Cognito.
Looks like Cognito is forcing users to sign up with at least email AND password to get the confirmation link
You can sign up users with adminCreateUser API call. They will receive an email with temporary passwords. This approach is configurable.
See: https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html
Use: AdminCreateUser
Create a new user profile by using the AWS Management Console or by calling the AdminCreateUser API. Specify the temporary password(will be your user's 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,
1. authenticate user using same user credentials
Use: SDK calls InitiateAuth(Username, USER_SRP_AUTH)
2. After success of initateAuth, amazon Cognito returns the PASSWORD_VERIFIER challenge with Salt & Secret block.
3. Use RespondToAuthChallenge(Username, <SRP variables>, PASSWORD_VERIFIER
4. Amazon Cognito returns the NEW_PASSWORD_REQUIRED challenge along with the current and required attributes.
5. The user is prompted and enters a new password and any missing values for required attributes.
6. Call RespondToAuthChallenge(Username, <New password>, <User attributes>).
7. After successful password change user can be able to login using same credentials added by you.
Short answer
- In that case, you can specify the temporary password(will allow Amazon Cognito to automatically generate one.).
- all user users will be forced to change their password only at first login.

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