AngularJS - Failed to instantiate module when passing parameters in url - angularjs

I have the following URL defined in my routes.js file:
app.get('/animal/:id', function(req, res, next) {
res.sendfile('./public/views/animal.html')
});
This is app.js:
var app = angular.module('adote', ['ngCookies', 'ngResource', 'ngRoute', 'ngAnimate', 'flow', 'ngTagsInput', 'ngSanitize', 'mgcrea.ngStrap'])
app.config(function($locationProvider, $routeProvider, $httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
})
This is the link for index.html (there's not much here): https://gist.github.com/larissaleite/6280ca1bcd9886e7b253
This is where I do all the configuration on my application:
app.use(cookieParser('appsecret'));
app.use(session({ secret: 'appsecret', saveUninitialized: true, cookie: { secure: true, maxAge: new Date(Date.now() + 3600000) } }));
// configuration ===============================================================
var db = mongoose.connect('mongodb://127.0.0.1:27017/Routing');
// connect to mongoDB database
mongoose.connection.once('connected', function(error){
if (error) {
console.log("Error: " + error);
} else {
console.log("Connected to the database");
}
});
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
require('./app/routes.js')(app, passport);
This is routes.js complete:
var Animal = require('./models/animal');
var User = require('./models/user');
module.exports = function(app, passport) {
require('../config/passport')(passport); // pass passport for configuration
app.get('/home', function(req, res, next) {
console.log(req.isAuthenticated());
res.sendfile('./public/views/home.html');
});
app.get('/cadastro', function(req, res, next) {
res.sendfile('./public/views/cadastro.html');
});
app.get('/animal/:id', function(req, res, next) {
res.sendfile('./public/views/animal.html')
});
app.get('/api/animals', function(req, res, next) {
console.log("GET - api/animals");
Animal.find({}, function(err, animals) {
if (err) {
console.log("erro");
res.send(err);
}
if (!animals.length) {
res.send("not found");
} else {
res.json(animals);
}
});
});
app.get('/api/animal/:id', function(req, res, next) {
//changed from query to params after removing angularjs routing
console.log("GET - api/animal/id = "+req.params.id);
Animal.findById(req.params.id, function(err, animal) {
if (err) {
console.log("erro");
res.send(err);
} else {
res.json(animal);
}
});
});
app.post('/api/animal', function(req, res, next) {
console.log("POST - api/animal");
console.log(req.body.tags);
//console.log(req.body.localizacoes);
var animal = new Animal({
nome: req.body.nome,
tipo: req.body.tipo,
tags: req.body.tags,
localizacoes: req.body.localizacoes,
descricao: req.body.descricao,
usuario_nome: "Maria Joaquina",
eventos: req.body.eventos
});
animal.save(function(err) {
if (err)
res.send(err);
res.send("success");
});
});
// =====================================
// FACEBOOK ROUTES =====================
// =====================================
// route for facebook authentication and login
app.get('/auth/facebook', passport.authenticate('facebook', { scope : 'email' }));
// handle the callback after facebook has authenticated the user
app.get('/auth/facebook/callback',
passport.authenticate('facebook', {
successRedirect : '/home',
failureRedirect : '/login'
}));
// route for logging out
app.get('/logout', function(req, res) {
console.log("logout");
req.session.regenerate(function(){
req.logout();
res.redirect('/login');
});
});
app.get('*', function(req, res) {
res.sendfile('./public/index.html');
});
}
I also have a controller called AnimalCtrl, which makes a GET request to my Express API:
$http({url: '/api/animal/:id', method: 'GET', params : { id: $routeParams.id } })
.success(function(response) {
...
}).error(function(response){
console.log("erro "+response);
});
However, I get the following error when I type in the url http://localhost:8080/animal/5429d6fa20348a6178cb1890
Uncaught SyntaxError: Unexpected token < app.js:1
Uncaught SyntaxError: Unexpected token < animal.js:1
Uncaught Error: [$injector:modulerr] Failed to instantiate module adote due to:
Error: [$injector:nomod] Module 'adote' is not available! You either misspelled the module name or forgot to load it.
If registering a module ensure that you specify the dependencies as the second argument.
What is a bit strange that I noticed that the id 5429d6fa20348a6178cb1890 is interpreted as if it was a file
This is my complete file structure:
Can someone help me with this?
Thank you!

Based on your code on github (https://github.com/larissaleite/Routing), here is an updated answer.
The issue is in your index.html file, replace:
<script src="js/app.js"></script>
by (see the leading /)
<script src="/js/app.js"></script>
Do not forget to add all your controllers to your index.html:
<script src="/js/controllers/animal.js"></script>
<script src="/js/controllers/home.js"></script>
<script src="/js/controllers/cadastro.js"></script>
Your index.html 'asks' for javascript files but receives your index.html because your server cannot 'resolve' the path your provide in your index.html. Using Chrome Dev Tools, if you look at the response from the server when asked for js/apps.js you should see it receives index.html
It is due to these lines:
app.get('*', function(req, res) {
res.sendfile('./public/index.html');
});
Define a view folder (see http://expressjs.com/api.html#app.set)
app.set('views', __dirname + '/public/views');
and remove these lines from your route.js:
app.get('/home', function(req, res, next) {
console.log(req.isAuthenticated());
res.sendfile('./public/views/home.html');
});
app.get('/cadastro', function(req, res, next) {
res.sendfile('./public/views/cadastro.html');
});
app.get('/animal/:id', function(req, res, next) {
res.sendfile('./public/views/animal.html')
});
Some other advices:
Add a .gitignore file. You do not have to track node_modules and bower_components folders
I would recommend you to use a router for your frontend app: see ngRoute or uiRouter

Related

How to render data using Express 4 + Pug/Jade + Angularjs

I'm starting learning Express and Angularjs. In the project, I want to render HTML at the server side and bind data via Angularjs but it didnt work. I saw that ng-repeat is disable in browser
<body ng-app="photoApp" class="ng-scope">
<h1>Express</h1>
<p>Welcome to Express</p>
<!-- ngView: -->
<div ng-view="" class="ng-scope">
<div id="photos" class="ng-scope">
<!-- ngRepeat: photo in vm.photos -->
</div>
</div>
</body>
, therefore no data is showed. Please help me to fix that, thanks in advanced!
Project Structure
photo
--public
----javascript
------lib
------photoApp.js
--routes
----index.js
----photo.js
--views
----partials
------photo-list.pug
----error.pug
----index.pug
----layout.pug
--app.js
Server-side code:
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 routes = require('./routes/index');
var users = require('./routes/users');
var photos = require('./routes/photos');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
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('/', routes);
app.use('/users', users);
app.use('/photos', photos);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/partials/:name', function(req, res, next){
var name = req.params.name;
res.render('partials/' + name);
});
module.exports = router;
photos.js
var express = require('express');
var router = express.Router();
var photos = [];
photos.push({
name: 'Node.js Logo',
path: 'http://nodejs.org/images/logos/nodejs-green.png'
});
photos.push({
name: 'Ryan Speaking',
path: 'http://nodejs.org/images/ryan-speaker.jpg'
});
router.get('/api/get-all', function(req, res) {
res.json(photos);
});
router.get('/', function(req, res) {
res.render('photos');
});
module.exports = router;
layout.pug
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
script(src='javascripts/lib/angular.js')
script(src='javascripts/lib/angular-route.js')
script(src='javascripts/photoApp.js')
body(ng-app="photoApp")
block content
index.pug
extends layout
block content
h1= title
p Welcome to #{title}
div(ng-view)
photo-list.pug
#photos
.photos(ng-repeat="photo in vm.photos")
h2 {{photo.name}}
img(src="{{photo.path}}")
Client-side code:
photoApp.js
var photoApp = angular.module('photoApp', ['ngRoute']);
photoApp.controller('PhotoListController', PhotoListController);
photoApp.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'partials/photo-list',
controller: 'PhotoListController',
controllerAs: 'vm'
})
.otherwise({
redirectTo: '/'
});
}]);
function PhotoListController($scope, $http) {
var vm = this;
vm.getAllPhotos = getAllPhotos;
function getAllPhotos(){
$http.get('/photos/api/get-all')
.success(function(response) { vm.photos = response.photos; })
.error(function() { console.log('Error when getting all photos'); });
}
}

