i'm new to nodejs, i'm using express-session for my project
I can't retrieve session values nowhere than my login route
I see many people have the same problems
Any recommend or help would be awesome ! you all have a nice day !
Here's my login route
route.post('/verify', (req, res) => {
const email = req.body.email;
const pass = req.body.password;
userModel.findOne({ email: email }, (err, data) => {
if (err) {
console.log(err);
res.status(500).json({
success: false,
message: error.message
});
}
else {
if (data !== null) {
if (!bcryptjs.compareSync(pass, data.password)
) {
res.status(400).json({
success: false,
message: "Wrong Password"
})
}
else {
req.session.currentUser = {
email: data.email,
};
console.log(req.session);
res.status(200).json({
success: true,
message: "Login Success",
data: {
email: data.email,
name: data.name,
id:data.id,
}
})
}
}
else {
res.status(404).json({
success: false,
message: "Email doesn't exist"
})
}
}
})
})
Here's my server.js setup:
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const cors = require('cors');
const session = require('express-session');
const bcryptjs = require('bcryptjs');
const passport = require('passport');
var Schema = mongoose.Schema;
require('./passport/facebook-auth')(passport);
require('dotenv').config();
const passportSetup = require('./passport/google-auth');
const authRoutes = require('./routes/auth-routes');
const userRoutes = require('./user/user.routes')
const userModel = require('./user/user.schema');
// connect to mongodb
mongoose.connect('mongodb://' + process.env.USER + ':' + process.env.PASS + '#localhost:27017/' + process.env.DATABASE + '?authSource=admin', { useNewUrlParser: true, useUnifiedTopology: true }, (e) => {
//FIXME: tim cach viet khac
if (e)
throw e;
else {
console.log("MongoDB Connected...");
// basic init
const server = express();
server.use(session({
secret: 'keyboard cat',
resave: true,
saveUninitialized: false,
}));
server.use(express.static('public'));
// set up cors to allow us to accept requests from our client
server.use(cors({
origin: "http://localhost:3000", // allow to server to accept request from different origin
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
credentials: true // allow session cookie from browser to pass through
})
);
server.use(bodyParser.json());
// set up session cookies
// initialize passport
server.use(passport.initialize());
server.use(passport.session());
// set up route
server.use('/auth', authRoutes);
server.use('/users', userRoutes);
server.listen(process.env.PORT || 5000, (err) => {
if (err)
throw err;
else
console.log("Server listening on port 5000...");
console.log('hadm x tanhng...');
console.log('ununneee here we come');
});
}
})
after logging in , the session is destroyed automatically
thank you once again
Related
Although I am pretty new to software development, I have an intermediate understanding of exporting and importing data between files. However, for some reason, when trying to create a config file for Passport.js and trying to import that file into my Index.js file, I hit a brick wall. Something tells me that it could be a rookie mistake, but I'm almost sure that I probably need to move some functions over. Any advice would genuinely do. My code is below for a visual view.
Passport.JS
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const mysql = require('mysql2');
const crypto = require('crypto');
const session = require('express-session');
const SqlDbStore = require('express-mysql-session')(session);
const db = require('./db');
app.use(session({
key: 'session_cookie_name',
secret: 'session_cookie_secret',
store: new SqlDbStore({
host: 'localhost',
port: 3306,
user: 'root',
password: 'xxxxxxxxxx',
database: 'xxxxxxxxxx',
}),
resave: false,
saveUninitialized: false,
cookie:{
maxAge:1000*60*60*24,
}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyParser.json());
app.use(express.static('public'));
app.use(express.static(__dirname + '/views'));
db.connect((err) => {
if (!err) {
console.log("BD Connected");
} else {
console.log("BD Conection Failed");
console.log(err.message);
}
});
const customFields={
firstNameField: 'usersFirstName',
lastNameField: 'usersLastName',
emailField: 'usersEmail',
passwordField:'usersPassword',
confirmPasswordField:'usersConfirmedPassword'
};
/*Passport JS*/
const verifyCallback=(email,password,done)=>{
connection.query('SELECT * FROM USER WHERE usersEmail= ?', [email], function(error, results, fields) {
if (error) {
console.log('query error: ' + error);
return done(error);
}
if(results.length==0) {
return done(null,false, {message: 'Account is not recognized.'});
}
const isValid=validPassword(password, results[0].EncryptHash, results[0].EncryptPassword);
user={id:results[0].ID, email:results[0].usersEmail, hash:results[0].EncryptHash, password:results[0].EncryptPassword};
if(isValid) {
return done(null,user);
} else {
return done(null,false, {message: 'Password is incorrect.'});
}
});
};
const strategy = new LocalStrategy(customFields, verifyCallback);
passport.use(strategy);
passport.serializeUser((user,done)=>{
console.log("Inside serialize");
done(null, user.id);
});
passport.deserializeUser(function(userId, done) {
console.log('deserializeUser');
connection.query('SELECT * FROM User WHERE ID = ? ', [userId], function(error, results) {
done(null, results[0]);
});
});
/*middleware*/
function validPassword(password, hash, salt){
const hashVerify=crypto.pbkdf2Sync(password, salt, 10000, 60, 'sha512').toString("hex");
return hash === hashVerify;
};
function genPassword(password) {
var salt=crypto.randomBytes(32).toString('hex');
var genhash=crypto.pbkdf2Sync(password, salt, 10000, 60, 'sha512').toString('hex');
return {salt:salt, hash:genhash}
};
function checkAuthentication(req,res,next){
if(req.isAuthenticated()){
//req.isAuthenticated() will return true if user is logged in
next();
} else {
res.redirect("/login");
}
};
Index.JS
const express = require('express');
const router = express.Router();
const db = require('../config/db');
const passport = require('../config/passport');
const routes = require('')('passport');
router.post('/register', (req, res) => {
const firstName = req.body.firstName;
const lastName = req.body.lastName;
const email = req.body.email;
const password = req.body.password;
const saltHash = genPassword(password);
const salt = passport.saltHash.salt;
const hash = passport.saltHash.hash;
db.query('SELECT * FROM Users WHERE UsersEmail = ? ', [email], (err, results) => {
if (err){
console.log(err)
} else if (results.length > 0) {
res.json({ message: 'Email is already registered!' });
} else {
db.query('INSERT INTO Users (UsersFirstName, UsersLastName, UsersEmail, UsersPasswordHash, UsersPasswordSalt) VALUES (?, ?, ?, ?, ?)', [firstName, lastName, email, hash, salt], (err, results) => {
if (err){
console.log(err);
};
res.send(results);
});
}
})
});
router.post('/login', passport.authenticate('local'));
module.exports = {router, passport};
Update:
Question is reposted with more information on Export and Import Passport.JS Issues.
More information is located on Export and Import Passport.JS Issues. I assumed since this post was getting no attention at all, I may have either been lacking details of my issue and explaining everything else or just had not details at all.
I'm trying to create an application which uses JWKS with RSA to sign cookies. I have some issues with the passport strategy I defined, when I try using it, the following error appears:
done(null, jwks.keys[0])
^
TypeError: Cannot read properties of undefined (reading '0')
My code for the passport Strategy I created is the following:
passport.use('jwt-jku', new JwtStrategy({
jwtFromRequest: req => { return (req && req.cookies) ? req.cookies.jwtCookie : null },
secretOrKeyProvider: (req, rawJwtToken, done) => {
const decoded = jwt.decode(rawJwtToken, { complete: true }) // Tiene .header y .payload
if (decoded.header.jku /* && decoded.payload.role === 'admin' */) {
axios({
method: 'get',
url: decoded.header.jku,
responseType: 'json'
}).then(function (jwks) {
console.log(jwks.toString())
done(null, jwks.keys[0])
})
} /* else if(decoded.payload.role !== 'admin') { ESTO NO VA porq no hay 'res'
req.send("You can't access the fortune teller endpoint! Only admin has access to it!")
} */
}
}, (jwtPayload, done) => { return done(null, jwtPayload ?? false) }
))
I use a file called jwks.json that contains:
{"keys":[{"kty":"RSA","kid":"tbrTvJIqhJ7jnYPdQL-LpkPUwqFltyQnWC5QGGUY8JM","use":"sig","alg":"RS256","e":"AQAB","n":"sFTW93A8v-oDFIS7oB2kzZq0RG15Oim9-FyeiTg6QBHcRb4kbTfXf0bQ3dTe-y0mVKUdZUtFyk71DNmI1INpO9y-QU2b-03KIW56As-kR6cmZeDIFwqDjceoUJreLEdEnxkObxuD5d5Qb7Zt8TS1BiRkX5vpiV32VTWpPZs0TglBv-Jdm54r1bvmrwaVUUMMi0DUptKIKLbqysl1j4OIXQSUMjRJF7OFIDfaZqvhPBNXTW7dbvxbfOq46Gpz_EqD2VBlYXOOgfXh8OhhhPkgZnbkq2HSUO1TZoiGFlq6M-Rah64D_8ESsDG2Bvk1Tx7hUCUmiba4AG2am2Gr8qcMmQ","d":"N0NHogHzkCQrtfUJhptzyJpZL-7tZOyrJJkGeLP-EZFnaxY1_WLYb4PGtxddkPPsBPBAn7vxEgAf7diJeSz8QK4klHvZzG9rT4H7zEC-WFSLBLfnjc0WQMuXtTdsNQ1a9M_aBblmY5cCt5hBqaxepZ-nM42-KfagWsE4Gt43DNN0vO7ztotY5TzKGv2R8TIz8BJIYVLVlUwvFheTDNJ97kz6EMR7keTzRcpg6pj-21l0NCLIySkRv4ZEQirW12kek7hgtI0A-mCiU61-GzX0S_MFEGi16Clk0kIQ6Ld2stT26xT01x0-htubgp-KEgW64GXKetOCzXrjZVivSHywPw","p":"vHSS2gMw56CgPyQmrLQNwR4cwL6QC77Zk5IE2QZlRWBDKUwOYioruqoc8t3Nop5xMcFjbNrtEb2RlMDB-lfyfJtcIWo9xh67AMcZ5Zq-FGnJBTjCry8Vf08r9jAfXzvr5dGbFnp4xV2gpuATQ3apBLy9eCkQKOVshdTbqtbKnCM","q":"74fZ4QSOQKqroCqqGnJ-MyyzTL2mSnthDzo7AmwSIZlzkgaqXO4o27uwRJVW2dxEK0XmDKNd94XNflADv1SDhu3mWcDVjkOjnc-zrVgEZjUWG3sABtwUWlSijOkmZG5jD9KPvb1ksvN0K3Xn0wcu8z1XJ9xSm4gw3NXHM2eBEhM","dp":"Zp64BL1uGQNPn3JpGOwm_T0PfSmHuM2hHwmJWEByTvffOpKu1meOTmQpxVpgiqfqjaR4JqOEKn_m0XCxcEgJxC65WXzHzKWZQRAqGuxLi0QbcZt57_kcpKmRD8semjY_-3JLGE9yik60l4o3Eyp_WRQJvG_n280qbin9wCacR68","dq":"skdAqTQE1KiyuLFIjgqtV1Vr1jBJdqJB6V2D0hexnwRhekwvvJ8eFf2qAkHMtLY2nqaVxM5LABG8ksjnIR68Dk8-5Yqa6Bn7y1dt-hTKoW_dlnKD4JcpJtpbadmWU6W9YWdsyOIP8wk0a6yD8RMlpLEBD4_yhARnqdYLP31IGbU","qi":"iIjOxBfcAwzikLRjMFQRfoEcW2RXDzi0xs2c9keut4j1DVgacVlS5J7sDHcJDsJJToHmaasix7-nl7nA5IYn6UiayzU7BqOc0D-orn8HecWWeYQ6hMZ81U80jRHmSN2cp-g4X2NtduxlGw8yoSlAKxQyEpgb5SqXYcDr5hQNgy4"}]}
I don't know what else to do, following I leave the whole code, maybe its easier to understand or something... Thank you!
const express = require('express')
const logger = require('morgan')
const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy
const JwtStrategy = require('passport-jwt').Strategy
const fortune = require('fortune-teller')
const axios = require('axios')
const cookieParser = require('cookie-parser')
const jwt = require('jsonwebtoken')
const fs = require('fs')
const path = require('path')
const jose = require('node-jose') // probar jose
const keyStore = jose.JWK.createKeyStore()
keyStore.generate('RSA', 2048, { alg: 'RS256', use: 'sig' })
.then(result => {
fs.writeFileSync(
path.join(__dirname, 'jwks.json'),
JSON.stringify(keyStore.toJSON(true))
)
// console.log(`Exported JWKSet: ${JSON.stringify(keyStore.toJSON(true), undefined, 2)}`)
})
const port = 3000
const app = express()
app.use(logger('dev'))
app.use(cookieParser())
/*
Configure the local strategy for using it in Passport.
The local strategy requires a `verify` function which receives the credentials
(`username` and `password`) submitted by the user. The function must verify
that the username and password are correct and then invoke `done` with a user
object, which will be set at `req.user` in route handlers after authentication.
*/
passport.use('local', new LocalStrategy(
{
usernameField: 'username', // it MUST match the name of the input field for the username in the login HTML formulary
passwordField: 'password', // it MUST match the name of the input field for the password in the login HTML formulary
session: false // we will store a JWT in the cookie with all the required session data. Our server does not need to keep a session, it's going to be stateless
},
function (username, password, done) {
if (username === 'walrus' && password === 'walrus') {
const user = {
username: 'walrus',
description: 'the only user that deserves to contact the fortune teller'
}
return done(null, user) // the first argument for done is the error, if any. In our case there is no error, and so we pass null. The object user will be added by the passport middleware to req.user and thus will be available there for the next middleware and/or the route handler
}
return done(null, false) // in passport returning false as the user object means that the authentication process failed.
}
))
passport.use('jwt-jku', new JwtStrategy({
jwtFromRequest: req => { return (req && req.cookies) ? req.cookies.jwtCookie : null },
secretOrKeyProvider: (req, rawJwtToken, done) => {
const decoded = jwt.decode(rawJwtToken, { complete: true }) // Tiene .header y .payload
if (decoded.header.jku /* && decoded.payload.role === 'admin' */) {
axios({
method: 'get',
url: decoded.header.jku,
responseType: 'json'
}).then(function (jwks) {
console.log(jwks.toString())
done(null, jwks.keys[0])
})
} /* else if(decoded.payload.role !== 'admin') { ESTO NO VA porq no hay 'res'
req.send("You can't access the fortune teller endpoint! Only admin has access to it!")
} */
}
}, (jwtPayload, done) => { return done(null, jwtPayload ?? false) }
))
app.use(express.urlencoded({ extended: true })) // needed to retrieve html form fields (it's a requirement of the local strategy)
app.use(passport.initialize()) // we load the passport auth middleware to our express application. It should be loaded before any route.
app.get('/', passport.authenticate('jwt-jku', { session: false, failureRedirect: '/login' }),
(req, res) => {
res.send(
"<a href='/'>Refresh</a> / <a href='/logout'>Logout</a><br><br>User: " +
req.user.sub + '<br><br>' + fortune.fortune()
)
}
)
app.get('/login',
(req, res) => {
res.sendFile('login.html', { root: __dirname })
}
)
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login', session: false }),
async (req, res) => {
const [key] = keyStore.all({ use: 'sig' })
const opt = {
compact: true,
jwk: key,
fields: {
typ: 'jwt',
jku: 'http://localhost:3000/jwks.json' // IP server
}
}
const payload = JSON.stringify({
exp: Math.floor(Date.now() / 1000) + 604800, // 1 week (7×24×60×60=604800s) from now
iat: Math.floor(Date.now() / 1000),
role: 'user'
})
const token = await jose.JWS.createSign(opt, key).update(payload).final()
// console.log(`Token sent. Debug at https://jwt.io/?value=${token}`)
res.cookie('jwtCookie', token, { httpOnly: true, secure: false }) // Store the token into the cookie
res.redirect('/')
// res.send(token)
}
)
/* app.get('/user', (req, res) => {
const user = { // Create the json object user with a name and a description
name: 'walrus',
description: 'it is what it is'
}
res.json(user) // Send the json object 'user'
}) */
app.get('/jwks.json', async (req, res) => {
const ks = fs.readFileSync('./jwks.json')
const keyStore = await jose.JWK.asKeyStore(ks.toString())
res.send(keyStore.toJSON())
})
app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
I have recently started using node.js as my backend and I have successfully posted data to the database, the problem that I am facing now is telling the front end that data has been successfully saved. Below is my user route with all the things I have tried commented out.
import { Router } from 'express';
import { IUser } from '../models/user.model';
const User = require('../models/user.model');
// import bcrypt from 'bcrypt';
const bcrypt = require('bcrypt');
const bodyParser = require('body-parser');
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
const userRouter = Router();
userRouter.get('/', (req, res) => {
return res.json('This is the user route');
})
userRouter.post("/register", (req, res: any, next) => {
const user: IUser = new User({
email: res.email,
firstName: res.firstName,
lastName: res.lastName,
password: res.password,
displayName: res.displayName,
cellNumber: res.cellNumber,
});
user.save()
.then((result: any) => {
res.status(201).json({
message: 'Successfully created a new user!',
result: result
});
// res.sendCode(201);
// console.log(res);
// res.status(201).send("User has been successfully created");
//return 'User has been successfully created';
// return Object({ message: "User has been successfully created" });
// return res.status(201).send({
// message: "User has been successfully created",
// statusCode: 201
// })
// return res;
})
.catch((err: any) => {
res.status(500).json({
error: err
})
})
// bcrypt.hash(req.body.password, 10)
// .then((hash: string) => {
// const user = new User({
// email: req.body.email,
// firstName: req.body.firstName,
// lastName: req.body.lastName,
// password: hash,
// displayName: req.body.displayName,
// cellNumber: req.body.cellNumber,
// });
// user.save()
// .then((res: any) => {
// res.status(201).json({
// message: 'Successfully created a new user!',
// result: res
// });
// })
// .catch((err: any) => {
// debugger;
// res.status(500).json({
// error: Error
// })
// })
// })
})
export default userRouter;
which I then export to the server.ts file which is below
import express = require('express');
//import cors from 'cors';
const cors = require('cors');
const bodyParser = require('body-parser')
import { Router } from 'express';
import mongoose from "mongoose";
import "dotenv/config"
//routes
import userRouter from './routes/user.routes';
//Create a new express instance
const app: express.Application = express();
app.get('/', function (req, res) {
res.send('Hello World');
});
// //get router
// var router = express.Router();
//Database
mongoose.connect(`${process.env.MONGO_URI}`,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log("Connected to MongoDB")
})
.catch(() => {
console.log("Connection to Database has failed")
})
var corsOptions = {
origin: '*',
credentials: true,
methods: '*'
};
const routes = Router();
export default routes;
app.use(routes);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors(corsOptions));
app.use("/user", userRouter);
routes.use('/user', userRouter);
routes.use(cors(corsOptions));
//use cors middleware
// router.use(cors(options));
app.listen(3000, function () {
console.log('App is listening on port 3000!');
})
What is strange is that when I set breakpoints and analyse the res file, i can see the data that I would have posted from the front end. But the front end gets the 500 status code instead of the 201 that I want to be sending, even though it passes right over that code. I have googled the keys of my keyboard for three days now. So I am at a loss now.
All The latest changes can be found in the GitLab repository below
https://gitlab.com/ShanahJr/SuperiorBallers
You just need to make use of res variable provided by express.
Example -
module.exports.updateData = async (req, res, next) => {
try {
const data = await Editor.edit(req.body.query);
res.status(200).json({ "status": true, "result": 'Edit successful!' })
} catch (error) {
console.log(error)
res.status(200).json({ "status": false, "result": "Request Failed!" })
}
}
This statement - res.status(200).json({ "status": true, "result": 'Edit successful!' })
Nowadays, express also suggests using res.sendStatus(200) over res.status(200)
You can lookup for status codes here
Use res.status(201).send(), res.status().json usually gets blocked by http rules especially when you activate https
I´m trying to set up a register and login server with node.js and mongoose. So I have create an user model and an user route. Can someone find the mistake why I can´t create an user. I connect to Postman under POST : localhost:3000/users/register
my user model:
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const bcrypt = require('bcryptjs');
const UserSchema = new mongoose.Schema({
email: {
type: String,
required: true,
minlength: 1,
trim: true, //calls .trim() on the value to get rid of whitespace
unique: true, //note that the unique option is not a validator; we use mongoose-unique-validator to enforce it
},
password: {
type: String,
required: true,
minlength: 8,
},
});
//this enforces emails to be unique!
UserSchema.plugin(uniqueValidator);
//this function will be called before a document is saved
UserSchema.pre('save', function(next) {
let user = this;
if (!user.isModified('password')) {
return next();
}
//we generate the salt using 12 rounds and then use that salt with the received password string to generate our hash
bcrypt
.genSalt(12)
.then((salt) => {
return bcrypt.hash(user.password, salt);
})
.then((hash) => {
user.password = hash;
next();
})
.catch((err) => next(err));
});
module.exports = mongoose.model('User', UserSchema);
my routes user:
const express = require('express');
const bcrypt = require('bcryptjs');
const User = require('../models/user');
const router = express.Router();
//util function to check if a string is a valid email address
const isEmail = (email) => {
if (typeof email !== 'string') {
return false;
}
const emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")#(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
return emailRegex.test(email);
};
router.post('/register', async (req, res) => {
try {
const { email, password } = req.body;
if (!isEmail(email)) {
throw new Error('Email must be a valid email address.');
}
if (typeof password !== 'string') {
throw new Error('Password must be a string.');
}
const user = new User({ email, password });
const persistedUser = await user.save();
res.status(201).json({
title: 'User Registration Successful',
detail: 'Successfully registered new user',
});
} catch (err) {
res.status(400).json({
errors: [
{
title: 'Registration Error',
detail: 'Something went wrong during registration process.',
errorMessage: err.message,
},
],
});
}
});
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
if (!isEmail(email)) {
return res.status(400).json({
errors: [
{
title: 'Bad Request',
detail: 'Email must be a valid email address',
},
],
});
}
if (typeof password !== 'string') {
return res.status(400).json({
errors: [
{
title: 'Bad Request',
detail: 'Password must be a string',
},
],
});
}
//queries database to find a user with the received email
const user = await User.findOne({ email });
if (!user) {
throw new Error();
}
//using bcrypt to compare passwords
const passwordValidated = await bcrypt.compare(password, user.password);
if (!passwordValidated) {
throw new Error();
}
res.json({
title: 'Login Successful',
detail: 'Successfully validated user credentials',
});
} catch (err) {
res.status(401).json({
errors: [
{
title: 'Invalid Credentials',
detail: 'Check email and password combination',
errorMessage: err.message,
},
],
});
}
});
module.exports = router;
my server :
const express = require('express');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const mongoose = require('mongoose');
const dotenv = require("dotenv");
const app = express();
dotenv.config();
//other imports
const usersRoute = require('./routes/users');
//other app.use statements
//connect to db
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true,
useUnifiedTopology: true},
() => console.log('Database connected')
);
mongoose.Promise = global.Promise;
const port = process.env.PORT || 3000;
//sets up the middleware for parsing the bodies and cookies off of the requests
app.use(bodyParser.json());
app.use(cookieParser());
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});
module.exports = { app };
what I only get is this.:
Cannot POST /users/register
You didn't specify the path prefix in your server file. You should define:
app.use("/users", usersRoute );
I am successfully authenticating and logging in with the google OAuth API.
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const passportInit = require('./app/routes/auth')
const session = require('express-session');
module.exports = (app, db, passport) => {
app.use(session({secret: "ahskfjdhkjshadkjfhlajsdhlfkj"}));
passportInit(passport)
app.use(passport.initialize());
app.use(passport.session())
app.get('/', (req, res) => {
if (req.session.token) {
res.cookie('token', req.session.token);
res.json({
status: 'session cookie set'
});
console.log(req.session.token);
console.log(JSON.stringify(req.user))
} else {
res.cookie('token', '')
res.json({
status: 'session cookie not set'
});
}
});
app.get('/auth/google', passport.authenticate('google', {
scope: ['https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/youtube']
}));
app.get('/auth/google/callback',
passport.authenticate('google', {
failureRedirect: '/' // Fail: To err Page
}),
(req, res) => {
req.session.token = req.user.token;
userString = JSON.stringify(req.user);
userObjectValue = JSON.parse(userString);
userId = userObjectValue['profile'].id;
userName = userObjectValue['profile'].name;
userGivenName = userName.givenName;
const details = {'userId': userId};
db.collection('users').findOne(details, (err, item) => {
if (item == null) {
res.redirect('http://localhost:80/Register.html');
} else {
if(item['rolle'] == 'yt') {
res.redirect('http://localhost:80/YT_Welcome.html');
} else {
res.redirect('http://localhost:80/WT_Welcome.html');
}
}
});
}
);
app.get('/logout', (req, res) => {
req.logout();
req.session.token = null;
res.redirect('/');
});
}
Now I want to make a POST request from my frontend to my NodeJS backend.
Frontend-Request:
function registerWT() {
console.log('registerWT started...')
var rolle = 'wt';
var json = {"rolle": rolle};
$.ajax({
url: 'http://localhost:8000/user',
type: 'POST',
data: JSON.stringify(json),
contentType: 'application/json; charset=utf-8',
dataType: 'JSON',
async: false,
success: function (msg) {
var js = JSON.stringify(msg);
var state = msg['state'];
if (state == true) {
console.log('successfully created new user')
} else {
console.log('failed to create new user')
}
}
});
Backend-API:
var ObjectID = require('mongodb').ObjectID;
const passport = require('passport');
const passportInit = require('./auth');
module.exports = (app, db) => {
app.post('/user', (req, res) => {
console.log("POST USER REACHED!"); // This is printed out...
console.log(req.body.rolle); //is printed out correctly
console.log(req.user); // Is undefined...
if (!req.isAuthenticated()) { return res.send({'error':'unauthorized'}) } //Authentication fails...
console.log(req.user.userId);
console.log(req.userGivenName);
console.log(req.body.rolle);
userId = req.user.userId;
userGivenName = req.user.userGivenName;
userRolle= req.body.rolle;
const details = { userId: userId, userGivenName: userGivenName, rolle: userRolle };
db.collection('users').insert(details, (err, result) => {
if (err) {
res.send({ 'error': 'An error has occurred' });
} else {
res.send(result.ops[0]);
}
});
});
}
From my understanding the user authentication data should be send automaticly with every request I am doing from my frontend to my backend, since I logged in via google before. Is this correct or do I miss to include something in my frontend JS request code?
What is interessting is that after I logged in, I have to trouble with navigating to /user. So there is no problem with manualy doing a get request to this API, where I am also checking for authentication.
app.get('/user', (req, res) => {
if (!req.isAuthenticated()) { return res.send({'error':'unauthorized'}) }
db.collection('users').find({}).toArray((err, item) => {
if (err) {
res.send({'error':'An error has occurred'});
} else {
res.json(item)
}
});
});
But when I am making a Get request with JavaScript, the authentication fails again...
JavaScript get request:
function getTest() {
console.log('YT');
$.ajax({
url: 'http://localhost:8000/user',
type: 'GET',
async: false,
success: function (msg) {
var state = msg['state']; //nehmen den Wert von state aus der JSON
if (state == true) {
console.log('successfully created new user')
} else {
console.log('failed to create new user')
}
}
});
}
Does someone know what I am doing wrong here?
Edit:
My passportInit:
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const keys = require('../../config/keys')
module.exports = (passport) => {
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
passport.use(new GoogleStrategy({
clientID: keys.google.clientID,
clientSecret: keys.google.cientSecret,
callbackURL: keys.google.callback
},
(token, refreshToken, profile, done) => {
return done(null, {
profile: profile,
token: token
});
}));
};
Edit2: Added cors package:
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const db = require('./config/db');
const keys = require('./config/keys')
const passport = require('passport');
const express = require('express');
const app = express();
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const cors = require('cors')
const port = 8000;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors({ origin: 'http://localhost' })); //configuring cors
MongoClient.connect(db.url, (err, database) => {
if (err) return console.log(err)
app.options('*', cors()) // enable pre-flight across-the-board
require('./authenticate')(app, database,passport);
require('./app/routes')(app, database, passport);
app.listen(port, () => {
console.log('We are live on ' + port);
});
});
I finally was able to solve the problem.
No, Browser Plug-in or something like this is needed!
Please see my Code below.
Frontend-Request:
function register() {
var role = 'wt';
var json = {"role": role};
$.ajax({
url: 'http://localhost:8000/user',
type: 'POST',
data: JSON.stringify(json),
contentType: 'application/json; charset=utf-8',
dataType: 'JSON',
xhrFields: {
withCredentials: true
},
crossDomain: true,
async: false,
success: function (msg) {
var state = msg['state'];
if (state == true) {
console.log('successfully created new WT')
location.href = 'http://localhost:80/WT_Welcome.html'
} else {
console.log('failed to create new WT')
location.href = 'http://localhost:80/index.html'
}
}
});
}
Backend Server.js
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const db = require('./config/db');
const keys = require('./config/keys')
const passport = require('passport');
const express = require('express');
const app = express();
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const port = 8000;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
MongoClient.connect(db.url, (err, database) => {
if (err) return console.log(err)
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', "http://localhost");
res.header('Access-Control-Allow-Methods','GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Credentials', true)
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
})
require('./authenticate')(app, database,passport);
require('./app/routes')(app, database, passport);
app.listen(port, () => {
console.log('We are live on ' + port);
});
});
Backend API:
app.post('/user', (req, res) => {
if (!req.isAuthenticated()) { return res.send({'error':'unauthorized'}) } //Authentication fails...
userString = JSON.stringify(req.user);
userObject = JSON.parse(userString)
userId = userObjectValue['profile'].id;
userName = userObjectValue['profile'].name; //not used
userGivenName = userName.givenName;
userRolle= req.body.rolle;
const details = { userId: userId, userGivenName: userGivenName, rolle: userRolle };
console.log(details);
db.collection('users').insert(details, (err, result) => {
if (err) {
res.send({ 'state': false });
} else {
res.send({'state' : true});
}
});
});