Angular问题和“否”Access-Control-Allow-Origin'标题“ – 使用OAuth 2,Passport,Express和Node

我有一个使用节点上运行的OAuth 2的Web应用程序。 使用EJS模板,我能够正确地创build一个工作stream,提示用户login,validation,然后执行“GetUser”GET命令并将输出转储到屏幕上。 最近我试图删除EJS,并希望得到AnguarJS的工作。

目前我已经删除了EJS并实现了Angular,但是有很多奇怪的事情发生,我不知道为什么!

当我的用户点击“login”,他们应该被带到另一个网站,他们login到使用OAuth 2.这个过程工作正常与EJS节点,但是我的angular度控制器加载,正确的部分被加载,但没有数据。 使用Chrome DEV工具查看此过程,我看到以下错误

XMLHttpRequest cannot load http://website/oauth/authorize?... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. 

更奇怪的是,在networking标签中,我可以看到正确的请求URL! 如果我复制并粘贴到另一个选项卡我的“GetUser”命令执行,但然后节点崩溃,我的网页失败。

我试过不同的浏览器,启用CORS,configurationCORS。 我知道问题是与Angular,因为我可以成功地使用相同的代码与EJS。 我已经把我的Angular代码放在下面,任何帮助将不胜感激!

服务器端

app.js

 var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var config = require('./config.js') var passport = require('passport'); var OAuth2Strategy = require('passport-oauth').OAuth2Strategy; var session = require('express-session'); var index = require('./routes/index'); var login = require('./routes/login'); var logout = require('./routes/logout'); passport.serializeUser(function(user, done) {done(null, user); }); passport.deserializeUser(function(obj, done) {done(null, obj); }); // config passport.use('Company', new OAuth2Strategy({ authorizationURL: config.authorizationURL, tokenURL: config.tokenURL, clientID: config.clientID, clientSecret: config.clientSecret, callbackURL: config.callbackURL, passReqToCallback: true }, function(req, accessToken, refreshToken, profile, done) { process.nextTick(function () { // store access token req.session.accessToken=accessToken; return done(null, profile); }); } )); var app = express(); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use(session({secret: 'secret'})) app.use(passport.initialize()); app.use(passport.session()); // configure Express app.get('/api/login', ensureAuthenticated, login.execute); app.get('/api/logout', logout.execute); app.get('/auth/company', passport.authenticate('company'), function(req, res){ }); app.get('/auth/company/callback', passport.authenticate('company', { failureRedirect: '/' }), function(req, res) { console.log('comming back from company'); res.redirect('/api/login'); }); app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); function ensureAuthenticated(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect('/') } module.exports = app; 

Login.js(路线)

 var request = require('request'); exports.execute = function (req, res) { console.log(req.user); console.log(req.app.get('accessToken')); var accessToken = req.session.accessToken; console.log("accessToken in loginjs" + accessToken); if(accessToken){ var options = { url: 'http://company/getCurrentUser', headers: { Authorization: 'bearer ' + accessToken } }; request.get(options, function(error, response, body){ if(error){ console.log('login.js inside error' + error); res.json('login.js inside error' + error); return; } console.log(response); res.render('account', { user: response }); }); }else{ res.render('account', { user: req.user }); } } 

万维网

 var debug = require('debug')('myApp'); var app = require('../app'); app.set('port', process.env.PORT || 8080); var server = app.listen(app.get('port'), function() { debug('Express server listening on port ' + server.address().port); }); 

客户端

app.js(angular)##

 angular.module('MyApp', ['ngCookies', 'ngResource', 'ngMessages', 'ngRoute', 'mgcrea.ngStrap']) .config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) { $locationProvider.html5Mode(true); $routeProvider .when('/', { templateUrl: 'views/home.html', controller: 'MainCtrl' }) .when('/login', { templateUrl: 'views/account.html', controller: 'LoginCtrl' }) .otherwise({ redirectTo: '/' }); }]); 

login.js控制器

 angular.module('MyApp') .controller('LoginCtrl', ['$scope', 'Auth', function($scope, Auth){ var user = Auth.authorize(); $scope.user=user; $scope.headingTitle='Logged in page'; }]); 

auth.js服务

 angular.module('MyApp') .factory('Auth', ['$resource', function($resource){ return $resource('/auth/company', null, { 'authorize': {method: 'GET'} }); }]); 

home.html部分路由到公司Oauth2

 <div class="container"> <div class="panel panel-default"> <div class="panel-body"> <div class="text-center"> <p><a href="/login">Login via Company</a></p> </div> </div> </div> </div> 

account.html部分显示用户数据

 <div> <h1>You are logged in.</h1> <a href="/">Go home</a><br> <a href="/api/logout">Logout</a><br> <p>Dumping User: {{user}}</p> </div> 

编辑

我已经试过了,没有成功

 var allowCrossDomain = function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X- Requested-With, Access-Control-Allow-Origin'); res.header("Access-Control-Max-Age", "86400"); // 24 hours if ('OPTIONS' == req.method) { res.send(200); } else { next(); } }; var app = express(); app.use(allowCrossDomain); 

编辑2:

我做了更多的挖掘,也注意到Angular没有被列为启动第二个URL。 它几乎就像是将callbackURL重新路由为一个单独的调用。 我附上了下面的图片 Chrome浏览器返回调用的开发工具

编辑3:

我一直在这个工作,但不知道为什么Angular剥离我的标题! 任何额外的input将不胜感激!

编辑4:

我发现我可以通过将下面的代码添加到Loginbutton来让网页加载路线而不是Angular。 这样做后,指向链接到/ auth /公司,而不是API /login我成功地redirect到login页面!

 <div class="container"> <div class="panel panel-default"> <div class="panel-body"> <div class="text-center"> <p><a target="_self" href="/auth/company">Login via Company</a></p> </div> </div> </div> </div> 

然而,战斗继续,因为我login后,我redirect到下面的图片 – 节点内部收到数据,但应用程序死亡,并没有显示/帐户页面。 从Oauth 2身份验证返回后的页面

我从来没有使用$resource ,而是使用$http 。 您还必须在客户的请求中启用“withCredentials”。 我也认为你不需要if('OPTIONS' == req.method)因为我从来不需要这个。 还有一点需要注意,你不能在凭证上使用通配符域“*”。 你必须明确地允许起源“ http://127.0.0.1:8080 ”,并确保你的cookie使用127而不是本地主机(否则你会遇到问题,否则cookie)。

  var req = { method:'POST', url: 'users/login', data: { }, withCredentials:true }; $http(req).then(function (response) { if( response.data.success ){ } if( response.data.error){ } });