Instead of sending token in response body, need to keep in header so we can track between different pages whether user is authenticated or not.
Earlier we created token manually, but we can use database functionality to do it.
Observe the generateAuthToken method created in userSchema.
models/users.js
const Joi = require("joi");
const mongoose = require("mongoose");
const jwt = require("jsonwebtoken");
const config = require("config");
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
minLength: 5,
maxLength: 50,
lowercase: true,
},
email: {
type: String,
required: true,
minLength: 5,
maxLength: 50,
unique: true,
lowercase: true,
},
password: {
type: String,
required: true,
minLength: 5,
maxLength: 255,
},
});
//can't use arrow function syntax as they don't have the this keyword.They use the calling function object reference.
//so class methods should not use arrow functions, they are only for normal functions.
userSchema.methods.generateAuthToken = function () {
const token = jwt.sign({ _id: this._id }, config.get("jwtPrivateKey"));
return token;
};
const User = mongoose.model("User", userSchema);
function validateUser(user) {
const schema = Joi.object({
name: Joi.string().min(5).max(50).required(),
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(255).required(),
});
return schema.validate(user);
}
exports.User = User;
exports.validate = validateUser;
router/auth.js
const { User, validate } = require("../models/user");
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const _ = require("lodash");
const { getHashed } = require("../utils/passwordRelated");
const jwt = require("jsonwebtoken");
const Joi = require("Joi");
const bcrypt = require("bcrypt");
const config = require("config");
router.post("/", async (req, res) => {
const { error } = validateAuth(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (!user) return res.status(400).send("User does'nt exist");
const validPassword = bcrypt.compare(req.body.password, user.password);
if (!validPassword) return res.status(400).send("Invalid credentials");
//const token = jwt.sign({_id:user._id},config.get('jwtPrivateKey'))//'jwtprivatekey'
const token = user.generateAuthToken();
res.send(token);
});
function validateAuth(req) {
const schema = Joi.object({
email: Joi.string().min(5).max(255).required().email(),
password: Joi.string().min(5).max(50).required(),
});
return schema.validate(req);
}
module.exports = router;
router/users.js
const { User, validate } = require("../models/user");
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const _ = require("lodash");
const { getHashed } = require("../utils/passwordRelated");
router.post("/", async (req, res) => {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (user) return res.status(400).send("User already exists");
user = new User({
name: req.body.name,
email: req.body.email,
password: await getHashed(req.body.password),
});
await user.save();
user = _.pick(user, ["name", "email"]);
const token = user.generateAuthToken();
//res.send(user);
res
.header("x-auth-token", token)
.send(_.pick(user, ["_id", "name", "email"]));
});
module.exports = router;
No comments:
Post a Comment