Express angular refresh page error 404

I am using Angular with express. I am having problem when I try to refresh page which is not main '/', like register page http://localhost:3000/registerit gives me 404 error page not found.
Then I added this code to my server.js (express file)
app.all('/*', function(req, res) {
res.sendfile('public/index.html');
});
but It i snow always redirecting to root url. I want when I refresh page to refresh me the page I am on and to give me the same page again.
My server.js file is
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var passport = require('passport');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
//connect to mongodb
require('./models/user.js');
require('./models/item.js');
mongoose.connect("mongodb://localhost:27017/web-shop");
var index = require('./routes/index');
var api = require('./routes/api');
var authenticate = require('./routes/authenticate')(passport);
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(session({
secret: 'super duper secret'
}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
//Initialize Passport
var initPassport = require('./passport-init');
initPassport(passport);
app.use('/', index);
app.use('/api', api);
app.use('/auth', authenticate);
app.all('/*', function(req, res) {
res.sendfile('public/index.html');
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
And thi is my angular routing
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'main.html',
controller: 'itemController'
})
.when('/login', {
templateUrl: 'login.html',
controller: 'authController'
})
.when('/register', {
templateUrl: 'register.html',
controller: 'authController'
})
.when('/add_item', {
templateUrl: 'dashboard.html',
controller: 'itemController'
})
$locationProvider.html5Mode(true);
})
app.all('/*', function(req, res) {
res.sendfile('public/index.html');
});
Remove app.use('/', index); and it should work fine as it does not allow above route to send index.html every time it encounters route other than and including '/'

