I am using Parse Server from the market place of AWS and is able to access the database without a problem. But, I am not able to send email verification to newly signed up users.
After did some research, I know that I have to add Mail Adapter and enable a few parameters for the Parse Server but I don't know how to add Adapter from the dashboard
https://github.com/parse-community/parse-server#email-verification-and-password-reset
It's not possible to add a mail adapter using the dashboard. You should have the Mailgun adapter installed by default.
To add the configuration you need to access your server and add the following to your index.js file:
var server = ParseServer({
...otherOptions,
// Enable email verification
verifyUserEmails: true,
// if `verifyUserEmails` is `true` and
// if `emailVerifyTokenValidityDuration` is `undefined` then
// email verify token never expires
// else
// email verify token expires after `emailVerifyTokenValidityDuration`
//
// `emailVerifyTokenValidityDuration` defaults to `undefined`
//
// email verify token below expires in 2 hours (= 2 * 60 * 60 == 7200 seconds)
emailVerifyTokenValidityDuration: 2 * 60 * 60, // in seconds (2 hours = 7200 seconds)
// set preventLoginWithUnverifiedEmail to false to allow user to login without verifying their email
// set preventLoginWithUnverifiedEmail to true to prevent user from login if their email is not verified
preventLoginWithUnverifiedEmail: false, // defaults to false
// The public URL of your app.
// This will appear in the link that is used to verify email addresses and reset passwords.
// Set the mount path as it is in serverURL
publicServerURL: 'https://example.com/parse',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Parse App',
// The email adapter
emailAdapter: {
module: '#parse/simple-mailgun-adapter',
options: {
// The address that your emails come from
fromAddress: 'parse#example.com',
// Your domain from mailgun.com
domain: 'example.com',
// Your API key from mailgun.com
apiKey: 'key-mykey',
}
},
// account lockout policy setting (OPTIONAL) - defaults to undefined
// if the account lockout policy is set and there are more than `threshold` number of failed login attempts then the `login` api call returns error code `Parse.Error.OBJECT_NOT_FOUND` with error message `Your account is locked due to multiple failed login attempts. Please try again after <duration> minute(s)`. After `duration` minutes of no login attempts, the application will allow the user to try login again.
accountLockout: {
duration: 5, // duration policy setting determines the number of minutes that a locked-out account remains locked out before automatically becoming unlocked. Set it to a value greater than 0 and less than 100000.
threshold: 3, // threshold policy setting determines the number of failed sign-in attempts that will cause a user account to be locked. Set it to an integer value greater than 0 and less than 1000.
},
// optional settings to enforce password policies
passwordPolicy: {
// Two optional settings to enforce strong passwords. Either one or both can be specified.
// If both are specified, both checks must pass to accept the password
// 1. a RegExp object or a regex string representing the pattern to enforce
validatorPattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{8,})/, // enforce password with at least 8 char with at least 1 lower case, 1 upper case and 1 digit
// 2. a callback function to be invoked to validate the password
validatorCallback: (password) => { return validatePassword(password) },
validationError: 'Password must contain at least 1 digit.' // optional error message to be sent instead of the default "Password does not meet the Password Policy requirements." message.
doNotAllowUsername: true, // optional setting to disallow username in passwords
maxPasswordAge: 90, // optional setting in days for password expiry. Login fails if user does not reset the password within this period after signup/last reset.
maxPasswordHistory: 5, // optional setting to prevent reuse of previous n passwords. Maximum value that can be specified is 20. Not specifying it or specifying 0 will not enforce history.
//optional setting to set a validity duration for password reset links (in seconds)
resetTokenValidityDuration: 24*60*60, // expire after 24 hours
}
});
You will need to replace some of the values with your own. See here for more details.
Related
I am trying to build an app in React Native with AWS Cognito as authenication pool. My user pool is set to use MFA(optional). My app has both phone/OTP based signup/sign and Social logins. When I signup with a phone number, I get the OTP and all my triggers are working.
Problem is when I signup with a email, I don't get the user signed session or Auth.currentAuthenticatedUser() always returns Not authenticated
My code
const cognitoUser = await Auth.signUp({
username: user.email //I get the email from Google signin SDK
password: Date.now().toString() // some random password
});
const signedInUser = await.signin(user.email) //This returns user info, but signinSession is null
I saw people saying the user record must be confirmed, so I tried both of these and both didn't seem to be working
Auth.sendCustomChallengeAnswer(
cognitoUser,
1111 // Some random number as my Lambda trigger will be sending OTPs to phone numbers only
);
Auth.confirmSignUp(
cognitoUser,
1111
)
I also noticed the authenticationFlowType is USER_SRP_AUTH in this case, I was expecting it to be CUSTOM_AUTH
Right now I am stuck with this, not able to get the logged in user info in subsequent app screens.Any help will be appreciated.
If you already have it set up such that the sign up email address used in Auth.signUp will receive a verification code, then you will be using Auth.confirmSignUp.
However note the method signature from the type definition file:
confirmSignUp(username: string, code: string, options?: ConfirmSignUpOptions)
The verification code is a string; not a number as you had posted.
We just solved an issue where entering a wrong phone number (starting digit was missing) resulted in 'phone_number_verified' defaulting to false. Now that the issue is resolved, we do still have a lot of registered users who have had an activation sent to them (and entered said code) whose statuses are CONFIRMED in AWS Cognito, but have the 'phone_number_verified' property still set to false. Is there any way to edit this property in bulk / per user in Cognito itself or is there an API call that needs to be made? Or any solution that does not require the end user to go through the activation process again themselves.
(Further Info)
- AngularJS as Front-End
- Node v6.9 as Back-End
The recommendation here is that the users should call GetUserAttributeVerificationCode and receive a code to verify the phone/email which is then supplied to VerifyUserAttribute. This will ensure that if their numbers are verified.
Although if you are sure that all of their numbers are verified, you can use AdminUpdateUserAttributes to mark them verified. We do not have a batch API right now.
The phone number verified can be set to true by using the following example payload:
let parameters = {
UserPoolId : `${USER_POOL_ID}`,
Username : `${Username}`,
UserAttributes : [
{
'Name': "phone_number" ,
'Value': `${phoneNumber}`
},{
'Name':"phone_number_verified",
'Value': "true"
}]
}
cognitoIdentityServiceProvider.adminUpdateUserAttributes(parameters,function (err, result) {
if(err)
console.log(err);
else
console.log("Attribute updated successfully");
})
I want to change phone_number attribute of user before they confirm via phone. My flow step:
User register by username, password, and phone number
User must be enter confirmation code received by the phone. In this step user want to change the phone number (wrong number or change the phone...)
2.1 In case the 1st phone number be wrong, the next phone number is correct -> only one confirmation code had been sent -> it works!
2.2 In case the 1st phone number and the next are correct -> have two confirmation code had been sent(1st - xxx, 2nd - yyy) -> User enter 2nd confirmed code, Cognito throws CodeMismatchException: Invalid verification code provided, please try again. error. User enter 1st code, user had been confirmed, but in Cognito system the user has phone_number is 2nd number and phone_number_verified is true.
I use adminUpdateUserAttributes to change phone_number of a user who has status is UNCONFIRMED. Confirmation code auto send after me call change phone number.
How to fix this?
!!!Update
Currently, I removed the feature User can update their phone_number before they confirmed via phone from my application.
It takes me about 5 days, I just want to memo my case.
When you try to update phone_number (or email) attribute, Cognito will send a confirmation to your phone (or email) in automatically, this is the first code - (1st - xxx), the code to confirm your new attribute value (not for user confirmation).
In the same time, logic code calls resendConfirmationCode function, it send the second code - (2nd - yyy), this is main reason only the second code working (we use confirmSignUp function to handle the code).
I am on the Cognito team, same as behrooziAWS. After looking at your scenario, it does seem to be a bug on our side. I will mention it within the team so that we prioritize it accordingly.
This question was asked awhile ago but some people still having issues with verification code being sent and no way to verify the code on an account not confirmed yet so I found a solution that works for us.
Our auth flow is:
SignUp -> OTP Screen -> Confirmed OTP -> Cognito Account confirmed -> Custom email sent to user to verify email address -> Update attribute email_verified = true
On the OTP screen, we display the number OTP has been sent to, if it's the incorrect number, we allow the user to go back to signup page and change number and resubmit signup. We use a UUID for the user on cognito so as to allow a user to signup again without causing errors where account already exists but not confirmed.
This means we get two accounts with UUID in cognito, one being confirmed and one being unconfirmed with the only difference in the accounts is the phone number. We then get rid of unconfirmed accounts after a certain period. eg 7 days
For anybody else seeking the answer to this, what I ended up doing was writing a lambda that essentially checks if a user is unconfirmed, delete's the user and then signs them up again. I originally went the updateUserAttributes route but it felt insecure in case a bad actor got access to the lambda and updated a confirmed users phone number to theirs. If a user signups with a different username but the same number from a different account, it will invalidate the others users account. Hence the logic below.
try {
const userParams = {
UserPoolId: process.env.userpool_id,
Username: event.args.username
};
const { UserStatus } = await identity.adminGetUser(userParams).promise();
if (UserStatus === 'UNCONFIRMED') {
const deletedIdentity = await identity.adminDeleteUser(userParams).promise();
if (deletedIdentity) {
const signupParams = {
ClientId: process.env.client_id,
Password: event.args.password,
Username: event.args.password,
UserAttributes: [
{
Name: 'phone_number',
Value: event.args.phoneNumber
}
]
}
const newSignUp = await identity.signUp(signupParams).promise();
if (newSignUp) {
response.send(event, context, response.SUCCESS, {
newSignUp
});
callback(null, newSignUp)
}
}
} else {
response.send(event, context, response.ACCESSDENIED, {
error: 'User not authorized to perform this action'
});
callback({error: 'User not authorized to perform this action'}, null)
}
} catch (error) {
response.send(event, context, response.FAILURE, {
error
});
callback(error, null)
}
deploying an internal (corporate) API manager 2.0.0 we found a limitation - the email address validation apparently enforces email validation with 2-4 email :
/store/site/themes/wso2/templates/ui/validation/custom-validation.js:
$.validator.addMethod('validEmail', function(value, element) {
var emailRegex = /^([A-Za-z0-9_\-\.])+\#([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
return emailRegex.test(value);
}, i18n.t('Invalid email address'));
However - email addresses today may have even long last domain name (e.g. someuser#stad.gent, otheruse#my.internal.corporation)
I see the validation logic is implemented in the followinf file:
repository/deployment/server/jaggeryapps/store/site/themes/wso2/templates/ui/validation/custom-validation.js
Question: is the file the only place where the email format is enforced? (Users are managed in AD, so the default user view / management UI doesn't concern us too much atm)
Seems the only place where the email is validated is the script:
repository/deployment/server/jaggeryapps/store/site/themes/wso2/templates/ui/validation/custom-validation.js
I'm currently working on using AWS Cognito to manage user authentication for our application. One snag I'm running into is figuring out a good way to implement a "test" or "qa" environment.
I have a lot of automated tests for my APIs that will create users with random data. Obviously I don't want to Cognito to send out actual SMS or Email messages in this environment. Also when doing manual testing we will be creating users a lot with fake phone numbers and emails. Is there any way to turn the User Pool in "development" mode where all messages simply get logged some way?
You can write a pre sign up lambda function and auto confirm the user in the lambda function by setting the autoConfirmUser flag. In that case, Cognito doesn't send any SMSes or emails with confirmation codes. Example lambda below from the documentation (http://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#aws-lambda-triggers-pre-registration-example).
exports.handler = function(event, context) {
// This Lambda function returns a flag to indicate if a user should be auto-confirmed.
// Perform any necessary validations.
// Impose a condition that the minimum length of the username of 5 is imposed on all user pools.
if (event.userName.length < 5) {
var error = new Error('failed!');
context.done(error, event);
}
// Access your resource which contains the list of emails of users who were invited to sign up
// Compare the list of email IDs from the request to the approved list
if(event.userPoolId === "yourSpecialUserPool") {
if (event.request.userAttributes.email in listOfEmailsInvited) {
event.response.autoConfirmUser = true;
}
}
// Return result to Cognito
context.done(null, event);
};
Here is what I did to create a "staging" environment User Pool in AWS Cognito that does not send real notifications to users. There were actually a couple different pieces involved, but I think I was able to get everything covered. That being said, it would sure be nice if Cognito simply provided a User Pool setting to turn off all notifications, that way I don't have to write environment specific logic into my code.
Prevent User Invitations
In our app we use the AdminCreateUser function to create users who get invited by other users. This function will normally send an invitation message to the new user's phone number or email. In order to prevent those invitations, you can provide MessageAction: 'SUPPRESS' as a parameter to the function arguments. Like so:
let params = {
UserPoolId: config.cognitoUserPoolId,
Username: uuid.v4(),
MessageAction: 'SUPPRESS', /* IMPORTANT! */
TemporaryPassword: user.phone_number.slice(-6),
UserAttributes: [
{ Name: 'given_name', Value: user.first_name },
{ Name: 'family_name', Value: user.last_name },
{ Name: 'phone_number', Value: user.phone_number }
]
};
cognito.adminCreateUser(params).promise().then(data => {
console.log(data);
});
Official docs for that here: http://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminCreateUser.html
Prevent User Attribute Update Verfications
In our production app, we want users to have to re-verify their phone number or email if it changes. But in our staging environment we don't actually need this. So uncheck the boxes for email and phone under the "Do you want to require verification of emails or phone numbers?" section in your User Pool settings.