NodeJS Express req[user] undefined on multiple refresh - node.js

My Question is similar to this.I am using express version 4.14.0 and I have implemented OAuth2 SSO using "passport-ping" module. For getting new Access token from refresh token which we have on successful login I am using "passport-oauth2-refresh" module. No problem with these modules. Everything works fine as expected. But the problem is with request.user object. Below is my code
var express = require('express');
var async = require('async');
var cookieParser = require('cookie-parser');
var request = require('request');
var passport = require('passport');
var OAuth2Strategy = require('passport-ping').Strategy;
var refresh = require('passport-oauth2-refresh');
var session = require('express-session');
var bodyParser = require('body-parser');
var Client = require('node-rest-client').Client;
var client = new Client();
var _outputpath = "/build",
_templatePath = "./templates";
var app = express();
app.use(express.static(__dirname + "/"));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(session({
secret: "session secret",
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
var port = process.env.port || 8080;
// Allow cross orgin
app.all('*', function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Origin, Content-Type, X-Auth-Token');
res.setHeader('Access-Control-Allow-Credentials', true);
if (req.method === 'OPTIONS') {
res.status(200);
res.end();
} else {
next();
}
});
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (id, done) {
done(null, id);
});
var strategy = new OAuth2Strategy({
authorizationURL: 'xxx',
tokenURL: 'xxx',
clientID: 'xxx',
clientSecret: 'xxx',
callbackURL: 'http://localhost:8080'
},
function (accessToken, refreshToken, profile, done) {
done(null, { accessToken: accessToken, refreshToken: refreshToken });
}
);
passport.use('oauth-provider', strategy);
refresh.use('oauth-provider', strategy);
var isAuthenticated = function (req, res, next) {
if (req.isAuthenticated()) {
return next();
} else {
res.redirect('/');
}
}
/***************** GET BASE PAGE ************/
app.get('/guide', isAuthenticated, function (req, res) {
async.series({
one: function (callback) {
newAccessToken(req, res, true, function (reqQuery) {
var _reqQuery = reqQuery;
res.cookie('userAccessToken', req["user"].refreshToken, { maxAge: 1 * 24 * 3600000, httpOnly: false });
res.sendFile(__dirname + _outputpath + '/index.html');
callback(null, req["user"]);
})
},
two: function (callback) {
callback(null, 2);
}
},
function (err, results) {
console.log('Completed Guide Page');
});
});
app.get('/', passport.authenticate('oauth-provider', {
successRedirect: '/guide',
failureRedirect: '/error',
pfidpadapterid: 'OAuthAdapterCCDS'
})
);
function newAccessToken(req, res, isParent, callback) {
refresh.requestNewAccessToken('oauth-provider', req["user"].refreshToken, function (err, accessToken, refreshToken) {
var expireAccessToken = new Date();
expireAccessToken.setMinutes(expireAccessToken.getMinutes() + 59);
req["user"].refreshToken = refreshToken;
req["user"].accessToken = accessToken;
req["user"].accessTokenTime = new Date();
req["user"].expireAccessToken = expireAccessToken;
callback(req);
});
}
/***************** START THE SERVER ************/
app.listen(port, function () {
console.log('Server started & listening on port: ' + port);
});
On successful login OAuth2Strategy done function is adding below object to req.user.
{ accessToken: accessToken, refreshToken: refreshToken }
On every request I am hitting newAccessToken function to get new Access token for refresh token we have and updating the req.user object with new Access token and refresh token manually as shown below. Is there any better way to update the req["user"]?
req["user"].refreshToken = refreshToken;
req["user"].accessToken = accessToken;
req["user"].accessTokenTime = new Date();
req["user"].expireAccessToken = expireAccessToken;
If the user hits refresh continuously from browser, I am getting as req.user undefined. Tried few things by seeing forum but it dint worked. Any help is much appreciated.

I dint handled the error properly while getting the new access token. I changed new Access token function as below
function newAccessToken(req, res, isParent, callback) {
refresh.requestNewAccessToken('oauth-provider', req["user"].refreshToken, function (err, accessToken, refreshToken) {
var expireAccessToken = new Date();
expireAccessToken.setMinutes(expireAccessToken.getMinutes() + 59);
req["user"].refreshToken = refreshToken;
req["user"].accessToken = accessToken;
req["user"].accessTokenTime = new Date();
req["user"].expireAccessToken = expireAccessToken;
callback(req);
});
}

Related

req.user is blank even after authentication is successful using passportjs with saml

For my project I need to use authentication using ADFS + SAML.
I have followed the code and details as suggested at
http://www.passportjs.org/packages/passport-saml and sample code at https://github.com/gbraad/passport-saml-example
During authentication, the authentication is successful, but req.user is always undefined.
When I tried to print the req, using CircularJSON.stringyfy, I can see all the details inside SAMLResponse -> 'body'.
Here is my code snippet
routes.js
module.exports = function (app,config,passport) {
app.get('/', function (req, res) {
try {
if (req.isAuthenticated()) {
console.log(req.session)
res.send('user authenticated successfully' + req.user.name) // => If I print req using CircularJSON.stringify, I can see all the details.
} else {
//res.send('User not authenticated.')
res.redirect('/login')
}
} catch (error) {
console.log('Error ' + error);
}
});
app.get('/login',
passport.authenticate(config.passport.strategy,
{
successRedirect: '/',
failureRedirect: '/login'
})
);
}
app.js
const express = require('express');
const https = require('https');
const path = require('path');
const passport = require('passport');
const morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
const session = require('express-session');
const errorhandler = require('errorhandler');
const fs = require('fs');
const config = require('./config/config');
console.log('Using configuration', config);
require('./config/passport')(passport, config);
var app = express();
app.use(express.static("public"));
app.set('port', 3000);
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'https://localhost:3000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
app.use(morgan('combined'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false }));
app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(session(
{
resave: true,
saveUninitialized: true,
secret: 'my_secret',
cookie: {
secure: true,
httpOnly: true
}
}));
app.use(passport.initialize());
app.use(passport.session());
require('./config/routes')(app, config, passport);
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
var my_server = https.createServer(options,app)
my_server.listen(3000);
passport.js
const SamlStrategy = require('passport-saml').Strategy;
module.exports = function (passport, config) {
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
passport.use(new SamlStrategy(
{
path: config.passport.saml.path,
entryPoint: config.passport.saml.entryPoint,
issuer: config.passport.saml.issuer,
},
function (profile, done) {
return done(null,
{
id: profile.uid,
email: profile.email,
displayName: profile.cn,
firstName: profile.givenName,
lastName: profile.sn
});
})
);
};
Thanks for your help.
Let me answer my own question, in case someone finds it useful.
The mistake I was making was in passport.use
When I changed it to following, it worked..
passport.use(new SamlStrategy(
{
path: config.passport.saml.path,
entryPoint: config.passport.saml.entryPoint,
issuer: config.passport.saml.issuer,
cert: config.passport.saml.cert,
},
function (profile, done) {
return done(null,
{
id: profile['nameID'],
email: profile['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name'],
displayName: profile['http://schemas.microsoft.com/identity/claims/displayname'],
name: profile['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'],
lastName: profile['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname']
});
})
);

