I generated token with JWT using node and angular, and can't check if user is authorized.
Node:
module.exports.authenticate = function(req, res) {
var user = new User(req.body);
User.findOne({
username: req.body.username
}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({ success: false, message: 'Authentication failed. User not found.' });
}
else if (user) {
if (user.password != req.body.password) {
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
}
else {
var token = jwt.sign(user, config.secret, {
expiresIn: 60*60*24
});
res.json({
success: true,
token: token
});
}
}
});
};
Angular:
$http(req)
.then(function (response) {
console.log(response.data.success);
if(response.data.success) {
var user = localStorage.setItem('token', JSON.stringify(response.data));
token = localStorage.getItem('token');
// console.log('User info: ', JSON.parse(getuser));
// window.location = "/dashboard";
return response.data;
}
}, function (response) {
}
);
}
How can I check token when I change route?
And generically how can I use Token?
Angular ui-router provides $routeChangeStart event while you change a route. You can use it in the following way.
$rootScope.$on('$routeChangeStart', function (event, next, current){
//you can code here something to be run on changing routes
}
You might want to have a look here for detailed event documentation.
Regarding a more generic implementation , you can create a service to keep your token at the time of login or whenever you get it. Thereafter you can keep getting the token from the service for any future comparisons.
you should install "cookie-parser"
npm i cookie-parser
and go to index.js file and add
const cookieParser = require('cookie-parser');
app.use(cookieParser());
it works for me
Related
I'm attempting to use Amazon Passport in my MEAN application for authentication, but I'm running into a cross origin error. My application is set up like this:
View:
<a id="LoginWithAmazon" ng-click="vm.auth()">
<img class="responsive-img amazon-button"/>
</a>
Controller:
vm.auth = function () {
Auth.login()
.then(function () {
$location.path('/');
})
.catch(function (err) {
vm.error = err;
});
}
Service:
vm.login = function () {
var deferred = $q.defer();
$http.post('/auth/amazon')
.then(function (res) {
console.log('SUCCESS! ', res);
deferred.resolve();
})
.catch(function (err) {
console.log('ERR: ', err);
deferred.reject(err.data);
});
return deferred.promise;
};
And in my Express/NodeJS context...
Passport is configured like this:
passport.use(new AmazonStrategy({
clientID: config.amazon.clientID,
clientSecret: config.amazon.clientSecret,
callbackURL: "http://localhost:9000/test"
},
function(accessToken, refreshToken, profile, done) {
console.log('SUCCESS AUTH: ', profile);
process.nextTick(function() {
return done(null,profile);
});
});
}
));
Express route:
router.post('/auth/amazon', function (req, res, next) {
passport.authenticate('amazon', function (err, user, info) {
console.log('Err? ', err);
console.log('User: ', user);
})(req, res, next);
});
When I try to make the authentication request, I am getting the following error:
I've tried using Login with Amazon but to no avail as well. I've whitelisted http://localhost:9000 on Login with Amazon's configuration. Any help would be greatly appreciated.
Looks like you make an AJAX request to an endpoint you should redirect (302) to. The endpoint possibly contains a login page and the user should be able to see it and use it.
Make sure you follow the oauth specs and you don't issue an AJAX request prematurely. The protocol requires you first redirect to their login page and then, only when you have the one-time code, you issue an AJAX request to exchange the code for an access token.
I create a jwt token and stored in database. when login successfully done i want to redirect to home page with token. how could i do that.
My Nodejs file.
app.post('/authenticate', function(req, res, next) {
User.findOne({name: req.body.name}, function(err, user) {
if (err) {throw err;}
if (!user) {
res.json({ success: false, message: 'Authentication failed. User not found.' });
} else if (user) {
// check if password matches
if (user.password !== req.body.password) {
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
} else {
// if user is found and password is right
// create a token
var token = jwt.sign(user, app.get('superSecret'), {
expiresIn: 1440 // expires in 24 hours
});
// return the information including token as JSON
res.json({
success: true,
message: 'Enjoy your token!',
token: token
});
}
}
});
});
My angularjs file
var app = angular.module('loginApp', []);
// Controller function and passing $http service and $scope var.
app.controller('loginCtrl', function($scope, $http) {
// create a blank object to handle form data.
$scope.user = {};
// calling our submit function.
$scope.submitForm = function() {
// Posting data to file
$http.post('/tokken/login/', $scope.user).then(function (response) {
//$http.defaults.headers.common['Token'] = token
if (response.errors) {
// Showing errors.
$scope.errorName = response.errors.name;
$scope.erroPassword = response.errors.password;
} else {
$scope.message = response.data;
}
});
};
});
I print token value in same login page. I want to redirect to another page with the token
I'm very new to angular, so my knowledge is based on tutorials and even then I don't succeed.
I need to authenticate using a google account. That works, I get a token where my api calls could be authorized with. But after login the pop up window should dismiss and I should be redirected to the homepage. This doesn't work.
this is my controller
angular.module('MyApp').controller('loginController', ['$scope', '$auth', '$location','loginService', loginController]);
function loginController($scope, $auth, $location, loginService) {
$scope.authenticate = function(provider) {
$auth.authenticate(provider).then(function(data) {
loginService.saveToken(data.data.token);
console.log('You have successfully signed in with ' + provider + '!');
$location.path('http://localhost/#/home');
});
};
};
in app.js I have my configuration. this is not my work but a friend who is an intern as wel as me, he is responsible for a mobile application, where he uses the same function to get his token, and it works.
authProvider.google({
clientId: CLIENT_ID,
redirectUri: 'http://localhost:3000/api/users/signIn'
});
$authProvider.storage = 'localStorage'; // or 'sessionStorage'
$authProvider.loginRedirect = 'http://localhost/#/home';
This is the controller in node where the url is redirected to (google developer console)
router.get('/signIn', function(req, res) {
//console.log(req);
var code = req.query.code;
oauth2Client.getToken(code, function(err, tokens) {
if (!err) {
https.get("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=" + tokens.access_token, function(response) {
// Continuously update stream with data
var body = '';
response.setEncoding('utf8');
response.on('data', function(d) {
body += d;
});
// Data fetched
response.on('end', function() {
var parsed = JSON.parse(body);
// Check if client_id is from the right app
if (parsed.issued_to == '343234242055-vd082vo0o8r8lmfvp1a973736fd98dht.apps.googleusercontent.com') {
User.getGoogleId(parsed.user_id, function(err, user) {
if (err) {
res.status(500).send({
message: 'not authorized app'
});
}
// No user returned, create one
if (!user) {
// Request user info
oauth2Client.setCredentials(tokens);
plus.people.get({
userId: 'me',
auth: oauth2Client
}, function(err, plusUser) {
if (err) res.status(500).send({
message: 'not authorized app'
});
else {
// Create new user
User.create(plusUser.name.givenName, plusUser.name.familyName, (plusUser.name.givenName + "." + plusUser.name.familyName + "#cozmos.be").toLowerCase(), parsed.user_id, function(err, newUser) {
if (err) res.status(500).send({
message: 'not authorized app'
});
else {
res.statusCode = 200;
return res.send({
response: 'Success',
id: user._id,
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
token: tokens.access_token
});
}
});
}
});
} else {
// Return user
res.statusCode = 200;
return res.send({
response: 'Success',
id: user._id,
firstName: user.firstName,
lastName: user.lastName,
email: user.email,
token: tokens.access_token
});
}
});
}
// if not right app, return unauthorized response
else {
res.status(500).send({
message: 'not authorized app'
});
}
});
});
}
});
});
So I login, I get asked to give permission to the application to use my account info, I get a json response where I can see my name, email and token, and that's it
Even within the company where I work, no one could find an answer. So I came with a solution myself. I don't use satellizer anymore.
.when('/access_token=:access_token', {
template: '',
controller: function($window, $http, $location, $rootScope) {
var hash = $location.path().substr(1);
var splitted = hash.split('&');
var params = {};
for (var i = 0; i < splitted.length; i++) {
var param = splitted[i].split('=');
var key = param[0];
var value = param[1];
params[key] = value;
$rootScope.accesstoken = params;
}
console.log(params.access_token);
var json = {
Token: params.access_token
};
$window.localStorage['token'] = params.access_token;
$http.post('http://localhost:3000/api/users/signIn', json).success(function(data, status) {
console.log(data);
}).error(function(err) {
console.log(err);
});
$location.path("/home");
}
/*controller: 'createNewsFeed',
templateUrl: 'homepage.html'*/
}).
So redirect the page by itself. Because the authentication works on the backend side, I can get a access token, which is the only thing I really need for future use of my rest api. I defined a route where, after receiving the json with the token, my browser is manually redirected to with $window.location. So when that page is loaded (not visible for the user, it goes too fast to notice) I analyse the token, save the token, analyse authentication, when that is successful I manually redirect to the homepage.
I'm working on basic authentication for my project in node.js using passport.js and it's LocalStrategy method. It's even without password validation yet. Accounts are stored in MongoDB instance.
I was stuck for whole day when in course I'm going through instructor recommended binding form data to angular and sending $http.post() from there, like so:
$scope.signIn = function (username, password) {
$http.post('/login', {username: username, password: password})
.then(function (res) {
if(res.data.success) {
console.log('Logged in');
} else {
console.log('error logging in');
}
})
};
And here's the route for it:
app.post('/login', function (req, res, next) {
var auth = passport.authenticate('local', function (err, user) {
if(err) { return next(err); }
if(!user) { res.send({success: false, user: user}); }
req.login(user, function (err) {
if(err) { return next(err); }
res.render('index', { success: true, user: user });
});
});
auth(req, res, next);
});
Except it ALWAYS returned with { success: false, user: false }. After ton of googling I've decided to make a POST request directly from form:
JADE:
.navbar-right(ng-controller='navbarLoginCtrl')
form.navbar-form(action='/login' method='post')
.form-group
input.form-control(name='username' placeholder='username', ng-model='username' required)
.form-group
input.form-control(name='password' type='password', placeholder='password', ng-model='password' required)
button.btn.btn-default(type='submit' value="Submit") Sign in
as opposed to:
.navbar-right(ng-controller='navbarLoginCtrl')
form.navbar-form
.form-group
input.form-control(name='username' placeholder='username', ng-model='username' required)
.form-group
input.form-control(name='password' type='password', placeholder='password', ng-model='password' required)
button.btn.btn-default(ng-click='signIn(username, password)') Sign in
Submit approach actually works but i'd like to keep things clean and do it with angular.
How can I do it?
Other passport.js components for reference:
var User = mongoose.model('User');
passport.serializeUser(function (user, done) {
if (user) {
done(null, user._id);
}
});
passport.deserializeUser(function (id, done) {
User.findOne({_id: id}).exec(function (err, user) {
if(user) {
return done(null, user);
} else {
return done(null, false);
}
});
});
passport.use(new LocalStrategy(
function (username, password, done) {
User.findOne({username: username}, function (err, user) {
if (user) return done(null, user);
else return done(null, false);
});
}
));
You should check what your browser send.
Your broswer form send data in the form username=&password=, angular post them in JSON {username:, password:} and the Content-Type header is different.
If you want to do the same in angular :
var headers={ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'};
return $http.post(BackEndpoint+'/login','username='+username+'&password='+password,
{headers:headers}).then(function(result){
});
This is what i use against spring authentication.
I'm using the passport module to authenticate a user and generate a jwt token.
Now I want to make facebook login possible. I'm in the phase that I get a fb token and facebook id.
What am I supposed to do with this info? Currently I make a new user that has a variable with facebook id but without a password.
Without a password I can't generate a jwt token, thus I cannot login.
How does this work?
My front end is angular and my API is written with nodejs, express & mongoose.
Passport code:
passport.use(new LocalStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect password.' });
}
return done(null, user);
});
}
));
generatejwt code:
UserSchema.methods.generateJWT = function() {
// set expiration to 60 days
var today = new Date();
var exp = new Date(today);
exp.setDate(today.getDate() + 60);
return jwt.sign({
_id: this._id,
username: this.username,
exp: parseInt(exp.getTime() / 1000),
}, 'SECRET');
};
You need to create 2 routes :
1) This will be called to login to facebook.
2)Callback route if the user authentication is successful.(This callback route needs to be registered in the facebook developer portal.
//Facebook Login
app.route('/auth/facebook')
.get(passport.authenticate('facebook', { scope: 'email' }));
// Callback
app.route('/auth/facebook/callback')
.get(passport.authenticate('facebook'),users.generateJWT);
Define a facebook strategy that will store the user details (id, token, email) in your database
var facebookStrategy = new FacebookStrategy({
clientID: cfg.facebook.clientID,
clientSecret: cfg.facebook.clientSecret,
callbackURL: cfg.facebook.callbackURL,
profileFields: ['id', 'email', 'first_name', 'last_name']
},
function(token, refreshToken, profile, done) {
console.log("Token: "+ token);
console.log("RefreshToken: "+ refreshToken);
console.log("profile: "+ profile);
process.nextTick(function() {
User.findOne({ 'facebook.id': profile.id }, function(err, user) {
if (err)
return done(err);
if (user) {
console.log("User Found");
return done(null, user);
} else {
console.log("Creating user");
var newUser = new User();
console.log("Token: "+ token);
newUser.facebook.id = profile.id;
newUser.facebook.token = token;
newUser.facebook.name = profile.name.givenName + ' ' + profile.name.familyName;
newUser.facebook.email = (profile.emails[0].value || '').toLowerCase();
newUser.save(function(err) {
if (err)
throw err;
return done(null, newUser);
});
}
});
});
});
In the controller, write the below code for callback route:
/**
* Generate JWT Token
*/
exports.generateJWT = function(req, res) {
var token;
token = req.user.generateJwt();
res.status(200);
res.json({
"token" : token
});
};