my passport strategy is never called. I recently added passport to my project and am using Boxes API to log a user in. I have done the example problem in another project and gotten it to work (https://github.com/smithdavedesign/OAUTH-Passport-BoxAPILogin-Example/blob/master/login/BoxLogin.js), however when I am trying to integrate it into my current project something has gone haywire. I read sessions and passport session are different and should not cause an issue, that being said I trying to figure out what middle ware is causing the issue. The box API is working correctly and returning me to my dashboard on the callback, however passport seams to be being skipped.
var products = require("../controllers/products");//get functions from product like add update delete ect
var validations = require("../controllers/validations");//get functions from product like add update delete ect
var settings = require("../config/settings");// get all things from settings we need
var Promise = require("bluebird");// adding promise mechanism
var bodyParser = require('body-parser');
var express = require('express');//web framework for node
const expressLayouts = require('express-ejs-layouts');// ejs view engine
const flash = require('connect-flash');//for error and success messages
const session = require('express-session');// holds data of users after login
const uuid = require('uuid')
var MemoryStore = require('memorystore')(session)//https://www.npmjs.com/package/memorystore
const util = require('util');
var os = require("os");
var hostname = os.hostname();//This is the users computer name
const multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
const upload = multer({ storage: storage })
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var BoxStrategy = require('passport-box').Strategy;
const app = express();//create instance of express
var BOX_CLIENT_ID = "**";
var BOX_CLIENT_SECRET = "**";
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function (user, done) {
console.log("serializeUser")//NEVER BEING CALLED
done(null, user);
});
passport.deserializeUser(function (obj, done) {
console.log("deserializeUser")//NEVER BEING CALLED
done(null, obj);
});
passport.use(new BoxStrategy({
clientID: BOX_CLIENT_ID,
clientSecret: BOX_CLIENT_SECRET,
callbackURL: "http://localhost:9000/dashboard"
},
function (accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
return done(null, profile);
});
}
));
//EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');//view engine
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(
session({
genid: (req) => {
console.log('Inside session middleware genid function')
console.log('Request object sessionID from client: ' + req.sessionID);
var new_sid = uuid.v4();
console.log('New session id generated: ' + new_sid);
return new_sid; // use UUIDs for session IDs
},
store: new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
}),
secret: 'secret',
resave: true,
httpOnly: false,
saveUninitialized: false,
cookie: {
maxAge: 24 * 60 * 60 * 1000
}
})
);
// Connect flash
app.use(flash());
// Global variables
app.use(function (req, res, next) {//diferent colors
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
//routes
app.use('/', require('./GraphRoutes'));
app.use('/', require('./dashboardRoutes'));
app.use('/', require('./index'));
app.use('/', require('./extraProccess'));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static('public'));//public folder where all templates live
app.use(express.static("."));
app.get('/', function (req, res) {
res.render('index', { user: req.user });
});
app.get('/login', function (req, res) {
res.render('login', { user: req.user });
});
app.get('/auth/box', passport.authenticate('box'), function (req, res) {
console.log("box call")
});
app.get('/auth/box/callback',
passport.authenticate('box', { failureRedirect: '/login' }),
function (req, res) {
res.redirect('/dashboard');
});
app.get('/logout', function (req, res) {
req.logout();
res.redirect('/login');
});
I was calling my routes before initializing passport, as well as having cookie parser and other middle ware not in the correct spot.
Related
I am trying to create a tweet to the user profile using twit package. This is the code I am using. By using this code I am able to tweet to my profile because I have access_token and access_token_secret. My question is If I want to tweet to some other people's profile. What is the procedure to do it I am not able to understand? I am using passport library to get the user details.
var Twit = require('twit');
var T = new Twit({
consumer_key: '************',
consumer_secret: '**********',
access_token: '******************',
access_token_secret: '******************',
timeout_ms: 60 * 1000,
strictSSL: true,
})
T.post('statuses/update', {status: 'hello world! '}, function(err, data, response) {
console.log('post on ',data);
})
Below down is my passport authentication code
'use strict';
require('dotenv').config();
const path = require('path');
const express = require('express');
const passport = require('passport');
const { Strategy } = require('passport-twitter');
const { TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, SESSION_SECRET } = process.env;
const port = process.env.PORT || 3000;
const app = express();
const routes = require('./routes');
passport.use(new Strategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: '/return'
},
(token, tokenSecret, profile, cb) => {
console.log(token);
console.log(tokenSecret);
console.log(profile);
return cb(null, profile);
}));
passport.serializeUser((user, cb) => {
cb(null, user);
});
passport.deserializeUser((obj, cb) => {
cb(null, obj);
});
app.set('view engine', 'ejs');
app.use('/public', express.static(path.join(__dirname, 'public')));
app.use(require('express-session')({ secret: SESSION_SECRET, resave: true, saveUninitialized: true }));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);
app.listen(port);
another file
'use strict';
const express = require('express');
const passport = require('passport');
const router = express.Router();
router.get('/', (req, res, next) => {
const { user } = req;
console.log('user details', req.user);
// res.render('home', { user });
});
router.get('/login/twitter', passport.authenticate('twitter'));
router.get('/logout', (req, res, next) => {
req.logout();
res.redirect('/');
});
router.get('/return',
passport.authenticate('twitter', { failureRedirect: '/' }),
(req, res, next) => {
res.redirect('/');
});
module.exports = router;
Got the answer following these steps. https://developer.twitter.com/en/docs/basics/authentication/oauth-1-0a
Hello i am trying to understand and apply "passport-azure-ad" function which i found on https://learn.microsoft.com/en-us/graph/tutorials/node?tutorial-step=1 to my own web applicaton.
Instead of "hbs"template engine what they use in the tutorial i use "jade". I registered the application in Azure. When running the web-application I and noticed that the signin function is working (redirected to the login page of Microsoft to enter my credentials). But when i leave the credentials page it returns to the http://localhost:3000/error instead of **http://localhost:3000/succes ** what i expected.
Can you please help me?
Below i put the javascript files:
app.js
require('dotenv').config();
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session');
var flash = require('connect-flash');
var passport = require('passport');
var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
var graph = require('./graph');
// Configure simple-oauth2
const oauth2 = require('simple-oauth2').create({
client: {
id: process.env.OAUTH_APP_ID,
secret: process.env.OAUTH_APP_PASSWORD
},
auth: {
tokenHost: process.env.OAUTH_AUTHORITY,
authorizePath: process.env.OAUTH_AUTHORIZE_ENDPOINT,
tokenPath: process.env.OAUTH_TOKEN_ENDPOINT
}
});
// Configure passport
// In-memory storage of logged-in users
// For demo purposes only, production apps should store
// this in a reliable storage
var users = {};
// Passport calls serializeUser and deserializeUser to
// manage users
passport.serializeUser(function(user, done) {
// Use the OID property of the user as a key
users[user.profile.oid] = user;
done (null, user.profile.oid);
});
passport.deserializeUser(function(id, done) {
done(null, users[id]);
});
// Callback function called once the sign-in is complete
// and an access token has been obtained
async function signInComplete(iss, sub, profile, accessToken, refreshToken, params, done) {
if (!profile.oid) {
return done(new Error("No OID found in user profile."), null);
}
try{
const user = await graph.getUserDetails(accessToken);
if (user) {
// Add properties to profile
profile['email'] = user.mail ? user.mail : user.userPrincipalName;
console.info(users)
}
} catch (err) {
done(err, null);
}
// Create a simple-oauth2 token from raw tokens
let oauthToken = oauth2.accessToken.create(params);
// Save the profile and tokens in user storage
users[profile.oid] = { profile, oauthToken };
return done(null, users[profile.oid]);
}
// Configure OIDC strategy
passport.use(new OIDCStrategy(
{
identityMetadata: `${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}`,
clientID: process.env.OAUTH_APP_ID,
responseType: 'code id_token',
responseMode: 'form_post',
redirectUrl: process.env.OAUTH_REDIRECT_URI,
allowHttpForRedirectUrl: true,
clientSecret: process.env.OAUTH_APP_PASSWORD,
validateIssuer: false,
passReqToCallback: false,
scope: process.env.OAUTH_SCOPES.split(' ')
},
signInComplete
));
//setup routes
//require('./routes/routes')(app, passport);
var indexRouter = require('./routes/index');
var authRouter = require('./routes/auth');
var app = express();
app.use(session({
secret: 'your_secret_value_here',
resave: false,
saveUninitialized: false,
unset: 'destroy'
}));
// Flash middleware
app.use(flash());
// Set up local vars for template layout
app.use(function(req, res, next) {
// Read any flashed errors and save
// in the response locals
res.locals.error = req.flash('error_msg');
// Check for simple error string and
// convert to layout's expected format
var errs = req.flash('error');
for (var i in errs){
res.locals.error.push({message: 'An error occurred', debug: errs[i]});
}
next();
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Initialize passport
app.use(passport.initialize());
app.use(passport.session());
app.use(function(req, res, next) {
// Set the authenticated user in the
// template locals
if (req.user) {
res.locals.user = req.user.profile;
}
next();
});
app.use('/', indexRouter);
app.use('/auth', authRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
auth.js
var express = require('express');
var passport = require('passport');
var router = express.Router();
/* GET auth callback. */
router.get('/signin',
function (req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res,
prompt: 'login',
failureRedirect: '/',
failureFlash: true,
successRedirect: '/'
}
)(req,res,next);
}
);
router.post('/callback',
function(req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res,
failureRedirect: '/Error',
failureFlash: true,
successRedirect: '/Succes'
}
)(req,res,next);
}
);
graph.js
var graph = require('#microsoft/microsoft-graph-client');
require('isomorphic-fetch');
module.exports = {
getUserDetails: async function(accessToken) {
const client = getAuthenticatedClient(accessToken);
const user = await client.api('/me').get();
return user;
}
};
function getAuthenticatedClient(accessToken) {
// Initialize Graph client
const client = graph.Client.init({
// Use the provided access token to authenticate
// requests
authProvider: (done) => {
done(null, accessToken);
}
});
return client;
}
Trying to use passport.js for linkedins oauth protocol (passport-linkedin-oauth2), i face this issue: when running 'node server', i get the following error:
PATH/node_modules/express/lib/router/index.js:139
debug('dispatching %s %s', req.method, req.url);
TypeError: Cannot read property 'method' of undefined
this is my server.js file:
const express = require('express');
const bodyParser = require("body-parser");
const path = require('path');
const passport = require('passport');
const session = require("express-session");
const app = new express();
const os = require('os');
const keys = require('./keys.js');
const listrategy = require('passport-linkedin-oauth2').Strategy;
require('events').EventEmitter.defaultMaxListeners = 15;
const PORT = process.env.PORT || 4000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static("public"));
const INDEX = path.join(__dirname, 'index.html');
const server = app().get('/',(req, res) => res.sendFile(INDEX))
passport.use(
new listrategy (
{
clientID: keys.linkedin.clientID,
clientSecret: keys.linkedin.clientSecret,
callbackURL: "/auth/linkedin/callback",
scope: ['r_emailaddress', 'r_liteprofile','w_member_social'],
state:true
},function (accessToken,refreshToken,profile,done) {
process.nextTick(function () {
console.log('profile',profile);
return done(null, profile);
});
})
);
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
app.use(session({resave: false, saveUninitialized: true, secret: 'recudorPegarevAecirP', cookie: { maxAge: 60000 }}));
app.use(passport.initialize());
app.use(passport.session());
app.listen(PORT);
I have got a valid linkedin secret and ID.
I am guessing something is wrong with the order of my declarations, or misusing the syntax. However, I don't know what. Could you help?
Thanks very much in advance.
You are trying to export router as router() somewhere in the other files and because of which is giving this error
just write router instead of router() while exporting the router file.
I am new to web development and NodeJS. I am working on authentication using passport. It was a small app so I put check on each route request to check whether the user is authenticated or not; But I guess that technique won't be feasible for a big app.
I want to authenticate the whole app. I know that it has something to do with middleware as each request passes through middleware, but I can't figure out where. Any middleware related explanation would be appreciated.
Here is my code
const express = require('express');
const app = express();
const path = require('path');
const mongo = require('mongodb').MongoClient;
const cookieParser = require('cookie-parser');
const expressHandlebars = require('express-handlebars');
const expressValidator = require('express-validator');
const session = require('express-session');
const passport = require('passport');
const localStrategy = require('passport-local').Strategy;
const mongoose = require('mongoose');
const User = require('./models/user');
const Admin = require('./models/admin');
app.engine('handlebars', expressHandlebars({defaultLayout:'layout'}));
app.set('view engine', 'handlebars');
const port = 8888;
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true
}));
app.use(passport.initialize());
app.use(passport.session());
//express Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.'),
root = namespace.shift(),
formParam = root;
while (namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param: formParam,
msg: msg,
value: value
};
}
}));
app.use(express.static(__dirname));
mongoose.Promise = global.Promise;
const url = 'mongodb://localhost:27017/userDB';
mongoose.connect(url);
Here is my login functionality.
app.get("/login", function (req, res) {
const loginPath = path.join(__dirname, '/login.html');
res.sendFile(loginPath);
});
passport.use(new localStrategy({
usernameField: 'adminUsername',
passwordField: 'password',
session: false
},
function (adminUsername, password, done) {
Admin.getAdminByAdminUsername(adminUsername, function (err, admin) {
if (err) throw err;
console.log('getAdmin called');
if (!admin) {
console.log('Admin Not Found');
return done(null, false);
}
Admin.comparePassword(password, admin.password, function (err, isMatch) {
console.log('comparePassword called');
if (err) throw err;
if (isMatch) {
return done(null, admin);
} else {
console.log('Wrong Password!');
return done(null, false);
}
});
});
}));
passport.serializeUser(function (admin, done) {
done(null, admin.id);
});
passport.deserializeUser(function (id, done) {
Admin.getAdminById(id, function (err, admin) {
done(err, admin);
console.log('findById called');
});
});
app.post('/login', passport.authenticate('local', {
failureRedirect: '/login'}), function(req, res){
console.log('login called');
res.redirect('/');
});
function ensureAuthenticated(req, res, next){
console.log(req.isAuthenticated());
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/login');
}
}
Previously, this is how I put a check on each request. Here is an example.
app.get("/update", ensureAuthenticated, function (req, res) {
const updatePath = path.join(__dirname, '/update.html');
res.sendFile(updatePath);
});
ensureAuthenticated is a middleware that you can also use standalone, like this:
app.use(ensureAuthenticated);
Express will pass requests to middleware and route handlers in order of their declaration. That means that if you add the line above in front of other middleware and route handlers, it will always be called, for each request (but read below why you might not actually want that). That way, you don't have to add it explicitly to each request handler.
Typically though, you separate "requests that require authentication" from requests that don't. For instance, requests for static resources (client-side JS, CSS, HTML, etc) typically don't require authentication. That means that you need to declare the static handler before ensureAuthenticated:
app.use(express.static(__dirname));
app.use(ensureAuthenticated);
The same goes for requests that are part of the login process: the login page and login request handler, for the simple reason that requiring a user to be logged in before they can access the login page doesn't make sense.
So the overall structure of your middleware/route handlers would look like this:
Common middleware (body parser, cookie handler, passport middleware, etc)
app.use(express.static(...))
Login routes
app.use(ensureAuthenticated)
"Protected" routes
i'm developing application on cloud9 enviroment. using:
node 4.43
express 4.13.4
i have integrated my Demo Auth0 account into my on-dev application.
i am able to login (being redirected to the first page of my app), but when i'm printing req.isAuthenticated() i'm getting false. also req.user is undefined.
i have followed the quick start of auth0 for node.js.
i'm attaching the three files that are mainly invovled:
app.js:
var express = require('express'),
app = express(),
BodyParser = require("body-parser"),
mongoose = require("mongoose"),
student = require ("./models/student"),
students_class = require("./models/class"),
// =============
// auth0
// =============
passport = require('passport'),
strategy = require('./models/setup-passport'),
cookieParser = require('cookie-parser'),
session = require('express-session');
app.use(cookieParser());
app.use(session({ secret: 'FpvAOOuCcSBLL3AlGxwpNh5x-U46YCRoyBKWJhTPnee2UELMd_gjdbKcbhpIHZoA', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
app.get('/login',passport.authenticate('auth0', { failureRedirect: '/url-if-something-fails' }),
function(req, res) {
res.send(req.user);
if (!req.user) {
throw new Error('user null');
}
res.redirect("/", {username: req.user});
});
mongoose.connect("mongodb://localhost/myapp");
// ============================
// routes
// ============================
var classRoutes = require("./routes/class"),
indexRoutes = require("./routes/index"),
studentRoutes = require("./routes/student"),
assocRroutes = require ("./routes/assoc");
// ============================================
// configuring the app
// ============================================
app.set("view engine", "ejs");
app.use(express.static ("public"));
app.use(BodyParser.urlencoded({extended: true}));
app.use(classRoutes);
app.use (indexRoutes);
app.use(studentRoutes);
app.use(assocRroutes);
app.listen(process.env.PORT, process.env.IP, function() {
console.log('Attendance Server is Running ....');
});
setup-passport.js
var passport = require('passport');
var Auth0Strategy = require('passport-auth0');
var strategy = new Auth0Strategy({
domain: 'me.auth0.com',
clientID: 'my-client-id',
clientSecret: 'FpvAOOuCcSBLL3AlGxwpNh5x-U46YCRoyBKWJhTPnee2UELMd_gjdbKcbhpIHZoA',
callbackURL: '/callback'
}, function(accessToken, refreshToken, extraParams, profile, done) {
// accessToken is the token to call Auth0 API (not needed in the most cases)
// extraParams.id_token has the JSON Web Token
// profile has all the information from the user
return done(null, profile);
});
passport.use(strategy);
// This is not a best practice, but we want to keep things simple for now
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
module.exports = strategy;
index.js (the actual fisrt page where i want to re-direct after successful login:
var express = require("express");
var passport = require('passport');
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn();
var router = express.Router();
var student = require ("../models/student");
//INDEX
router.get("/callback", function(req, res) {
student.find({}, function(err, student) {
console.log(req.isAuthenticated())
if (err) {
console.log(err);
} else {
res.render("home/index.ejs", {
students: student
});
}
});
});
module.exports = router;
any suggestion what could go wrong?
also wierd for me that on app.js, the guide is initializing the variable strategy but actually never seem to use it.
BUMP
You are not calling passport.authenticate() in the /callback endpoint. See for comparison: https://auth0.com/docs/quickstart/webapp/nodejs#5-add-auth0-callback-handler
// Auth0 callback handler
app.get('/callback',
passport.authenticate('auth0', { failureRedirect: '/url-if-something-fails' }),
function(req, res) {
if (!req.user) {
throw new Error('user null');
}
res.redirect("/user");
});