node.js api express oauth passport.js

Haga una API segura a través de passport.js y express.js(node.js)



oauth (2)

Tengo un problema específico, a menos que no esté haciendo las cosas de la manera correcta.

Tengo una aplicación con 2 lados, un cliente (sitio html) y una API (construida con Express + mongodb). La API tendrá que ser accedida de forma segura. Ambos están en diferentes dominios, por ahora digamos que mi sitio está en domain.com y mi API está en api.com:3000.

He agregado el pasaporte para obtener un token de acceso de Github, ya que estoy creando a mis usuarios con sus datos, para que pueda tener un "Iniciar sesión con Github" básicamente.

Mi proceso actual es:

1) el cliente (el sitio), abre una ventana emergente en la API

window.open("http://api.com:3000/oauth")

2) El servidor express, inicie el proceso de pasaporte:

app.get(''/oauth'', passport.authenticate(''github''), function(req, res) { });

Para la estrategia, utilicé este código .

3) Redirijo la devolución de llamada a una url que cierra la ventana emergente (javascript con un window.close ()):

app.get(''/oauth/callback'', passport.authenticate(''github'', { failureRedirect: ''/'' }), function(req, res) { res.redirect(''/auth_close''); });

En ese momento, todo está bien, ahora estoy registrado en la API. Mi problema es cómo devolver los datos al cliente, ya que el cliente todavía no sabe nada sobre accessToken, usuario o identificación de usuario.

Entonces, desde el cliente (el sitio que abre la ventana emergente), probé diferentes enfoques:

  • Obtención de un valor de la ventana emergente: no funciona debido a la redirección, pierdo la pista de la información de javascript de la ventana emergente

  • llamando a mi API para obtener el "usuario actual" en la sesión, como http://api.com:3000/current Una solicitud más, no ideal, pero esta funciona. Sin embargo, todavía tengo un problema.

Esta / url actual está devolviendo al usuario si lo accedo desde el navegador, porque el navegador envía en el encabezado la solicitud de la cookie de sesión rápida:

Cookie:connect.sid=s%3AmDrM5MRA34UuNZqiL%2BV7TMv6.Paw6O%2BtnxQRo0vYNKrher026CIAnNsHn4OJdptb8KqE

El problema es que necesito hacer esta solicitud desde jquery o similar, y ahí es donde falla porque la sesión no se envía. Entonces el usuario no es devuelto:

app.get(''/current'', function() { // PROBLEM HERE, req.user is undefined with ajax calls because of the session! });

Encontré una forma de hacerlo funcionar, pero no estoy contento porque tendré problemas de CORS en varios navegadores, lo que se agrega a Express:

res.header("Access-Control-Allow-Credentials", "true");

Y agregue el campo withCredentials en una llamada jquery ajax, como se explica here .

Un mapa de los pares fieldName-fieldValue para establecer en el objeto XHR nativo. Por ejemplo, puede usarlo para establecer withCredentials en true para las solicitudes de dominios cruzados si es necesario.

$.ajax({ url: a_cross_domain_url, xhrFields: { withCredentials: true } });

Tampoco estoy contento con esto ya que estoy perdiendo el comodín en mi encabezado: Access-Control-Allow-Origin , necesito especificar un dominio, como se explica here .

Por lo tanto, no estoy seguro del enfoque que debo tomar aquí, lo único que necesito es que el cliente reciba un AccessToken o un ID de usuario del proceso de pasaporte o de la cuenta. La idea es usar ese token en cada llamada a la API para validar las llamadas.

¿Cualquier pista?


Antes de configurar algo en la aplicación Express, use lo siguiente (exactamente lo mismo) para establecer el encabezado de respuesta para el dominio cruzado:

app.use(function(req, res, next) { res.header(''Access-Control-Allow-Credentials'', true); res.header(''Access-Control-Allow-Origin'', req.headers.origin); res.header(''Access-Control-Allow-Methods'', ''GET,PUT,POST,DELETE''); res.header(''Access-Control-Allow-Headers'', ''X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept''); if (''OPTIONS'' == req.method) { res.send(200); } else { next(); } });


Tuve el mismo problema. Estaba utilizando la estrategia local en la página de inicio de sesión y luego comprobé si el usuario estaba en la sesión en otras solicitudes.

Como usted dice, la solución es usar CORS para que la ID de sesión se pase en una cookie usando XMLHTTPRequest.

En lugar de usar el CORS que todavía no funciona en todos los navegadores, decidí usar tokens de acceso en otras solicitudes. El flujo de trabajo que utilicé es el siguiente:

POST /login

  • El nombre de usuario y la contraseña se pasan en el cuerpo.
  • Autenticación mediante estrategia local.
  • La respuesta devuelve el objeto de usuario, incluido el access_token

GET / endpoint / abc123? Access_token = abcdefg

  • Token obtenido de la respuesta de inicio de sesión
  • Autenticación utilizando la estrategia del portador (en el pasaporte-http-bearer)

Las sesiones ahora no son necesarias en Express.

Espero que esta alternativa ayude.