I have an angular-fullstack app generated from here -
https://github.com/angular-fullstack/generator-angular-fullstack
I am using the same directory structure as angular-fullstack.
Now I am trying to authenticate users with facebook sdk and did the following steps -
1) specify passport facebook login strategy
// created auth/facebook/index.js
'use strict';
var express = require('express');
var passport = require('passport');
var auth = require('../auth.service');
var router = express.Router();
router
.get('/', passport.authenticate('facebook', {
scope: ['email', 'public_profile', 'user_friends', 'user_events'],
failureRedirect: '/',
session: false
}))
.get('/callback', passport.authenticate('facebook', {
failureRedirect: '/',
session: false
}), auth.setTokenCookie);
module.exports = router;
// created auth/facebook/passport.js
var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;
var config = require('../../config/environment');
var jwt = require('jsonwebtoken');
exports.setup = function (User, config) {
passport.use(new FacebookStrategy({
clientID: config.facebook.clientID,
clientSecret: config.facebook.clientSecret,
callbackURL: config.facebook.callbackURL
},
function(accessToken, refreshToken, profile, done) {
User.findOne({'facebookId':profile.id}, function(err, user){
if(err) return done(err);
if(user) {
return done(null, user);
} else {
var newUser = {};
newUser['facebookId'] = profile.id;
newUser['providerData'] = {
name: 'facebook',
username: profile.username,
displayName: profile.displayName,
gender: profile.gender,
profileUrl: profile.profileUrl
};
newUser['name'] = profile.name.givenName ? profile.name.givenName: '';
newUser['email'] = profile.emails.length>0? profile.emails[0].value : done('email not found');
function generatePassword() {
var length = 8,
charset = "abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
retVal = "";
for (var i = 0, n = charset.length; i < length; ++i) {
retVal += charset.charAt(Math.floor(Math.random() * n));
}
return retVal;
}
newUser['password'] = generatePassword();
newUser['role'] = 'user';
var user = new User(newUser);
user.save(function (err, user) {
if (err) { console.log(err); done(err); }
var token = jwt.sign({_id: user._id }, config.secrets.session, { expiresInMinutes: 60 * 5 });
res.json({ token: token });
});
}
});
}
));
};
// added entry in auth/index.js for facebook module
'use strict';
var express = require('express');
var passport = require('passport');
var config = require('../config/environment');
var User = require('../api/user/user.model');
// Passport Configuration
require('./local/passport').setup(User, config);
require('./facebook/passport').setup(User, config);
var router = express.Router();
router.use('/local', require('./local'));
router.use('/facebook', require('./facebook'));
module.exports = router;
In client side I made the following changes -
// installed ng-facebook from https://github.com/GoDisco/ngFacebook using bower install ng-facebook
// added ngFacebook in Angular App module
// set App Id in app.config -
$facebookProvider.setAppId('XXXXXXXXXXXX');
Then added this - in app.run
app.run(function ($rootScope, $location, Auth) {
(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
// Redirect to login if route requires auth and you're not logged in
$rootScope.$on('$stateChangeStart', function (event, next) {
Auth.isLoggedInAsync(function (loggedIn) {
if (next.authenticate && !loggedIn) {
$location.path('/access/signin');
}
});
});
})
Then finally calling /auth/facebook
from my client now I am getting the data from facebook after a user logs in and I am able to save it in Database, but the homepage always gets redirected to login state and not the dashboard.
I have the following http interceptors in my client app -
app.factory('authInterceptor', function ($rootScope, $q, $cookieStore) {
return {
// Add authorization token to headers
request: function (config) {
config.headers = config.headers || {};
if ($cookieStore.get('token')) {
config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
}
return config;
},
// Intercept 401s and redirect you to login
responseError: function (response) {
if (response.status === 401) {
$cookieStore.remove('token');
return $q.reject(response);
}
else if (response.status === 403) {
$cookieStore.remove('token');
return $q.reject(response);
} else if (response.status === 405) {
$cookieStore.remove('token');
return $q.reject(response);
}
else {
return $q.reject(response);
}
}
};
})
Now after I login with my facebook account, when I receive the callback from facebook. It is getting redirected to the same login state again even when the API /api/users/me is giving me the logged in information in my browser console -
{"_id":"569bc8d6b0c2e8315539539e","facebookId":"XXXXX","name":"Harshit","email":"XXXX","__v":0,"providerData":{"name":"facebook"},"messages":[],"notifications":[],"subjects":[],"date":"2016-01-17T17:01:10.000Z","role":["user"]}
So, I am thinking passport is not setting the authorization headers properly or there is something other than my http interceptor that is redirecting me to the login page only
How can I debug this issue or find out where I am going wrong, or missing something ?