La autenticación está devolviendo “401 (no autorizado)” cuando no debería

Estoy configurando una funcionalidad de autenticación por primera vez y obtengo algunos resultados inesperados después de que un usuario haya iniciado sesión. Un colega me ha dado una aplicación con autenticación de trabajo para modelar mi aplicación después y parece que todo lo que he hecho es correcto .

Estoy utilizando AngularJS en el front-end, el framework de back-end de SailsJS y el middleware de autenticación PassportJS .

Mi fuente es (por ahora) almacenada públicamente … la API de back-end está en Github aquí ( API Github ) y el código de usuario se encuentra aquí ( Gitub de frente )

Lo que básicamente sucede es que el usuario

  1. Golpea el botón de inicio de sesión, que activa esta función.

    login: function (credentials) { return baseAuth.customPOST(credentials, 'login').then(function (user) { $log.debug('User logged in: ', user); isAuthenticated = true; return user; }); }, 
  2. La lógica del controlador para ese customPOST es esta

     login: function (req, res, next) { passport.authenticate('local', function (err, user, info) { if (err) { return res.json(err); } else if (user) { req.logIn(user, function (err) { if (err) { return res.json(err); } return res.json(user); }); } else { return res.json(400, info); } })(req, res); }, 
  3. En ese paso, el pasaporte debe hacer su trabajo e iniciar sesión en el usuario.

     passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function(email, password, next) { User.findOne({ email: email }) .exec(function (err, user) { if (err) { return next(err); } if (user) { if (user.activated) { bcrypt.compare(password, user.password, function (err, valid) { if (err) { next(err); } if (valid) { return next(null, user, { message: 'Logged In' }); } else { return next(null, false, { message: 'Incorrect password'}); } }); } else { next(null, false, { message: 'User is not activated. Please contact admins.'}); } } else { next(null, false, { message: 'Could not find user with email ' + email }); } }); } )); 

En la consola, siempre entiendo que esto tiene éxito.

La consola lee:

 User logged in: Object {firstName: "John", lastName: "Doe", email: "[email protected]", activated: true, isUser: true…} 
  1. Entonces, mi comprensión de lo que sucede se vuelve un poco borrosa. Sé que la aplicación intenta ver si el usuario está autenticado. IsAuthenticated se activa, lo que se ve así en AngularJS:

     isAuthenticated: function (force) { var deferred = $q.defer(); if (isAuthenticated && currentUser) { deferred.resolve(currentUser); } else { return baseAuth.customGET('authenticated').then(function (user) { deferred.resolve(currentUser); isAuthenticated = true; currentUser = user; return user; }); } return deferred.promise; } 
  2. Golpea esta acción en el backend UserController.

     isAuthenticated: function (req, res) { if (req.isAuthenticated() && req.user.isUser) { return res.json(req.user); } else { return res.send(401); } }, 

Luego falla 🙁 GET http://localhost:1337/user/authenticated 401 (Unauthorized) Ni req.isAuthenticated ni req.user.isUser pass. Los he separado para probarlos individualmente y ninguno de ellos es verdadero “. IsUser “es un valor que por defecto es verdadero y es así que debería ser cierto para todos los usuarios de la base de datos. req.isAuthenticated también falla, lo cual no entiendo completamente.

¿Alguien tiene alguna idea de mi problema? ¿Qué he hecho mal aquí?

Si su aplicación frontend tiene un origen diferente al de su aplicación backend, las solicitudes de AJAX no incluirán la cookie de sesión y req.isAuthenticated() nunca devolverá true.

Utilice las opciones withCredentials para forzarlo.

 $http({ withCredentials: true, ... }) 

Parece que Restangular usa las mismas opciones:

https://github.com/mgonto/restangular#setdefaulthttpfields

https://docs.angularjs.org/api/ng/service/$http#usage

Editar: También debe verificar la configuración del lado del servidor como lo indica idbehold


Según lo sugerido por Matan, realmente deberías intentarlo con el generador sails-genera-auth en el lado del servidor.

https://github.com/sails101/even-more-passport

https://github.com/kasperisager/sails-generate-auth

Por lo general, un error 401 “no autorizado” en realidad se refiere a un error de credenciales en lugar de un error 403 que se refiere a un error real no autorizado (prohibido), por lo que primero debe verificar a su cliente con Postman para probarlo y luego pasar al cliente.

Sin embargo, le recomendaría encarecidamente que se deslice desde ese proyecto github y use este tutorial para implementar su autenticación passport.js, ya que solo necesita ejecutar 2 líneas de código y algunas configuraciones en lugar de ensuciarse con el código: https: / /www.bearfruit.org/2014/07/21/tutorial-easy-authentication-for-sails-js-apps/

Dado que passport.js funciona con el concepto subyacente de estrategias, debe asegurarse de que se autentica utilizando el correcto. No veo en ninguna parte una estrategia llamada ‘usuario’.

 passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function(email, password, next) { User.findOne({ email: email }) .exec(function (err, user) { if (err) { return next(err); } if (user) { if (user.activated) { bcrypt.compare(password, user.password, function (err, valid) { if (err) { next(err); } if (valid) { return next(null, user, { message: 'Logged In' }); } else { return next(null, false, { message: 'Incorrect password'}); } }); } else { next(null, false, { message: 'User is not activated. Please contact admins.'}); } } else { next(null, false, { message: 'Could not find user with email ' + email }); } }); } )); 

debe ser cambiado a

 passport.use('user', new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, function(email, password, next) { User.findOne({ email: email }) .exec(function (err, user) { if (err) { return next(err); } if (user) { if (user.activated) { bcrypt.compare(password, user.password, function (err, valid) { if (err) { next(err); } if (valid) { return next(null, user, { message: 'Logged In' }); } else { return next(null, false, { message: 'Incorrect password'}); } }); } else { next(null, false, { message: 'User is not activated. Please contact admins.'}); } } else { next(null, false, { message: 'Could not find user with email ' + email }); } }); } )); 

También asegúrese de que el indicador de usuario de su usuario esté establecido en verdadero.