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!
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;
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);
});
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: '/'
});
}]);
angular.module('MyApp')
.controller('LoginCtrl', ['$scope', 'Auth', function($scope, Auth){
var user = Auth.authorize();
$scope.user=user;
$scope.headingTitle='Logged in page';
}]);
angular.module('MyApp')
.factory('Auth', ['$resource', function($resource){
return $resource('/auth/company', null,
{
'authorize': {method: 'GET'}
});
}]);
<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>
<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>
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);
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
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!
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With