ReferenceError: User is not defined on callback

I'm implementing a google login with node, express, and passport. After I click sign in, I get a User is not defined error when it's calling back to the page. It worked before but for some reason it doesn't now. Since the user isn't found, the session data is also not going to the database either. After sign in, the user is correctly signed into chrome.
Any suggestions on how to fix this issue?
User.findOne({ "google.id": profile.id }, function (err, user) {
^
ReferenceError: User is not defined
app.js on localhost:3000
var createError = require("http-errors");
var express = require("express");
var path = require("path");
var cookieParser = require("cookie-parser");
var logger = require("morgan");
var passport = require("passport");
var bodyParser = require("body-parser");
var passport = require("passport");
var session = require("express-session");
var DynamoDBStore = require("connect-dynamodb")(session);
var GoogleStrategy = require("passport-google-oauth2").Strategy;
var AWS = require("aws-sdk");
var cors = require("cors");
require("dotenv").config({ path: __dirname + "/.env" });
var GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
var GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET;
var app = express();
passport.use(
new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback",
passReqToCallback: true,
},
function (request, accessToken, refreshToken, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function () {
User.findOne({ "google.id": profile.id }, function (err, user) {
if (err) return done(err);
if (user) {
// if a user is found, log them in
return done(null, user);
} else {
// if the user isnt in our database, create a new user
var newUser = new User();
// set all of the relevant information
newUser.google.id = profile.id;
newUser.google.token = token;
newUser.google.name = profile.displayName;
newUser.google.email = profile.emails[0].value; // pull the first email
// save the user
newUser.save(function (err) {
if (err) throw err;
return done(null, newUser);
});
}
});
});
}
)
);
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (obj, done) {
console.log(obj);
done(null, obj);
});
AWS.config.update({
accessKeyId: process.env.ACCESS_KEY,
secretAccessKey: process.env.ACCESS_KEY_SECRET,
region: "us-west-1",
});
var dynamodb = new AWS.DynamoDB();
var server = require("http").createServer(app);
var userDrinksRouter = require("./routes/userDrinks");
var drinksRouter = require("./routes/drinks");
var ingredientsRouter = require("./routes/ingredients");
var liquorRouter = require("./routes/liquors");
var justIngredients = require("./routes/justIngredients");
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3001");
res.header("Access-Control-Allow-Credentials", true);
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(logger("dev"));
var options = {
table: "app-sessions",
AWSConfigJSON: {
accessKeyId: process.env.ACCESS_KEY,
secretAccessKey: process.env.ACCESS_KEY_SECRET,
region: "us-west-1",
},
client: dynamodb,
};
//initialzie session
app.use(
session({
store: new DynamoDBStore(options),
secret: "new user",
resave: true,
saveUninitialized: true,
})
);
app.use(passport.initialize());
app.use(passport.session());
// serialized and deserialized.
app.use((req, res, next) => {
console.log(req.user);
next();
});
app.get("/", function (req, res) {
res.status(200).send({ user: req.user });
});
app.get("/account", ensureAuthenticated, function (req, res) {
res.status(200).send({ user: req.user });
});
app.get("/login", function (req, res) {
res.status(200).send({ user: req.user });
});
app.get("/users", function (req, res) {
res.send({ user: req.user });
});
app.get(
"/auth/google",
passport.authenticate("google", {
scope: ["profile", "email", "openid"],
})
);
app.get(
"/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/login",
}),
function (req, res) {
res.redirect("http://localhost:3001/");
}
);
app.get("/logout", function (req, res) {
req.logout();
res.redirect("http://localhost:3001/");
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
res.redirect("/login");
}
//app.use(ensureAuthenticated);
//app.use("/userDrinks", userDrinksRouter);
app.use("/drinks", drinksRouter);
app.use("/ingredients", ingredientsRouter);
app.use("/liquors", liquorRouter);
app.use("/justIngredients", justIngredients);
server.listen(3000, () => console.log("Drinks API listening on port 3000!"));
If I saw correctly, appears that you didn't import User, take a look on your requires.

How can I make passportjs google login oauth work with JWT instead of creating session through serialize/deserialize method?

The below code will works perfectly If I add the serialize/deserialize passportjs method, which creates a session. I am working to create Json Web Token, not session. Any tutorial, suggestion or clear sample would be greatly appreciated.I use nodejs.
I understood the pro/con and basic overview of how JWT works. I learned it from the following source.
https://medium.com/#rahulgolwalkar/pros-and-cons-in-using-jwt-json-web-tokens-196ac6d41fb4
https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication
https://scotch.io/tutorials/the-anatomy-of-a-json-web-token
https://auth0.com/blog/cookies-vs-tokens-definitive-guide
/
No JWT code
var express = require("express"),
path = require("path"),
bodyParser = require("body-parser"),
mysql = require("mysql"),
connection = require("express-myconnection"),
morgan = require("morgan"),
app = express(),
passport = require("passport"),
GoogleStrategy = require("passport-google-oauth").OAuth2Strategy;
app.use(passport.initialize());
app.get("/", function(req, res) {
res.sendFile(__dirname + "/public/main.html");
});
// #1
passport.use(
new GoogleStrategy({
clientID: "32434m",
clientSecret: "23434",
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
console.log("profile.id: " + profile.id);
return done(null, profile.id); // that is being serealized(added in session)
});
}
)
);
// #1
app.get("/auth/google",
passport.authenticate(
"google", {
scope: ["profile", "email"]
}));
// #2
app.get("/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/google_callback_fail",
successRedirect: "/google_callback_success"
})
);
app.get("/google_callback_success", isLoggedIn, function(req, res) {
res.send("google_callback_success \n");
});
function isLoggedIn(req, res, next) {
console.log("isLoggedIn req.user: " + req.user);
if (req.isAuthenticated()) {
console.log("isAuthenticated TRUE");
return next();
}
res.redirect("/notloggedin");
}
app.get("/notloggedin", function(req, res) {
console.log("req.user: " + req.user);
res.json("not loggedin");
});
app.get("/google_callback_fail", function(req, res) {
res.json("the callback after google DID NOT authenticate the user");
});
app.listen(3000);
JWT code attempt. The problem is I need to add serialize/deserialize, which I don't want to, since, I don't want to use session. I want JWT
var express = require("express"),
path = require("path"),
bodyParser = require("body-parser"),
mysql = require("mysql"),
connection = require("express-myconnection"),
morgan = require("morgan"),
app = express(),
passport = require("passport"),
GoogleStrategy = require("passport-google-oauth").OAuth2Strategy,
jwt = require('jsonwebtoken'),
passportJWT = require("passport-jwt"),
ExtractJwt = require('passport-jwt').ExtractJwt,
JwtStrategy = require('passport-jwt').Strategy;
var jwtOptions = {};
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = 'secret';
app.use(passport.initialize());
app.get("/", function(req, res) {
res.sendFile(__dirname + "/public/main.html");
});
// #1
passport.use(
new GoogleStrategy({
clientID: "s-s.apps.googleusercontent.com",
clientSecret: "23redsf",
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
process.nextTick(function() {
console.log("\nprofile.id: " + profile.id);
return done(null, profile.id); // that is being serealized(added in session)
});
}
)
);
// #1
app.get(
"/auth/google",
passport.authenticate(
"google", {
scope: ["profile", "email"]
}
)
);
// #2
app.get(
"/auth/google/callback",
passport.authenticate("google", {
failureRedirect: "/google_callback_fail",
successRedirect: "/google_callback_success"
})
);
app.get("/google_callback_success", isLoggedIn, function(req, res) {
var payload = { id: user.id };
var token = jwt.sign(payload, jwtOptions.secretOrKey);
var strategy = new JwtStrategy(jwtOptions, function(jwt_payload, next) {
console.log('payload received', jwt_payload);
console.log('jwt_payload.id: ' + jwt_payload.id);
});
passport.use(strategy);
res.send("google_callback_success \n" + 'token: ' + token);
});
function isLoggedIn(req, res, next) {
console.log("isLoggedIn req.user: " + req.user);
if (req.isAuthenticated()) {
console.log("isAuthenticated TRUE");
var payload = { id: user.id };
var token = jwt.sign(payload, jwtOptions.secretOrKey);
console.log('token: ' + token);
return next();
}
res.redirect("/notloggedin");
}
app.get("/notloggedin", function(req, res) {
console.log("req.user: " + req.user);
res.json("not loggedin");
});
app.get("/google_callback_fail", function(req, res) {
res.json("the callback after google DID NOT authenticate the user");
});
app.get("/logout", function(req, res) {
console.log("logged out");
req.logout();
res.redirect("/logout");
});
app.listen(3000);
The code return done(null, profile.id); // that is being serialized(added in session) is the problem. What should I replace it so that I don't have to use sessions? I want to replace it with JWT.
https://www.sitepoint.com/spa-social-login-google-facebook/
basically after google authentication is done, you create a jwt for the user.
// src/index.js
function generateUserToken(req, res) {
const accessToken = token.generateAccessToken(req.user.id);
res.render('authenticated.html', {
token: accessToken
});
}
app.get('/api/authentication/google/start',
passport.authenticate('google', { session: false, scope:
['openid', 'profile', 'email'] }
));
app.get('/api/authentication/google/redirect',
passport.authenticate('google', { session: false }),
generateUserToken
);
After a long time spent trying to find a workaround, I finally came across this. The best option thus far, works perfectly for me.
app.get('/auth/google/callback',
passport.authenticate('google',
{ failureRedirect: '/', session: false }), (req, res) => {
const jwt = createJWTFromUserData(req.user);
const htmlWithEmbeddedJWT = `
<html>
<script>
// Save JWT to localStorage
window.localStorage.setItem('JWT', '${jwt}');
// Redirect browser to root of application
window.location.href = '/';
</script>
</html>
`;
res.send(htmlWithEmbeddedJWT);
});
This can be achieved by opening the google auth screen in a new window and writing the JWT back using window.postMessage().
App:
const Login = () => {
const setToken = function(e) {
if (
e.origin === origin &&
e.data &&
e.data.command === 'token-ready' &&
e.data.info &&
e.data.info.token
) {
localStorage.setItem('jwt', e.data.info.token);
e.source.postMessage(
{
command: 'info',
info: {
complete: true,
},
},
e.origin
);
}
};
window.addEventListener('message', setToken, false);
const login = () => {
window.open(loginUri);
};
return (<button onClick={login}>Login</button>
}
Server Response:
const html = `
<!DOCTYPE html>
<html>
<head>
<title>Authenticated</title>
</head>
<body>
Authenticated successfully.
<script type="text/javascript">
window.addEventListener("message", function(e) {
console.dir(e)
if (e.origin === "${postBackUri}" && e.data && e.data.info && e.data.info.complete) {
window.close();
}
}, false);
opener.postMessage({
command: "token-ready",
info: {
token: "${token}",
},
}, "${postBackUri}");
</script>
</body>
</html>
`;
return res.send(html);
Take a look at Passport-JWT. As they say, this module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.

Passport.js is not storing/sending passport user info

So I am trying to build a simple login/authorization tool utilizing node.js, passport.js and angular2. My current issue is that while a user can login, the session information doesn't appear to be passed to the front end server or the front end server doesn't pass the passport information back.
When logging in the user appears to get all the way to the portion where the res.send is called, and at that point serialize has been called and req.sessions.passport.user has been set; however, when the user tries to go to an authorized page, while the cookie is there, the passport is missing. While Deserialized is also never called, the middleware is called/appears called. When the middleware gets to the deserializer there is no passport/user attached thus deserialize is never called.
At this point I am wondering if it might be a CORS issue or something with angular2, but I have been working on this for several days and appear to be doing it the suggested way. I have also tried rebuilding it and setting up CORS in multiple ways along with the middleware and I am running out of ideas. I am also using express session but that appears to be working because the cookie I create in that exists.
Session Data at the end of auth but before responding to the site
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false },
passport:
{ user:
anonymous {
username: 'test',
hash: '4024ca40c4372e029459a1d2d52a25b2fc4642f980f6cc948cc4b35f6350adde',
} } }
Session Data after making further requests
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: false } }
Relevant Code:
Passport.js
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((users, done) => {
var id=users.username;
db.one('select * from users where username = $1', id)
.then((user) => {
done(null, user);
})
.catch((err) => { done(err,null); });
});
local.js
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const init = require('./passport');
var promise = require('bluebird');
var options = {
// Initialization Options
promiseLib: promise
};
var hashclient = require('hashapi-lib-node');
const crypto = require('crypto');
var hash = crypto.createHash('sha256');
var pgp = require('pg-promise')(options);
var connectionString = 'postgresql://...';
var db = pgp(connectionString);
const optionsPassport = {};
init();
passport.use(new LocalStrategy(optionsPassport, (username, password, done) => {
db.one('select * from users where username = $1', username)
.then((user) => {
hash.update(password);
var encryptedPassword=hash.digest('hex');
hash = crypto.createHash('sha256');
if (!user) return done(null, false, { message: 'Incorrect username.' });
if (encryptedPassword!=user.password) {
return done(null, false, { message: 'Incorrect information.' });
} else {
return done(null, user);
}
})
.catch((err) => { return done(err); });
}));
helpers.js
function loginRequired(req, res, next) {
if (!req.user) return res.status(401).json({status: 'Please log in'});
return next();
}
Router.js example
const users = require('express').Router();
const auth = require('./auth');
const update = require('./update');
const password = require('./password');
const authHelpers = require('./helpers');
const passport = require('./local');
users.post('/update', authHelpers.loginRequired, update);
users.get('/:userId', authHelpers.loginRequired, single);
users.post('/create', create);
users.post('/auth', passport.authenticate('local'), auth);
app.js
var passport = require('passport');
app.use(cookieParser())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: 'X+a1+TKXwd26mkiUUwqzqQ==',
resave:true,
saveUninitialized:true,
cookie:{secure:false}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
var allowedOrigins = ['http://localhost:3000']
res.header('Access-Control-Allow-Origin', allowedOrigins);
res.header( 'Access-Control-Allow-Headers', 'withCredentials, Access-Control-Allow-Headers, Origin, X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Request-Headers');
res.header( 'Access-Control-Allow-Methods', 'GET, OPTIONS, HEAD, POST, PUT, DELETE');
res.header( 'Access-Control-Allow-Credentials', true);
next();
});
var routes = require('./routes');
app.use('/', routes);
front end http service
getData (url:string, data:any): Observable<any> {
var headers = new Headers({ 'Content-Type': 'application/json', withCredentials: true });
var options = new RequestOptions({ headers: headers });
return this.http.get(url,options)
.map((res: Response): data => res.json())
.catch(this.handleError);
}
The issue was on the front end I was not setting withCredentials to true in the correct location
var options = new RequestOptions({ headers: headers, withCredentials: true });

