Trying to make an admin panel where the admin user can create passwords for the access page. You'll need the password to access the login/register page. I've been trying to make this with json web tokens. I've used the MEAN-stack for this:
access Schema
var accessSchema = new mongoose.Schema({
password: String
});
create jwt
function createAccessToken(password) {
var payload = {
sub: password._id,
iat: moment().unix(),
exp: moment().add(7, 'days').unix()
};
return jwt.encode(payload, config.ACCESSCODE_TOKEN_SECRET);
}
Login and signup
app.post('/auth/loginaccess', function (req, res) {
Access.findOne({ password: req.body.password }, function (err, access) {
if (!access) {
return res.status(401).send({ message: 'Invalid password' });
}
access.comparePassword(req.body.password, function (err, isMatch) {
if (!isMatch) {
return res.status(401).send({ message: 'Invalid password' });
}
res.send({ tokenauth: createAccessToken(access) });
});
});
getPasswords();
});
app.post('/auth/signupaccess', function (req, res) {
Access.findOne({ password: req.body.password }, function (err, existingPw) {
if (existingPw) {
return res.status(409).send({ message: 'Password is already taken' });
}
var access = new Access({
password: req.body.password
});
access.save(function (err, result) {
if (err) {
res.status(500).send({ message: err.message });
}
res.send({ tokenauth: createAccessToken(result) });
});
});
});
ComparePassword and save schema
accessSchema.pre('save', function (next) {
var access = this;
bcrypt.genSalt(10, function (err, salt) {
bcrypt.hash(access.password, salt, function (err, hash) {
access.password = hash;
next();
});
});
});
accessSchema.methods.comparePassword = function (password, done) {
bcrypt.compare(password, this.password, function (err, isMatch) {
done(err, isMatch);
});
};
the creation of the password works and is correctly encrypted and inserted into the database. But when I try to login it throws the 401 error inside app.post('/auth/loginaccess').
Why is this happening?
And any tips to improve this is highly appreciated.
Related
I'm trying to use Google OAuth in my App, on the Log In page and the Sign Up page, I'm looking for the best way and the easiest! I tried Passport Js, but I'm stuck right now.
I'm using Mongoose right now and I'm signing up and in users perfectly, but now i want to add a feature where the user can sign in using his google account, I'm looking for a way where the app can get the Email the user is using for his google account and then look if the email is already registered if so redirect him to the home page and if not sign his email up, save it to database, and then redirect to the home page.
This is how my Auth.js looks like
//REGISTER
router.post("/register", async (req, res) => {
try {
//generate new password
const salt = await bcrypt.genSalt(10);
const hashedPass = await bcrypt.hash(req.body.password, salt);
//create new user
const newUser = new User ({
username: req.body.username,
firstName: req.body.firstName,
lastName: req.body.lastName,
email: req.body.email,
password: hashedPass,
repeatPassword: hashedPass,
birthday: req.body.birthday,
});
//save user and respond
const user = await newUser.save();
res.status(200).json(user);
} catch (err) {
res.status(500).json(err);
}
});
//LOGIN
router.post("/login", async (req, res) => {
try {
const user = await User.findOne({ email: req.body.email });
// if(!user) return res.status(400).json("Wrong credentials!");
!user && res.status(400).json("Wrong credentials!");
const validated = await bcrypt.compare(req.body.password, user.password);
// if(!validated) return res.status(400).json("Wrong credentials!");
!validated && res.status(400).json("Wrong credentials!");
const { password, ...others } = user._doc;
return res.status(200).json(others);
} catch (err) {
return res.status(500).json(err);
}
});
PassportJs configuration I used: but didn't work
passport.use(
new GoogleStrategy(
{
clientID: "MyClientId",
clientSecret: "Myclientsecret",
callbackURL: "/api/auth/google/callback",
},
function (accessToken, refreshToken, profile, done) {
User.find(
{
social: profile.provider,
social_id: profile.id,
},
(err, user) => {
if (user.length === 0) {
const user = new User({
email: profile.email,
username: profile.displayName,
profilePic: profile.photos[0],
social: profile.provider,
social_id: profile.id,
});
const userModel = new User(data);
userModel.save();
done(null, profile);
}
if (err) {
return done(err);
}
},
);
return done(null, profile);
}
)
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
router.get("/login/success", (req, res) => {
if (req.user) {
res.status(200).json({
success: true,
message: "successfull",
user: req.user,
// cookies: req.cookies
});
}
});
router.get("/login/failed", (req, res) => {
res.status(401).json({
success: false,
message: "failure",
});
});
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
router.get(
"/google/callback",
passport.authenticate("google", {
successRedirect: CLIENT_URL,
failureRedirect: "/login/failed",
})
);
I hope someone can help me out as ive spent far too long scratching my head over this issue. I have a small React, Express, MongoDb app which i want to integrate with Passport.js. However I just cannot get the passport to authenticate.
I have a controller set up for a route /login. I have a console log at the start of the file so I know that the code goes into that block. However the code doesnt enter the passport authenticate block.
const bcrypt = require('bcrypt');
const user = db.user;
const passport = require('passport');
exports.login = async (req, res, next) => {
console.log('inside login controller');
passport.authenticate('local', function (err, user, info) {
console.log('inside passport');
req.login(user, function (err) {
console.log('inside req login');
if (err) {
return res.status(400).json({ errors: err });
}
return res
.status(200)
.json({ success: `logged in ${user.id}` })
.redirect('/users/' + user);
})(req, res, next);
});
};
My server file looks like this (omitted a lot of stuff to save space but the gist is as follows):
const passport = require('./passport/setup');
const initialisePassport = require('./passport/setup');
const auth = require('./controller/user.controller');
app.use(
session({
secret: 'a_very_special_secret',
resave: false,
saveUninitialized: true,
expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours
store: new MongoStore({ mongooseConnection: mongoose.connection }),
})
);
app.use(cookieParser('a_very_special_secret'));
app.use(initialisePassport.initialize());
app.use(passport.session());
The last file is the passport setup file which is here:
const bcrypt = require('bcrypt');
const db = require('../models');
const User = db.user;
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
//Local strategy
passport.use(
new LocalStrategy({ usernameField: 'email' }, (email, password, done) => {
console.log('inside passport strat');
User.findOne({ email })
.then((user) => {
bcrypt.compare(password, user.password, (err, isMatch) => {
if (err) throw err;
if (isMatch) {
return done(null, user);
} else {
return done(null, false, { message: 'Wrong password' });
}
});
})
.catch((err) => {
return done(null, false, { message: err });
});
})
);
module.exports = passport;
Id love a helping hand on where im going wrong with this. So basically when i post to the route via the front end I get the message in my console that im inside the login controller but the authentication process doesnt happen.
I am using Node.js,angularjs,express and passport. I have tried all options I can think of, but still no solution. Couldn't find a solution from other posts for this problem.
app.post('/login', function(req, res, next) {
console.log(req.body.Email);
console.log(req.body.Password);
passport.authenticate('local', function(err, user, info) {
console.log(err,user,info);
...
In above req.body is showing correct in console but in passport authenticate it is showing null,false and info as missing credentials.
I have used the following for pass port
passport.use(new LocalStrategy({ usernameField: 'Email' }, (Email, Password, done) => {
console.log(Email, Password, done);
User.findOne({ Email: Email.toLowerCase() }, (err, user) => {
console.log(err);
if (err) { return done(err); }
if (!user) {
return done(null, false, { msg: `Email ${Email} not found.` });
}
user.ComparePassword(Password, (err, isMatch) => {
if (err) { return done(err); }
if (isMatch) {
return done(null, user);
}
return done(null, false, { msg: 'Invalid email or password.' });
});
});
}));
passport.serializeUser((user, done) => {
// console.log(user, done);
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
I couldn't understand why the problem exist.
Does anybody know what I am missing here?!?!
Thanks!
Use { usernameField: 'email' } not { usernameField: 'Email' } because you send req.body.email not req.body.Email
Adding upto kaxi answer I have made to solve this error by adding password field in the passport local strategy as below
passport.use(new LocalStrategy({ usernameField: 'Email',passwordField: 'Password' }, (Email, Password, done)
in place of
passport.use(new LocalStrategy({ usernameField: 'Email' }, (Email, Password, done)
Can you make an if-else statement to decide what to respond with based on if a function returns a status code or not?
nodejs/server.js
app.get('/api/videos', function (req, res) {
if(ensureAuthenticated){
Video.find({}, { _id: 0, iframe: 1, title: 1 }, function (err, docs) {
res.json(docs);
});
}else{
Video2.find({}, { _id: 0, iframe: 1, title: 1 }, function (err, docs) {
res.json(docs);
});
});
function ensureAuthenticated(req, res, next) {
if (!req.header('Authorization')) {
return res.status(401).send({ message: 'Please make sure your request has an Authorization header' });
}
var token = req.header('Authorization').split(' ')[1];
var payload = null;
try {
payload = jwt.decode(token, config.TOKEN_SECRET);
}
catch (err) {
return res.status(401).send({ message: err.message });
}
if (payload.exp <= moment().unix()) {
return res.status(401).send({ message: 'Token has expired' });
}
req.user = payload.sub;
req.role = payload.role;
next();
}
to only allow logged in users have access to the http.get we can do
app.get('/api/videos', ensureAuthenticated, function (req, res)
How would I do the http.get and then check ensureAuthenticated before responding with either Video.find() if authenticated or Video2.find() when not authenticated?
I get an error when i try to login using this code. The part of creating the user works perfectly and the login methods I used are nearly identical. But chrome gives me this error message:
TypeError: undefined is not a function
at Object.loginUser (http://localhost:8080/js/app.js:28:10)
at Scope.HomeController.$scope.loginUser (http://localhost:8080/js/app.js:197:9)
This is the html:
<button ng-click="createUser(email, password)">Create user</button>
<button ng-click="loginUser(email, password)">Login</button>
In the controller:
$scope.createUser = function(email, password) {
Auth.createUser(email, password);
}
$scope.loginUser = function(email, password) {
Auth.loginUser(email, password);
}
And the factory:
(function () {
angular
.module("myQuiz")
.factory("Auth", ["$firebaseAuth", function($firebaseAuth) {
var ref = new Firebase("https://angularquiz.firebaseio.com/");
return {
createUser: function(email, password) {
ref.createUser({
email: email,
password: password
}, function(error, userData) {
if(error) {
console.log("Error creating user: ", error);
} else {
console.log("Succesfully created an account with uid: " + userData.uid);
}
});
},
loginUser: function(email, password) {
ref.authwithPassword({
email: email,
password: password
}, function(error, authData) {
if(error) {
console.log("Login failed! " + error);
} else {
console.log(authData + "Succesfully authenticated!");
}
});
}
}
}]);
})();
typo, its authWithPassword not authwithPassword!
it works now