Network error when authenticating user with AWS Cognito - reactjs

I'm trying to incorporate Cognito authentication into my React based project. My code is based on examples given in NPM page. This is what it looks like :
var authenticationData = {
Username : 'username',
Password : 'password',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : '...', // Your user pool id here
ClientId : '...' // Your client id here
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('Successfully logged!');
}
});
},
onFailure: function(err) {
console.log(JSON.stringify(err));
},
});
I have created a user pool and added an app client. I have also enabled identity provider for app client. However, my code fails to authenticate with error {"code":"NetworkError","name":"Error","message":"Network error"}. Since my project is still hosted on a localhost, I have installed CORS plug-in for firefox, but that doesn't resolve the issue. I couldn't make much sense out of this error message. I have double checked Cognito region, pool id and client id. They all set to correct values. Does anyone familiar with this error and have an idea what maybe causing this?

A bit late, but I had exactly the same error today and it took me a while to figure it out. This happens when the automatic refresh occurs after a submit. This prevents the API call to AWS Cognito to finish resulting in a network error.
Before starting the cognito function, add a event.preventDefault(); to your code.
For example, I do this in my addEventListener:
document.querySelector("#authCognito").addEventListener("click", function(){
var username = document.getElementById("userInput").value;
var password = document.getElementById("passInput").value;
var authenticationData = {
Username: username,
Password: password,
};
event.preventDefault();
cognitoAuthenticate(authenticationData);
});

I had the same issue, the following is the fix in Vue
<template>
<button v-on:click="login($event)" class="btn btn-default btn-large">login</button>
</template>
<script>
methods: {
login (event) {
if (event) {
event.preventDefault()
}

Related

How can I check if user is already Logged in using aws cognito user pool anywhere in project?

I am doing SSO(Single Sign On) in my application. I am making use of AWS cognito for it and user pool and Identity pool for users.
I have setup user pool, identity pool and using hosted UI.
When I am using Custom UI for login and calling below cognito function:
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
var accessToken = result.getAccessToken().getJwtToken();
AWS.config.region = config.region;
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : config.IdentityPoolId, // your identity pool id here
Logins : {
'cognito-idp.<region>.amazonaws.com/<pool-id>': result.getIdToken().getJwtToken()
}
});
//refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
AWS.config.credentials.refresh((error) => {
console.log("in refresh");
if (error) {
console.error(error);
} else {
console.log('Successfully logged!');
}
});
},
onFailure: function(err) {
console.log("in failure");
alert(err.message || JSON.stringify(err));
},
mfaRequired: function(codeDeliveryDetails) {
// MFA is required to complete user authentication.
// Get the code from user and call
console.log("in mfa required");
cognitoUser.sendMFACode(mfaCode, this)
}
});
This works fine but I am not able to redirect user to routes on successful and failure.
I want to use hosted UI.
Now I am able to successfully authenticate user from hosted UI and redirect to URL provided in app client settings callback URL. And getting id_token, access_token in url. I am able to decode it and get username from that.
But when I do:
var AmazonCognitoIdentity = require('amazon-cognito-identity-js');
var userPool = new AmazonCognitoIdentity.CognitoUserPool(config.poolData);
console.log("cog user: ", userPool.getCurrentUser());
I get null.
Is there any way to get current logged in user So that I can identify if user is logged in or not and do next operations accordingly.

Reactjs AWS Cognito - How to Handle newPasswordRequired

I'm using AWS Cognito Javascript SDK in a react application. I have a user that was created in the AWS Console by an admin. The user recieves an email with their username and temporary password. Now based on my understanding, I have to go through the newPasswordRequired flow, but I have been struggling with this for several hours now trying multiple different approaches and none are getting me anywhere. When I check the AWS Console, the user in the user pool is set to FORCE_CHANGE_PASSWORD.
Here is my code in its current state. Please if someone can help me solve the process as I am fairly new to using Cognito authentication.
function setNewPassword(data) {
console.log("data \n", data)
var authenticationData = {
Username: data.username,
Password: data.temp_password
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(
authenticationData
);
var userPool = new AmazonCognitoIdentity.CognitoUserPool(config.cognito);
var userData = {
Username: data.username,
Pool: userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
return new Promise(function(resolve, reject) {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(result) {
resolve(resolve);
},
onFailure: function(err) {
reject(err);
},
newPasswordRequired: function(userAttributes, requiredAttributes) {
this.cognitoUser.completeNewPasswordChallenge(newPassword, attributesData, this)
}
});
});
}
In the browser console, I am getting the following error:
{code: "UnknownError", message: "Unkown error"}
Have you looked at using the AWS Amplify JS library for help here? There's a suite of React components already built to help with these sorts of things. Here's a link to the relevant documentation. The code is open sourced on GitHub and you might be able to just use the RequireNewPassword component, or at least find inspiration from it.