NodeJS using Passport and Facebook

I almost have Passport authenticating via Facebook, however the FacebookStrategy callback in my Model is never being called so not able to get profile information. I must be missing something, but not having any luck figuring it out.
My App.js
var express = require('express');
var http = require('http');
var path = require('path');
var mongoose = require('mongoose');
var fs = require('fs');
var io = require('socket.io');
var config = require("./server/config");
var passport = require("passport");
//init Express
var app = express();
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.header('Access-Control-Allow-Credentials', true);
next();
}
//client code could be found here
var clientDir = path.join(__dirname, 'www');
//set up Node app configurations
app.configure(function(){
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({
secret: 'adasdasdasdasdasdasdasdasdasdasd'
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.methodOverride());
app.use(allowCrossDomain);
app.use(app.router);
app.use(express.static(clientDir));
});
// Mongo startup
var mongoUri = config.development.mongoUrl;
var db = mongoose.connect(mongoUri);
mongoose.set('debug', true);
mongoose.connection.on("open", function() {
console.log("Mongo Open on: " + mongoUri);
init();
});
mongoose.connection.on("error", function() {
console.log("Mongo ERROR");
});
var init = function(){
var models = {
User: require('./server/models/User')(app, mongoose, config, passport)
};
//load up routes
require('./server/routes/FacebookAuth')(app, models, config, passport);
}
// Create an http server
app.server = http.createServer(app);
//go to 'client' index page
app.get('/', function(req, res){
res.sendfile(path.join(clientDir, 'index.html'));
});
var portNum = process.env.PORT || 3004;
app.server.listen(portNum, function(){
var addr = app.server.address();
console.log(' app listening on http://' + addr.address + ':' + addr.port);
});
My Route
module.exports = function (app, models, config, passport) {
app.get('/auth/facebook', passport.authenticate('facebook', {
scope: ['read_stream', 'publish_actions']
}));
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect: '/#/maker/123456',
failureRedirect: '/#/login'
}));
}
My Model
module.exports = function (app, mongoose, config, passport) {
var FacebookStrategy = require('passport-facebook').Strategy;
var UserSchema = new mongoose.Schema({
fbId: String,
name: String,
email: {
type:String,
lowercase: true
}
});
console.log("+++++++++++++ User Model");
var User = mongoose.model('User', UserSchema);
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
passport.use(new FacebookStrategy({
clientID : config.development.fb.appId,
clientSecret: config.development.fb.appSecret,
callbackURL: config.development.fb.url + '/#/maker/12345'
},
function(acccessToken, refreshToken, profile, done){
//THIS IS NEVER BEING CALLED!
console.log("################################");
process.nextTick(function(){
return done(null, profile);
console.log("################################");
})
}
));
/*****************
* Public API
*****************/
return {
User: User,
/***GET***/
//Get All Items
//Get "one" item by Id
findById: function (id, items, callback) {
User.findById(id, items, function (err, doc) {
callback(doc);
});
},
//Get All Items
findAll: function (callback) {
User.find({}, function (err, doc) {
callback(doc);
});
}
}
}
I misunderstood who the strategy worked
This is what I have
passport.use(new FacebookStrategy({
clientID : config.development.fb.appId,
clientSecret: config.development.fb.appSecret,
callbackURL: config.development.fb.url + '/#/maker/12345'
It should actually have have a callback URL of
/auth/facebook/callback
then the redirect happens in the callback

Resources