I am trying to make a custom authentication flow using AWS Cognito so that i can send MFA codes via email instead through the cognito triggers. I am using the initiateAuth() method to do this which is correct according to the documentation;
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#initiateAuth-property
My payload seems to be valid but when i try login with a user i get the error 't.getauthparameters is not a function'
I've had a look through some other stackoverflow posts but nothing is helping
Any ideas what is going wrong?
This is a snippet from my code below:
const payload = {
AuthFlow: 'CUSTOM_AUTH',
ClientId: 'my client id',
AuthParameters: {
USERNAME: $('input[name=username]').val(),
PASSWORD: $('input[name=password]').val(),
CHALLENGE_NAME: 'SRP_A'
}
};
cognitoUser.initiateAuth(payload, {
onSuccess: function(result) {
// User authentication was successful
},
onFailure: function(err) {
// User authentication was not successful
},
customChallenge: function(challengeParameters) {
// User authentication depends on challenge response
var verificationCode = prompt('Please input OTP code' ,'');
cognitoUser.sendCustomChallengeAnswer(verificationCode, this);
},
});
So i ended up finding out that initiateAuth() is not the correct method to use.
The right method to use is cognitoUser.authenticateUser() (since i am using SRP-based authentication then adding a custom challenge) - My updated code is below
This was a similar example that i followed to help me find the answer
I couldnt find very much online for doing it with just the Amazon Cognito Identity SDK so hopefully this is helpful for anyone doing the same!
AWSCognito.config.region = 'region';
var poolData = {
UserPoolId : 'user pool id',
ClientId : 'client id'
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username: $('input[name=username]').val(),
Pool: userPool,
};
var authenticationData = {
Username : $('input[name=username]').val(),
Password : $('input[name=password]').val(),
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.setAuthenticationFlowType('CUSTOM_AUTH');
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(result) {
console.log('success');
var resultStr = 'Login Successful';
console.log(resultStr);
$('#resultsSignIn').html(resultStr);
},
onFailure: function(err) {
alert(err);
},
customChallenge: function(challengeParameters) {
// User authentication depends on challenge response
var verificationCode = prompt('Please input OTP code' ,'');
cognitoUser.sendCustomChallengeAnswer(verificationCode, this);
},
});
return false;`
A downside to the authenticateUser() method is that you won't be able to get user's input mid-execution during the authenticateUser workflow (i.e, having to use prompts in the callbacks for customchallenge etc). I believe initiateAuth() would solve this issue.
https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-define-auth-challenge.html
Related
If I click the "reset password" button for a user in the AWS Cognito, all it does is re-send the verification email, containing the account registration email code.
However, if the user takes that code and enters it on the verification page, AWS returns the error:
NotAuthorizedException: User cannot be confirmed. Current status is RESET_REQUIRED
First, how do I get Cognito to send a real "password reset" email instead of the "confirm your registration" email?
I assume it's giving me this error because the verification JS is calling:
createCognitoUser(email).confirmRegistration(code, true, function confirmCallback(err, result)
and not some undocumented password reset function. What function should I be calling?
You should be calling forgotPassword. From the AWS Documentation at Using Amazon Cognito User Identity Pools Javascript Examples:
cognitoUser.forgotPassword({
onSuccess: function (result) {
console.log('call result: ' + result);
},
onFailure: function(err) {
alert(err);
},
inputVerificationCode() {
var verificationCode = prompt('Please input verification code ' ,'');
var newPassword = prompt('Enter new password ' ,'');
cognitoUser.confirmPassword(verificationCode, newPassword, this);
}
});
So Even I faced a same issue, Even in AWS cognito documentation it was not clear, basically the process involves two steps.
call cognitoUser.forgotPassword() this will start forgot password process flow, and the user will receive a verification code.
then call cognitoUser.confirmPassword() which will reset the password verifying the code send to the email of user.
Below I have given a cognitoUserClass which has static methods forgotPassword() and confirmPassword() methods which implements those two steps.
import * as AmazonCognitoIdentity from 'amazon-cognito-identity-js'
class cognitoUserClass {
static cognitouser: AmazonCognitoIdentity.CognitoUser
static userPool = new AmazonCognitoIdentity.CognitoUserPool({
UserPoolId: 'your pool id',
ClientId: 'your client id',
})
static forgotPassword(userName: string): void {
const userData = {
Username: userName,
Pool: cognitoUserClass.userPool,
}
cognitoUserClass.cognitouser = new AmazonCognitoIdentity.CognitoUser(
userData
)
cognitoUserClass.cognitouser.forgotPassword({
onSuccess: (data) => {
console.log(data)
},
onFailure: (err) => {
console.log('ERR:', err)
},
})
}
static confirmPassword(
verificationCode: string,
newPassword: string
): void {
cognitoUserClass.cognitouser.confirmPassword(
verificationCode,
newPassword,
{
onFailure(err) {
console.log(err)
},
onSuccess(data) {
console.log(data)
},
}
)
}
}
export { cognitoUserClass }
I tried to create a phone authentication using firebase and Angular. After setting recaptcha verifier and phone number and passed to firebase.auth.signInWithPhoneNumber() function. It returns only the verification Id and not verification code and it not sending sms to my number as well.
onSignInSubmit(phoneNumber) {
this.recaptcha = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
'size' : 'invisible',
'callback': function(response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
}
});
this.afauth.auth.signInWithPhoneNumber(phoneNumber, this.recaptcha).then((confiramtionResult) => {
console.log(confiramtionResult);
});
}
You have to ask the user for the SMS code.
After the user provides it, you call:
var code = getCodeFromUserInput();
confirmationResult.confirm(code).then(function (result) {
// User signed in successfully.
var user = result.user;
// ...
}).catch(function (error) {
// Error occurred.
});
I'm doing my app users management with the Cognito AmazonWebService and on AngularJS.
I can not figure out how to solve this problem :
After registering, users are receiving an email with a code to confirm it. When I try to enter and validate the code I have a pop-up message saying "Error: the user is not authenticated".
But if is I swap the steps I can not authenticated myself because I've this error: "Your account must be confirmed".
EDIT: That's how I'm confirming the registration :
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(_poolData);
var userData = {
Username : username,
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.getAttributeVerificationCode('email', {
onSuccess: function (result) {
console.log('call result: ' + result);
},
onFailure: function(err) {
console.log("error");
alert(err);
},
inputVerificationCode: function(code) {
var verificationCode = prompt('Check you email for a verification code and enter it here: ' ,'');
cognitoUser.verifyAttribute('email', verificationCode, this);
}
});
I have also try this code below :
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.confirmRegistration('123456', true, function(err, result) {
if (err) {
alert(err);
return;
}
console.log('call result: ' + result);
});
But everytime I'm using the code you gave me to confirm an user I have this error message : "ExpiredCodeException: Invalid code provided, please request a code again." while user is well confirmed in my user pool...
How could I solve it ?
Your second code is the right one to be called. How long are you waiting to call?
I have the following code ran on the client-side to access the properties of a user within the database.
firebaseAUTH.signInWithEmailAndPassword(email, password).then(function (user) {
console.log('user has signed in with e-mail address: '+user.email+' and user ID: '+user.uid)
firebaseAUTH.currentUser.getToken(true).then(function(idToken) {
$.ajax(
{
// Send token to your backend via HTTPS (JWT)
url: '/auth',
type: 'POST',
data: {token: idToken},
success: function (response){
var userID = response.userID
firebase.database().ref('/users/' + userID).once('value').then(function(snapshot) {
var industry = snapshot.val().industry
var company = snapshot.val().company
var firstname = snapshot.val().firstname
var email = snapshot.val().email
var source = snapshot.val().source
var phone = snapshot.val().phone
var password = snapshot.val().password
var lastname = snapshot.val().lastname
$.get(
{
url: '/members-area/'+userID,
data: {userID: userID,
industry: industry,
email: email},
success: function(response){
window.location = '/members-area/'+userID
}
})
My server-side code:
app.get('/members-area/:userID', function(req,res,next) {
res.render('members-area', { userID: req.params.userID, industry: req.params.industry, email: req.params.email})
})
However, when I try to access the 'industry' variable in pug, it shows undefined. As you can see I send it above within the GET ajax call so what is the problem? It's also weird because I logged to the console the variables names'right after the function snapshot and they were there. Also, mysteriously 'userID' shows up as a var with content but 'industry' and 'email' do not at all.
I don't quite know what you're trying to do but hopefully I can help some.
First off you don't need a second call to get the token. When you call signInWithEmailAndPassword firebase returns the user. So you can call getToken right away
firebaseAUTH.signInWithEmailAndPassword(email, password).then(function (user) {
console.log('user has signed in with e-mail address: '+user.email+' and user ID: '+user.uid)
console.log('we also got the token: ' + user.getToken());
...
You also seem to be posting to a route that isn't defined, and then you query a different route with get.
Also, mysteriously 'userID' shows up as a var with content but
'industry' and 'email' do not at all.
In your server side code your route is only defined with one parameter: userID. The line
app.get('/members-area/:userID', function(req,res,next)
Defines userID as a parameter, not the other 2 variables. So it makes sense that they're undefined.
What I think you're trying to do is:
firebaseAUTH.signInWithEmailAndPassword(email, password).then(function (user) {
const userId = user.getToken();
firebase.database().ref('/users/' + userID).once('value').then(function(snapshot) {
$.post('/members-area/' + userId, snapshot.val(), function(data, status) {
console.log(data);
console.log(status);
});
});
And then in your server code:
app.post('/members-area/:userID', function(req,res,next) {
const theSnapshot = req.body;
res.send(theSnapshot)
});
I still don't understand why you would want to retrive information using client code from a database and then post it a server only to get it again. But maybe I am misunderstanding something :)
Its also very strange to see a get request that sends data, I'm pretty sure its against the specs. You usually want to use post to send data and then use get to ehm get the data :)
I'm trying doing the following: I have a local database (using PouchDB), I check if user is logged in (with pouchdb-authentication login function) and if true I sync the locale db with the remote one.
Unfortunately, when I try to create a new database on CouchDB (I want one db for every user) I always get the error {"error":"not_found","reason":"no_db_file"}. I saw this is a common error described in PouchDB documentation (https://pouchdb.com/guides/databases.html#remote-databases) but CORS is enabled and I can't figure out where is the problem.
My couchdb configuration is:
I do the login as follow:
var user = {
name: 'name',
password: 'password'
};
var url = "http://ip/";
var pouchOpts = {
skipSetup: true
};
var ajaxOpts = {
ajax: {
headers: {
Authorization: 'Basic ' + window.btoa(user.name + ':' + user.password)
}
}
};
var db = new PouchDB(url+'auth', pouchOpts);
db.login(user.name, user.password, ajaxOpts).then(function() {
return db.allDocs();
}).then(function(docs) {
//HERE I TRY TO CREATE THE NEW DATABASE
pouchDBService.sync(url+"newDatabase", user);
}).catch(function(error) {
console.error(error);
});
And, in my pouchDBService I have:
var database;
//I call this function as app starts
this.setDatabase = function(databaseName) {
database = new PouchDB(databaseName, {
adapter: 'websql'
});
}
this.sync = function(remoteDatabase, user) {
var remoteDB = new PouchDB(remoteDatabase, {
auth: {
username: user.name,
password: user.password
},
skip_setup: true //without this I get the login popup! Why if I'm passing the auth params???
});
remoteDB.info().then(function (info) {
console.log(info);
database.sync(remoteDB, {live:true, retry: true})
})
}
Is there something wrong? Any help is appreciated.
Thanks
To create databases on the CouchDB server, you need to be an admin. You could create a small custom API on the server for this (e.g. with a small node http server), or use the couchperuser plugin for CouchDB.