问题描述
我从这里产生的角fullstack应用程序 -
我使用的是相同的目录结构角fullstack。
现在我试图与Facebook SDK来验证用户身份,做下面的步骤 -
1)指定护照Facebook登录策略
//创建的auth / Facebook的/ index.js使用严格的;VAR前preSS =要求('前preSS');
VAR护照=要求('护照');
VAR AUTH =要求('../ auth.service');VAR路由器=前press.Router();路由器
获得('/',passport.authenticate(的Facebook',{
范围:['邮件','public_profile','user_friends','user_events'],
failureRedirect:'/',
会议:假的
})) 获得('/回调',passport.authenticate(的Facebook',{
failureRedirect:'/',
会议:假的
}),auth.setTokenCookie);module.exports =路由器;//创建的auth / Facebook的/ passport.jsVAR护照=要求('护照');
VAR FacebookStrategy =要求('护照Facebook的)战略。
无功配置=要求('../../配置/环境);
VAR JWT =要求('jsonwebtoken');
exports.setup =功能(用户配置){
passport.use(新FacebookStrategy({
clientID的:config.facebook.clientID,
clientSecret:config.facebook.clientSecret,
callbackURL:config.facebook.callbackURL
},
功能(的accessToken,refreshToken,型材,完成){
User.findOne({'facebookId':profile.id},功能(ERR,用户){
如果(ERR)回做(ERR);
如果(用户){
返回完成(NULL,用户);
}其他{
变种NEWUSER = {};
NEWUSER ['facebookId'] = profile.id;
NEWUSER ['providerData'] = {
名称:Facebook的,
用户名:profile.username,
显示名:profile.displayName,
性别:profile.gender,
profileUrl:profile.profileUrl
};
NEWUSER ['名'] = profile.name.givenName? profile.name.givenName:'';
NEWUSER [电子邮件] = profile.emails.length大于0? profile.emails [0] .value的:做(的电子邮件没有找到');
功能generatePassword(){
变种长度= 8,
字符集=abcdefghijklnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
retVal的=;
对于(VAR I = 0,N = charset.length; I<长度; ++ I){
retVal的+ = charset.charAt(Math.floor(的Math.random()* N));
}
返回retVal的;
} NEWUSER ['密码'] = generatePassword();
NEWUSER ['角色'] ='用户';
VAR用户=新用户(NEWUSER);
user.save(函数(ERR,用户){
如果(ERR){执行console.log(ERR); DONE(ERR); }
VAR令牌= jwt.sign({_ ID:user._id},config.secrets.session,{expiresInMinutes:60 * 5});
res.json({令牌:令牌});
});
}
});
}
));
};//为Facebook模块认证/ index.js添加的条目
使用严格;
VAR前preSS =要求('前preSS');
VAR护照=要求('护照');
无功配置=要求('../配置/环境);
VAR用户=要求('../ API /用户/ user.model');//护照配置
要求('./本地/护照')设置(用户,配置)。
要求('./的Facebook /护照')设置(用户,配置)。VAR路由器=前press.Router();router.use('/本地,要求('./本地'));
router.use('/ Facebook的,需要('./ Facebook的'));module.exports =路由器;
在客户端的我做了以下修改 -
//从安装使用https://github.com/GoDisco/ngFacebook鲍尔安装NG-的Facebook NG-的Facebook
//在角应用模块添加ngFacebook
//中的app.config设置应用程序ID - $ facebookProvider.setAppId('XXXXXXXXXXXX');
然后添加这一点 - 在app.run
app.run(函数($ rootScope,$位置,验证){ (函数(D,S,id)的{
变种JS,FJS = d.getElementsByTagName(多个)[0];
如果(d.getElementById(ID)){
返回;
}
JS = d.createElement(S);
js.id = ID;
js.src =//connect.facebook.net/en_US/sdk.js;
fjs.parentNode.insertBefore(JS,FJS);
}(文件,脚本,Facebook的jssdk')); //如果重定向路由需要身份验证登录,你没有登录
$ rootScope。在$('$ stateChangeStart',函数(事件,旁边){
Auth.isLoggedInAsync(功能(的loggedIn){
如果(next.authenticate&安培;&安培;!的loggedIn){
$ location.path('/门禁/登入');
}
});
});
})
于是最后调用 / auth /中的Facebook
从我的客户现在我在,我能够将其保存在数据库中的用户登录后获得来自Facebook的数据,但主页总是被重定向到登录状态,而不是仪表盘。
我有以下HTTP拦截在我的客户端应用程序 -
app.factory('authInterceptor',函数($ rootScope,$ Q $的CookieStore){
返回{
//授权令牌添加到页眉
要求:功能(配置){
config.headers = config.headers || {};
如果($ cookieStore.get('令牌')){
config.headers.Authorization ='承载'+ $ cookieStore.get('令牌');
}
返回配置;
}, //拦截401S和重定向您登录
responseError:功能(响应){
如果(response.status === 401){
$ cookieStore.remove('令牌');
返回$ q.reject(响应);
}
否则,如果(response.status === 403){
$ cookieStore.remove('令牌');
返回$ q.reject(响应);
}否则如果(response.status === 405){
$ cookieStore.remove('令牌');
返回$ q.reject(响应);
}
其他{
返回$ q.reject(响应);
}
}
};
})
现在经过我和我的facebook账号,密码,当我收到来自Facebook的回调。这是越来越重定向到相同的登录状态,即使再当API / API /用户/我是给我登录的信息在我的浏览器控制台 -
<$p$p><$c$c>{\"_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\"]}所以,我想护照未正确设置授权头或没有比被重定向我到登录页面,我的HTTP拦截其他事只有
我如何调试这个问题,或找出我错了,还是失去了一些东西?
在我看来我preFER只是检查服务器是否仍然有你的sesssion信息。
在你的路由,你可以做检查
时,('/ URL',{
templateUrl:部分,
控制器:控制器,
解析:{的loggedIn:checkLoggedin}})。
只要创建你的函数checkLoggedin这样
VAR checkLoggedin =功能($ Q $ HTTP,$位置){\r
变种推迟= $ q.defer();\r
\r
$ http.get('/的loggedIn'),然后(功能(响应){\r
deferred.resolve();\r
},函数(响应){\r
deferred.reject();\r
$ location.path('/家);\r
});\r
\r
返回deferred.promise;\r
}
\r
基本上你在这里做一个承诺。你说这里到后端,检查我将等待后端送我回一个响应。如果响应是200让它们在网页或其他重新定向到家庭。
您的后端应返回401(取消授权)或200(成功)响应让您的前端知道是否允许页面上的用户。
功能(REQ,RES){\r
\r
如果(req.isAuthenticated()==真){\r
res.status(200)。发送(验证);\r
}其他{\r
res.status(401)。发送(无法验证);\r
}\r
\r
}
\r
您可以查看这里的决心更多信息
的决心将在加载你的看法之前运行传递给它的所有依赖关系。
这将让你做出一个HTTP请求到你的后端和护照检查,看看如果会话仍然存在。
角具有使一个http请求到后端每次以确保用户在确实记录
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 ?
In my opinion I prefer just checking whether the server still has your sesssion information.
In your routing you can do check
when('/url', {
templateUrl: 'partial',
controller: 'controller',
resolve: { loggedin: checkLoggedin}}).
Just create your function checkLoggedin like this
var checkLoggedin = function($q, $http, $location){
var deferred = $q.defer();
$http.get('/loggedin').then(function(response){
deferred.resolve();
},function(response){
deferred.reject();
$location.path('/home');
});
return deferred.promise;
}
Basically your making a promise here. Your saying here go to the backend and check I will wait for the backend to send me back a response. If the response is 200 let them on the page or else redirect to home.
Your back-end should return a 401 (unauthorize) or 200 (success) response letting your front-end know whether to let the user on the page.
function(req,res){
if (req.isAuthenticated() == true) {
res.status(200).send("Authenticate.");
}else{
res.status(401).send("Not Authenticate");
}
}
You can check more info about resolve here
The resolve will run all dependencies that is passed to it before loading your view.
This will allow you to make a http request to your back end and verify with passport to see if the session is still there.
Angular has to make a http request to the backend everytime to make sure that the user is indeed logged in.
这篇关于与角fullstack应用在角fullstack结构不保存用户会话护照Facebook的整合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!