Angular Node Routing

I've node on server and Angular on client...
angular routes:
var todoApp = angular.module('todoApp', ['ngResource', 'ngRoute', 'ngCookies'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/', {
templateUrl: 'templates/index.html'
});
$routeProvider.when('/todo',
{
templateUrl: 'templates/todo.html',
controller:"TodoController"
});
$routeProvider.when('/admin',
{
templateUrl: 'templates/admin.html'
});
$routeProvider.otherwise({redirectTo: '/'});
$locationProvider.html5Mode(true);
});
on server side I've defined a route for '/todo'
app.use('/todo', todo);
and My todo File is
var express = require('express'),
router = express.Router(),
todo = require('../controllers/todo'),
winston = require('../../server/config/winston');
// GET users listing.
router.get('/', todo.list);
router.post('/:id', todo.save);
router.delete('/:id', todo.delete);
module.exports = router;
My Problem
if I go to home page it works fine and data shows along with loaded Pages i.e if I Enter localhost/3000/ then by default it redirects to /todo and works perfectly.
If i enter localhost/3000/todo then i only see plain text on page that is data returned from server rather then HTML page that i can see above.
I don't know whats wrong with it...
Edit
My Todo Controller
var db = require('../config/sequelize'),
StandardError = require('standard-error');
var winston = require('winston');
exports.save = function (req, res) {
if (!req.user) {
return res.send("Please Login");
}
console.log("in create", req.body);
var _task = {
task: req.body.task,
UserId: req.user.id
}
console.log(req.user);
db.Todo.create(_task).then(function (todo) {
if (!todo) {
return res.send(new StandardError('Cannot insert'));
} else {
console.log(req.body);
return res.send(todo);
}
}).catch(function (err) {
return res.send({
errors: err,
status: 500
});
});
};
exports.list = function (req, res) {
if (!req.user || req.user.isAdmin) {
return res.redirect('/');
}
console.log(db.User);
db.Todo.findAll({where: {UserId: req.user.id}}).then(function (todo) {
console.log(todo);
res.jsonp(todo);
}).catch(function (err) {
console.log(err)
res.send([{task: "No Data"}]);
});
};
exports.delete = function (req, res) {
db.Todo.destroy({
where: {
id: req.params.id,
UserId: req.user.id
}
}).then(function (response) {
console.log("deleted");
res.send(response + " Record Deleted");
//db.Todo.findAll().then(function (todo) {
// res.jsonp(todo);
// }).catch(function (err) {
// return res.render('error', {
// error: err,
// status: 500
// });
// });
});
};
May be you are confused with the angular routes and the server routes.
Use localhost/#!/todo for your todo template and localhost/todo for invoking server

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>Login via Company</p>
</div>
</div>
</div>
</div>
account.html Partial to show User data
<div>
<h1>You are logged in.</h1>
Go home<br>
Logout<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
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.
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
I never user $resource and instead use $http. You have to enable 'withCredentials' on the client's request as well. I also think you DON'T need if('OPTIONS' == req.method) as I've never needed this. One more note, you can't use a wildcard domain '*' with credentials. You'd have to explicitly allow origin 'http://127.0.0.1:8080' and make sure you're cookie uses the 127 and not localhost (you'll run into problems with cookies otherwise).
var req = {
method:'POST',
url: 'users/login',
data: {
},
withCredentials:true
};
$http(req).then(function (response) {
if( response.data.success ){
}
if( response.data.error){
}
});