callback missmatch error in angular with auth0

Hi I'm using Auth0 with Nodejs and angularjs
here is what i want to achieve
1. I want to user to signup using auth0's lock
2. as soon as user logs in a callback should be called at my nodejs server
3. after that i will get the user information and user's JWT
4. then i will redirect user to dashboard page and store the JWT in browser
What's the problem with Auth0's example
1. they provide example either for angular or nodejs standalone not the combined
2. there is combined(client server) example but that's using jade with nodejs
my code snipped
Angular snipped
var options = { auth: {
redirectUrl: 'http://localhost:3000/callback'
, responseType: 'code'
, params: {
scope: 'openid name email picture'
}
}
}
lockProvider.init({
clientID: 'cUlBNhhaIblahBlahRp6Km',
domain: 'rishabh.auth0.com',
option:options
});
node snipped
router.get('/callback',
passport.authenticate('auth0', { failureRedirect: '/url-if-something-fails' }),
function(req, res) {
console.log(req.user);
res.json({id_token:req.user});
});
Note: I've added this callbacks in auth0
http://localhost:3000/callback
but dont know why I'm facing this error for callback error when I've mentioned my redirect URL in angular side
can anyone tell me what is the problem with my code why auth0 not redirecting me to this url http://localhost:3000/callback
and the interesting thing is when i use simple lock.js instead of angular like this
<script>
var options = { auth: {
redirectUrl: 'http://localhost:3000/callback'
, responseType: 'code'
, params: {
scope: 'openid name email picture'
}
}
}
var lock = new Auth0Lock('clientID', 'rishabh.auth0.com',options);
lock.show();
</script>
then in this case my nodejs /callback route is called properly, so what I'm doing wrong with angular ?
please help
Update
this is my project structure
full code
https://github.com/LabN36/error
Config.js
var Auth0Strategy = require('passport-auth0');
var passport = require('passport');
var strategy = new Auth0Strategy({
domain: process.env.AUTH0_DOMAIN || 'rishabh.auth0.com',
clientID: process.env.AUTH0_CLIENT_ID || 'cUheWwRxm7OLdHBRzlBNvfvfvfvfvhhaI1lxRp6Km',
clientSecret: process.env.AUTH0_CLIENT_SECRET || 'e37eIZpjgBnDMBtrYMwvffvfvfvfaU4jSqt8qylZMT9Oj1EiffLGViinWQ5AiuWi1-WBwA8v3',
callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'
}, function(accessToken, refreshToken, extraParams, profile, done) {
// accessToken is the token to call Auth0 API (not needed in the most cases)
// extraParams.id_token has the JSON Web Token
// profile has all the information from the user
console.log(extraParams.id_token);
//save user detail with token here and return token only profile
return done(null, extraParams.id_token);
});
passport.use(strategy);
// you can use this section to keep a smaller payload
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
module.exports = passport;
AngularApp.js
angular.module('workApp',['auth0.lock'])
.config(function($locationProvider,lockProvider){
var options = { auth: {
// redirect:true,
responseType: 'code',
redirectUrl: 'http://localhost:3000/callback',
params: {
scope: 'openid name email picture'
}
}
}
lockProvider.init({clientID: 'cUheWwRxm7OLdHBRzlBNhhaI1lxRp6Km',domain: 'rishabh.auth0.com',
option:options
});
$locationProvider.html5Mode(true);
})
.controller('homeCtrl',function($scope,$http,$location,$window,lock){
$scope.login = function() {
// window.alert("magic")
console.log("Messed Up really")
var vm = this;
vm.lock = lock;
lock.show();
}
}).run(function(lock){
lock.interceptHash();
lock.on('authenticated', function(authResult) {
localStorage.setItem('id_token', authResult.idToken);
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
console.log(error);
}
localStorage.setItem('profile', JSON.stringify(profile));
});
});
})
According to the screenshot the error happens because the authentication request is made with a redirect_uri of:
http://localhost:3000/
and the allowed callback URL's are:
http://localhost:3000/callback
http://35.162.118.253:3000/callback
Also based on the code you shared you're indeed setting the redirectUrl to be http://localhost:3000/callback so there may be something on the rest of the code that either causes that value to be overridden or not used at all.
If the redirectUrl is not set, Lock will use the current page so the likely culprit is that the options you set are not being used. If you still don't find the cause for this, update the question with the code associated with how Lock is shown.
Damn, the actual root cause was already shown in the code you initially provided, but only looking now at the full code made it possible for me to catch it...
You're calling lockProvider.init() with:
{ clientID: [?], domain: [?], option: options }
when it should be called with:
{ clientID: [?], domain: [?], options: options } // options instead of option

