Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular issues and "No 'Access-Control-Allow-Origin' header" - Using OAuth 2, Passport, Express and Node

I have a web application that uses OAuth 2 running on Node. Using EJS templates I was able to properly create a workflow that prompts a user to login, authenticate, and then performs a "GetUser" GET command and dumps the output to the screen. Recently I have attempted to remove EJS and want to get AnguarJS working.

Currently I have removed EJS and implemented Angular, however with angular many strange things happen and I cannot figure out why!

When my user clicks "Login" they are supposed to be brought to another website that they login to using OAuth 2. This process works fine on Node with EJS, however with angular my controller loads, the correct partial is loaded but there is no data. Reviewing this process with Chrome DEV tools I see the following error

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.

What is even weirder is that in the network tab I can see the correct Request URL! If I copy and paste this URL into another tab my "GetUser" command executes, but then node crashes and my page fails.

I have attempted different browsers, enabling CORS, and configuring CORS. I know the issue is with Angular as I can successfully use the same code with EJS. I have put my Angular code below, any assistance would be appreciated!

Server Side

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 (Route)

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 });
    }   
}

www

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);
});

Client Side

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 Controller

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

auth.js Service

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

home.html Partial to route to company 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 Partial to show User data

<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>

edit

I have tried the follow with no success

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);

Edit 2:

I did some more digging and also noticed that Angular is not listed as initiating the second URL. Its almost as if angular is re-routing the callback URL as a separate call of its own. I have attached the below picture Dev Tools for Chrome of returned calls

Edit 3:

I have continued to work on this but cannot figure out why Angular is stripping out my headers! Any Additional input would be greatly appreciated!

Edit 4:

I found that I can have the webpage load the route instead of Angular by adding the code below to the Login button. After doing this and pointing the link to /auth/company rather than to api/login I get successfully redirected to the login page!

<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>  

However the battle continues, as after I login I get redirected to the below picture - inside of node I receive the data however the application dies and does not show the /account page. Page after coming back from Oauth 2 Authentication

like image 477
Kent0111 Avatar asked Dec 19 '14 01:12

Kent0111


1 Answers

Can you try enabling CORS in express server

npm install cors

app.js

var cors = require('cors')
var app = express()

app.use(cors())

Reference to this link

like image 137
Zaw Hlaing Bwar Avatar answered Oct 20 '22 02:10

Zaw Hlaing Bwar