NodeJs Passport isAuthenticated() returning false even after login

I'm new to Angular.js and trying to build local authentication for a website. I have gone through various sources and Authentication in Single Page Applications was very helpful. When I tried build the same in my localhost my code went in to a loop.
app.post('/login',.....) is returning user in the response but after that while loading the admin page it is checking whether the user is logged in by calling app.get('/loggedin',... ) and req.isAuthenticated() is returning false even after login and it goes to a loop. I can't understand why this is happening please help me.
Server Side code
var express = require('express');
var http = require('http');
var path = require('path');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
//==================================================================
// Define the strategy to be used by PassportJS
passport.use(new LocalStrategy(
function(username, password, done) {
if (username === "admin" && password === "admin") // stupid example
return done(null, {name: "admin"});
return done(null, false, { message: 'Incorrect username.' });
}
));
// Serialized and deserialized methods when got from session
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
// Define a middleware function to be used for every secured routes
var auth = function(req, res, next){
if (!req.isAuthenticated())
res.send(401);
else
next();
};
//==================================================================
// Start express application
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.use(express.favicon());
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.session({ secret: 'securedsession' }));
app.use(passport.initialize()); // Add passport initialization
app.use(passport.session()); // Add passport initialization
app.use(app.router);
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
//==================================================================
// routes
app.get('/', function(req, res){
res.render('index', { title: 'Express' });
});
app.get('/users', auth, function(req, res){
res.send([{name: "user1"}, {name: "user2"}]);
});
//==================================================================
//==================================================================
// route to test if the user is logged in or not
app.get('/loggedin', function(req, res) {
res.send(req.isAuthenticated() ? req.user : '0');
});
// route to log in
app.post('/login', passport.authenticate('local'), function(req, res) {
res.send(req.user);
});
// route to log out
app.post('/logout', function(req, res){
req.logOut();
res.send(200);
});
//==================================================================
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
Client Side Js file
'use strict';
/**********************************************************************
* Angular Application
**********************************************************************/
var app = angular.module('app', ['ngResource','ngRoute'])
.config(function($routeProvider, $locationProvider, $httpProvider) {
//================================================
// Check if the user is connected
//================================================
var checkLoggedin = function($q, $timeout, $http, $location, $rootScope){
// Initialize a new promise
var deferred = $q.defer();
// Make an AJAX call to check if the user is logged in
$http.get('http://localhost:3000/loggedin').success(function(user){
// Authenticated
if (user !== '0')
$timeout(deferred.resolve, 0);
// Not Authenticated
else {
$rootScope.message = 'You need to log in.';
$timeout(function(){deferred.reject();}, 0);
$location.url('/login');
}
});
return deferred.promise;
};
//================================================
//================================================
// Add an interceptor for AJAX errors
//================================================
$httpProvider.responseInterceptors.push(function($q, $location) {
return function(promise) {
return promise.then(
// Success: just return the response
function(response){
return response;
},
// Error: check the error status to get only the 401
function(response) {
if (response.status === 401)
$location.url('/login');
return $q.reject(response);
}
);
}
});
//================================================
//================================================
// Define all the routes
//================================================
$routeProvider
.when('/', {
templateUrl: 'views/main.html'
})
.when('/admin', {
templateUrl: 'views/admin.html',
controller: 'AdminCtrl',
resolve: {
loggedin: checkLoggedin
}
})
.when('/login', {
templateUrl: 'views/login.html',
controller: 'LoginCtrl'
})
.otherwise({
redirectTo: '/login'
});
//================================================
}) // end of config()
.run(function($rootScope, $http){
$rootScope.message = '';
// Logout function is available in any pages
$rootScope.logout = function(){
$rootScope.message = 'Logged out.';
$http.post('http://localhost:3000/logout');
};
});
/**********************************************************************
* Login controller
**********************************************************************/
app.controller('LoginCtrl', function($scope, $rootScope, $http, $location) {
// This object will be filled by the form
$scope.user = {};
// Register the login() function
$scope.login = function(){
$http.post('http://localhost:3000/login', {
username: $scope.user.username,
password: $scope.user.password,
})
.success(function(user){
// No error: authentication OK
$rootScope.message = 'Authentication successful!';
$location.url('/admin');
})
.error(function(){
// Error: authentication failed
$rootScope.message = 'Authentication failed.';
$location.url('/login');
});
};
});
/**********************************************************************
* Admin controller
**********************************************************************/
app.controller('AdminCtrl', function($scope, $http) {
// List of users got from the server
$scope.users = [];
// Fill the array to display it in the page
$http.get('http://localhost:3000/users').success(function(users){
for (var i in users)
$scope.users.push(users[i]);
});
});
You need to allow cookies to be set in cross domain
In express
res.header('Access-Control-Allow-Credentials', true);
And in ajax setup
xhrFields: {
withCredentials: true
}
You can find relevant answers here and here
I think rdegges has part of the idea since cookies and session variables are part of what makes the state management work. I think that bodyParser is also required but I omitted it here.
I'm using Passport on my website (authenticating to a MongoDB users table) and here are excerpts from my code.
/server.js:
var cookieParser = require('cookie-parser');
...
var passport = require('passport');
var expressSession = require('express-session');
var initPassport = require('./passport/init');
initPassport(passport);
...
self.app.use(cookieParser());
self.app.use(expressSession({secret: 'MYSECRETISVERYSECRET', saveUninitialized: true, resave: true}));
self.app.use(passport.initialize());
self.app.use(passport.session());
...
var routes = require('./routes/index')(passport);
self.app.use('/', routes);
/passport/init.js:
var login = require('./login');
var signup = require('./register');
var User = require('../models/user');
module.exports = function(passport) {
// Passport needs to be able to serialize and deserialize users to support persistent login sessions
passport.serializeUser(function(user, done) {
console.log('serializing user: ');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
console.log('deserializing user:', user);
done(err, user);
});
});
// Setting up Passport Strategies for Login and SignUp/Registration
login(passport);
signup(passport);
}
/routes/index.js:
var passport = require('passport');
var User = require('../models/user');
...
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/login');
}
For what it's worth I'm not seeing your isValidated() function anywhere defined.
Can be so many things.
1.) Order as in PassportJS Facebook login isAuthenticated returns false even though authentication succeeds (order seems correct though in your case).
2.) No req.login() as in Passport and Passport Local req.isAuthenticated always returns false
In this case I opt for the latter but for a different reason than in that question.
You have provided your own LocalStrategy. To make the user log in, you will have to call req.login() yourself. Just as if you would define your own custom callback, as described in the passport documentation: http://passportjs.org/guide/authenticate/.
I had the same issue by forgetting to add
request.login()
on
app.post('/login',
function(request, response, next) {
console.log(request.session)
passport.authenticate('login',
function(err, user, info) {
if(!user){ response.send(info.message);}
else{
request.login(user, function(error) {
if (error) return next(error);
console.log("Request Login supossedly successful.");
return response.send('Login successful');
});
//response.send('Login successful');
}
})(request, response, next);
}
);
also make sure you have the following order for initialization
var session = require('express-session');
// required for passport session
app.use(session({
secret: 'secrettexthere',
saveUninitialized: true,
resave: true,
// using store session on MongoDB using express-session + connect
store: new MongoStore({
url: config.urlMongo,
collection: 'sessions'
})
}));
// Init passport authentication
app.use(passport.initialize());
// persistent login sessions
app.use(passport.session());
Is your browser keeping your session cookie around? It sounds to me as if your browser isn't holding onto your session cookie after login, which is why subsequent requests to /loggedin are failing.
In my case I tried solution suggested by JMeas to manually call session saving, but it didn't work
https://github.com/jaredhanson/passport/issues/482
req.session.save(function() { successRedirect(); })
After some experiments, I just moved app.use(session({ ... })) at the top of all middleware calls and now req.isAuthenticated() works as expected. I presume, session setup should go as the first middleware or at least before setting cookies.
Broken call :
var app = express();
app.use(query.json());
app.use(query.urlencoded({ extended: false }));
app.use(cookies());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use(session({
secret: 'card',
resave: true,
saveUninitialized: true
}));
app.use('/', routes); // this is where I call passport.authenticate()
Fixed call :
app.use(session({
secret: 'card',
resave: true,
saveUninitialized: true
}));
app.use(query.json());
app.use(query.urlencoded({ extended: false }));
app.use(cookies());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', routes);

Resources