howto prevent www-authenticate header when using passport-http Basic + passport-local combination

Hi I want to support both formbased authentication and http basic authentication in my app. Everything works as expected except when I use form based auth via angularjs with wrong credentials.
Instead of having my angular code handle the 401, the browser shows the BASIC auth dialog, caused by the WWW-Authenticate header.
How can I prevent that header from being added when the local strategy is used?
Or how can I support both mechanisms in a different way?
I use the following route in my express based app.
api.post('/authenticate', passport.authenticate(['local', 'basic'], { session: false }), function (req, res) {
This enables both authentication methods on that url. I repeat, when I use wrong credentials using formbased it shows me the basic auth dialog (I don't want that).
Following is how I registered the strategies.
passport.use(new BasicStrategy({ realm: 'Authentication failed. Wrong username or password.'}, verifyLocalUser));
passport.use(new LocalStrategy(verifyLocalUser));
This is how my verifyUser method looks like...
var verifyLocalUser = function (username, password, next) {
User.findOne({
username: username
}).select('fullname admin username password').exec(function (err, user) {
if (err) {
return next(err);
}
if (user && user.comparePasswords(password)) {
return next(null, user);
} else {
next(null, false, { message: 'Authentication failed. Wrong username or password.' });
}
});
}
Does anyone know how to support multiple authentication methods using passport.js?
For completeness, this is the angular code which authenticates me...
authFactory.signIn = function (username, password) {
return $http.post('/api/authenticate', {
username: username,
password: password
}).then(function (res) {
AuthToken.setToken(res.data.token);
return res.data;
}, function (res) {
console.warn(res);
});
};
instead of this:
next(null, false, { message: 'Authentication failed. Wrong username or password.' });
You can use this:
cb(new YourCustomError())
And "YourCustomError" can have a message, for me mine "YourCustomError" looks like:
class HttpError extends Error {
constructor (msg = 'Invalid Request', status = 400) {
super(msg)
this.status = status
}
}
class Forbidden extends HttpError {
constructor (msg = 'Forbidden') {
super(msg, 403)
}
}
Or probably new Error(<message>) will work properly for you, too

Firebase createUser() does not return id of created user

I'm using Firebase 1.1 (which embeds old firebase-simple-login functionalities).
Now, when creating a user, how do I get it's id (or uid)?
app.controller('AuthCtrl', function ($scope, $firebase) {
var ref = new Firebase(MY_FIREBASE_URL);
ref.createUser({
email: 'mary#mail.com',
password: 'her-super-secret-password'
},
function(err) {
switch (err.code) {
...
}
}
}
As far as I can understand, createUser function callback only reports an err object in case of error. But - in case of success - I need the created user id (or better uid), to use it to add the user to my internal users profiles...
How do I get created user id from Firebase createUser ?
UPDATE:
I did just give up with 1.1, reverting to 1.0 until some more docs are available (or some answer I get...) :-(
Firebase recently released an updated JavaScript client (v2.0.5) which directly exposes the user id of the newly-created user via the second argument to the completion callback.
Check out the changelog at https://www.firebase.com/docs/web/changelog.html and see below for an example:
ref.createUser({
email: '...',
password: '...'
}, function(err, user) {
if (!err) {
console.log('User created with id', user.uid);
}
});

Resources