I am setting up my NodeJS & Express App, using Passport for authentication with Google Sign In and Login. Everything works very well when working on localhost.
The signin process works very well, and I can see the user information attached to req.user contains all user information.
However, right after that, when calling any route, req.user is undefined
I try desperately, to check if any session doesent exist to redirected that, on my login page, but it gives me some error based on Unexpected token
index.js:
const express = require("express");
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
const app = express()
const port = 5000
// if user is not logged-in redirect back to login page
app.use(function(req, res, next) {
if (req.session.user == null){
res.redirect('http://localhost:3000/login');
} else {
next();
}
});
app.use(
session({
secret: 'keyboard cat',
resave: false,
cookie: { httpOnly: false, secure: false, maxAge: 60 * 1000},
saveUninitialized: false,
})
)
passport.use(
new GoogleStrategy({
clientID: "process.env.clientID",
clientSecret: "process.env.clientSecret",
callbackURL: '/auth/google/callback',
},
async (accessToken, refreshToken, profile, done) => {
const existingUser = await User.findOne({
providerId: profile.id,
})
if (existingUser) {
return done(null, existingUser);
}
const user = await new User({
provider: profile.provider,
providerId: profile.id,
displayName: profile.displayName,
}).save()
done(null, user);
})
)
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (obj, done) {
done(null, done);
});
My error :
ERROR Error in fetch(): request to http://localhost:3000/login failed, reason: read ECONNRESET
at ClientRequest.<anonymous> (node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (events.js:400:28)
at Socket.socketErrorListener (_http_client.js:475:9)
at Socket.emit (events.js:400:28)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21)
Thank you
For starters, move this:
// if user is not logged-in redirect back to login page
app.use(function(req, res, next) {
if (req.session.user == null){
res.redirect('http://localhost:3000/login');
} else {
next();
}
});
to be after this:
app.use(
session({
secret: 'keyboard cat',
resave: false,
cookie: { httpOnly: false, secure: false, maxAge: 60 * 1000},
saveUninitialized: false,
})
)
There will NEVER be a req.session until AFTER the session middleware runs so any code that tries to use req.session must be after the session middleware.
Also change this:
if (req.session.user == null)
to:
if (!req.session || !req.session.user)
So the code is safe if req.session doesn't exist.
Related
I am trying to use passport to google auth and log in a user.
Based on logs, I am able to fetch the user profile fine and also store it in mongodb for reuse.
Yet when after clicking the google login in UI, logs looking fine, but it doesn't redirect to the private page /private. Instead it throws following error.
Error is not consistent. Sometimes shows this. Other times just keeps staying on the google login page and keeps redirecting back to it.
InternalOAuthError: failed to fetch user profile
at /Users/name/projects/project-name/node_modules/passport-google-oauth2/lib/oauth2.js:92:28
at ClientRequest.<anonymous> (/Users/name/projects/project-name/node_modules/oauth/lib/oauth2.js:162:5)
at ClientRequest.emit (node:events:513:28)
at TLSSocket.socketErrorListener (node:_http_client:494:9)
at TLSSocket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
What am I missing?
This is the entire logic.
authentication.js (doubt issue is here. This is more on db connection which is fine)
import mongoose from 'mongoose';
import findOrCreate from 'mongoose-findorcreate'
import {DB_CLUSTER, DB_NAME, DB_OPTIONS, DB_PASSWORD, DB_USERNAME} from "./secrets.js";
export const createDbConnections = async () => {
const connectionString = `mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}#${DB_CLUSTER}/${DB_NAME}?${DB_OPTIONS}`;
mongoose.connect(connectionString, { useNewUrlParser: true });
const db = await mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected to MongoDB');
});
}
const userSchema = new mongoose.Schema({
name: {
type: String,
},
email: String,
googleId: String
});
userSchema.plugin(findOrCreate);
export const User = mongoose.model('User', userSchema);
This is the main index.js file with the auth and routes.
import passport from 'passport';
import {Strategy} from 'passport-google-oauth2';
import express from 'express';
import session from 'express-session';
import {config} from "dotenv";
import {createDbConnections, User} from "./authentication.js";
import {COOKIE_SESSION_SECRET, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, PORT} from "./secrets.js";
const app = express();
app.use(session({
secret: COOKIE_SESSION_SECRET,
resave: false,
saveUninitialized: true
}));
config();
await createDbConnections(); // connecting to mongo db no issues here.
passport.use('google', new Strategy({
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: `/auth/google/callback`,
scope: ['profile', 'email']
},
(accessToken, refreshToken, profile, done) => {
User.findOrCreate({ googleId: profile.id }, (err, user) => {
console.log(user)
return done(err, user);
});
}
));
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/' }),
(req, res) => {
req.login(req.user, err => {
if (err) { return res.send('Error during callback req.login portion'); }
console.log(`I reach here fine ${req.user}`)
return res.redirect('/private');
});
});
app.get('/private', passport.authenticate('google', { failureRedirect: '/' }), (req, res) => {
console.log('Issue is here. I never reach here.')
res.send('private spot');
});
app.get('/', (req, res) => {
if (req.user) {
// User is already logged in, render the homepage
res.redirect('/private');
} else {
// User is not logged in, render the login page
res.send(`Go and login # http://localhost:${PORT}/auth/google`);
}
});
passport.serializeUser((user, done) => {
done(null, user.id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
app.listen(PORT, () => {
console.log(`Go and authenticate # http://localhost:${PORT}/auth/google`);
});
I crate login by discord oauth2.
but sometimes I login the website it appears this error.
i want to fix this error
Error in console and website
InternalOAuthError: Failed to obtain access token (status: 429 data: error code: 1015)
at Strategy.OAuth2Strategy._createOAuthError (/home/runner/discord-oauth2/node_modules/passport-oauth2/lib/strategy.js:423:17)
at /home/runner/discord-oauth2/node_modules/passport-oauth2/lib/strategy.js:177:45
at /home/runner/discord-oauth2/node_modules/oauth/lib/oauth2.js:191:18
at passBackControl (/home/runner/discord-oauth2/node_modules/oauth/lib/oauth2.js:132:9)
at IncomingMessage.<anonymous> (/home/runner/discord-oauth2/node_modules/oauth/lib/oauth2.js:157:7)
at IncomingMessage.emit (node:events:402:35)
at IncomingMessage.emit (node:domain:475:12)
at endReadableNT (node:internal/streams/readable:1343:12)
I can't fix it i try many times but error don't always appears it's appears 1 from 10 times to login..
......
my website My website.
my backend code
index.js
const express = require('express');
const app = express();
const config = require("./config");
const passport = require("passport");
const { Strategy } = require("passport-discord");
const expressSession = require('express-session');
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((obj, done) => {
done(null, obj);
});
let strategy = new Strategy({
clientID: config.clientID,
clientSecret: config.clientSecret,
callbackURL: config.callbackURL,
scope: [ "identify", "email" ]
}, (accessToken, refreshToken, profile, done) => {
process.nextTick(() => done(null, profile));
});
const sessionMiddleware = expressSession({
secret: config.secret,
resave: true,
saveUninitialized: true
});
passport.use(strategy);
app.use(sessionMiddleware);
app.use(passport.initialize());
app.use(passport.session());
app.get("/login", passport.authenticate("discord", {
scope: [ "identify","email" ]
}));
app.get("/callback", passport.authenticate("discord", {
failureRedirect: "/hata"
}), (req, res) => {
res.redirect("/");
});
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.get("/", (req, res) => {
if(req.user){
res.render('loggiend/index.html', {
id: `${req.user.id}`,
username: `${req.user.username}`,
avatar: `${req.user.avatar}`,
email: `${req.user.email}`,
bot_name: "Mysterious Codes"
});
}else{
res.render('non-login/index.html',{
bot_name: "Mysterious Codes"
});
}
});
app.listen(config.PORT, () => console.log("Server ready, PORT: "+config.PORT));
app.use(express.static(__dirname + "/views"), (_, res, next) => {
res.status(404)
res.sendFile(__dirname + "/404.html")
});
config.js
module.exports = {
PORT: 3000,
secret: "????????????????????????",
clientID: process.env.clientID, // Discord API client ID
clientSecret: process.env.clientSecret, // Discord API client Secret
callbackURL: "https://discord-oauth2.hhhh68.repl.co/callback" // callback URL
};
I'm creating REST APIs using NodeJS and MongoDB as a database.
I'm using passport for handling the authentication.
I'm wondering why the sessions are not persistent! Also why the deserialization is never invoked!
passport.serializeUser(function (user, done) {
done(null, user._id);
});
passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
console.log(user, "deserialization"); // --> Never invoked!
done(err, user);
});
});
passport.use(User.createStrategy());
app.use(
session({
secret: process.env.SECRET,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }) // --> Sessions has been saved to database after each login or register
})
);
app.use(passport.initialize());
app.use(passport.session());
exports.getRestaurants = async (req, res) => {
console.log(req.session); // --> Not contains any user info
console.log(req.user); // -->undefined and this is my problem
const restaurants = await liveRestaurants.find().sort({ rate: -1 });
if (!restaurants) return next();
res.status(200).json({ restaurants });
};
After my research, I concluded that it might be for the following reasons:
app.use should be in the correct order
localhost port have an effect on it "as I read"
cluster
and other
Look, i've made a mean stack app with register/login using passportjs, and it was fine, when i change to angular2(the other was on angularjs) i've made the backend side and i think it works but i dont know how to test it on the fronted side, i know it has to be something with the url in the <a href=""> but when i put the route that passport gives me, example: /auth/facebook, my aplication does nothing... well it does something, send me to the homepage :c
here is my code so far on the backend side
const FacebookStrategy = require('passport-facebook').Strategy;
const session = require('express-session');
const secret = require('../config/database')
const user = require('../models/user')
module.exports = function(app, passport){
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}));
passport.serializeUser(function(user, done) {
token = jwt.sign({email: user.email}, secret, {expiresIn : '24h'});
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
passport.use(new FacebookStrategy({
clientID: '350645212059140',
clientSecret: '8a990aec6db37cc3535f4223c235c427',
callbackURL: "http://localhost:4200/auth/facebook/callback",
profileFields: ['id','displayName','email']
},
function(accessToken, refreshToken, profile, done) {
console.log(profile);
// User.findOrCreate(..., function(err, user) {
// if (err) { return done(err); }
// done(null, user);
// });
done(null, profile)
}
));
app.get('/auth/facebook',passport.authenticate('facebook', { scope: 'email' }));
app.get('/auth/facebook/callback' , passport.authenticate('facebook', {failureRedirect: '/login'}), function(res, res){
if (err) {
console.log(err)
}else{
res.send('wi')
}
})
return passport;
}
my question is, how can i implement this on the fronted side, remember angular 4 :)
Here is pseudo code for this.
Step 1: When you are submitting your form using ngSubmit call a function for instance passportLogin().
Step 2: Now in your component use this function and do an HTTP post request to your node js(express js) URL, for example, auth/login.
Step 3: In the server side write a routing
var express = require('express'),
router = express.Router();
module.exports = function(passport){
router.post('/login', passport.authenticate('local-login', {
successRedirect: '/auth/success',
failureRedirect: '/auth/failure'
}));
}
I'm trying to create an app with passport.js, node and sequelize.
But, passport is not returning the user in the session as expected.
When I log req.session I get this:
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: true } }
when I log req.session.passport I get undefined.
How can I fix this?
This is my server.js:
const express = require('express');
const load = require('express-load');
const passport = require('passport');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require('express-session');
// var app = express();
var app = module.exports = express();
// read cookies (needed for auth)
app.use(cookieParser());
// get information from html forms
app.use(bodyParser());
//set session
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'asdasdsada',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}))
// required for passport
app.use(passport.initialize());
app.use(passport.session({
secret: 'adsdssa',
name: 'sadasd',
proxy: true,
resave: true,
saveUninitialized: true
}));
And this is my passport.js:
var LocalStrategy = require('passport-local').Strategy;
var SlackStrategy = require('passport-slack').Strategy;
var User = require('../models/index').User;
var mysql = require('mysql');
var connection = mysql.createConnection({
host : process.env.MYSQL_HOST,
user : process.env.MYSQL_USER,
password : process.env.MYSQL_PASSWORD,
database : process.env.MYSQL_DB
});
module.exports = function(passport) {
passport.serializeUser(function(user, done) {
console.log('-----------serialize');
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
console.log('----------deserialize');
Model.User.findOne({
where: {
'id': id
}
}).then(function (user) {
if (user == null) {
done(new Error('Wrong user id.'));
}
done(null, user);
})
});
passport.use('slack', new SlackStrategy({
clientID: process.env.SLACK_ID,
clientSecret: process.env.SLACK_SECRET,
callbackURL: process.env.SLACK_REDIRECT,
scope: "incoming-webhook users:read"
},
function(accessToken, refreshToken, profile, done) {
var values = {
where: { slack_id: profile.id },
defaults: {slack_id: profile.id, name: profile.displayName}
};
User.findOrCreate(values)
.spread(function(user, created) {
return done(null,user);
});
}
));
And these are the routes I'm using:
app.get('/auth/slack',
passport.authorize('slack'));
app.get('/auth/slack/callback',
passport.authorize('slack', { failureRedirect: '/login' }),
function(req, res) {
//Successful authentication, redirect home.
console.log(req.session);
console.log(req.session.passport);
res.redirect('/dashboard');
}
);
I had the same problem and solved it.
Just remove
secure: true
for session like that
//set session
app.use(session({
secret: 'asdasdsada',
resave: false,
saveUninitialized: true
}))
It should works Also you can see simple example of passport-local here
https://github.com/passport/express-4.x-local-example