node.js - management - passport js session
Facebook-pasaporte con JWT (3)
He estado usando Passport en mi servidor para la autenticación de usuarios. Cuando un usuario inicia sesión localmente (con un nombre de usuario y contraseña), el servidor le envía un JWT que se almacena en el almacenamiento local, y se envía de vuelta al servidor para cada llamada api que requiere autenticación del usuario.
Ahora quiero apoyar el inicio de sesión de Facebook y Google también. Desde que comencé con Passport, pensé que sería mejor continuar con las estrategias de Passport, usando pasaporte-facebook y pasaporte-google-oauth .
Me referiré a Facebook, pero ambas estrategias se comportan igual. Ambos requieren redirección a una ruta del servidor ( ''/ auth / facebook'' y ''/ auth / facebook / callback'' para el caso). El proceso es exitoso hasta el punto de salvar a los usuarios, incluidos sus identificadores y tokens de facebook / google en la base de datos.
Cuando el usuario se crea en el servidor, se crea un JWT (sin depender del token recibido de facebook / google).
... // Passport facebook startegy
var newUser = new User();
newUser.facebook = {};
newUser.facebook.id = profile.id;
newUser.facebook.token = token; // token received from facebook
newUser.facebook.name = profile.displayName;
newUser.save(function(err) {
if (err)
throw err;
// if successful, return the new user
newUser.jwtoken = newUser.generateJwt(); // JWT CREATION!
return done(null, newUser);
});
El problema es que después de su creación, no encuentro una forma adecuada de enviar el JWT al cliente , ya que también debo redirigir a mi aplicación.
app.get(''/auth/facebook/callback'',
passport.authenticate(''facebook'', {
session: false,
successRedirect : ''/'',
failureRedirect : ''/''
}), (req, res) => {
var token = req.user.jwtoken;
res.json({token: token});
});
El código de arriba me redirige a la página principal de mi aplicación, pero no recibo el token . Si elimino successRedirect, recibo el token, pero no estoy redirigido a mi aplicación .
¿Alguna solución para eso? ¿Está mal mi enfoque? Cualquier sugerencia servirá.
Añadiendo a la respuesta de Bar.
Preparé un componente de aterrizaje para extraer la cookie, guardarla en el almacenamiento local, eliminar la cookie y luego redirigir a una página autorizada.
class SocialAuthRedirect extends Component {
componentWillMount() {
this.props.dispatch(
fbAuthUser(getCookie("auth"), () => {
document.cookie =
"auth=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
this.props.history.push("/profile");
})
);
}
render() {
return <div />;
}
}
La mejor solución que encontré para ese problema sería redirigir a la página esperada con una cookie que contiene el JWT.
El uso de res.json
solo enviaría una respuesta json y no redireccionaría. Es por eso que la otra respuesta sugerida aquí no resolvería el problema que encontré.
Así que mi solución sería:
app.get(''/auth/facebook/callback'',
passport.authenticate(''facebook'', {
session: false,
successRedirect : ''/'',
failureRedirect : ''/''
}), (req, res) => {
var token = req.user.jwtoken;
res.cookie(''auth'', token); // Choose whatever name you''d like for that cookie,
res.redirect(''http://localhost:3000''); // OR whatever page you want to redirect to with that cookie
});
Después de la redirección, puede leer la cookie de forma segura y usar ese JWT como se espera. (En realidad, puede leer la cookie en cada carga de la página, para verificar si un usuario ha iniciado sesión)
Como mencioné anteriormente, es posible redirigir con el JWT como parámetro de consulta, pero es muy inseguro. Usar una cookie es más seguro, y aún existen soluciones de seguridad que puede usar para hacerlo aún más seguro, a diferencia de un parámetro de consulta que es claramente inseguro.
Una solución adecuada sería implementar la redirección en el lado del cliente.
Simplemente use:
app.get(''/auth/facebook/callback'',
passport.authenticate(''facebook'', {
session: false,
failureRedirect: ''/login''
}), (req, res) => {
res.json({
token: req.user.jwtoken
})
}
)
Si el lado del cliente recibe el token, redirigir desde allí a la página de inicio, y en el caso de que el inicio de sesión no haya sido exitoso, el servidor lo redireccionaría directamente.
O puede ir a la gestión completa del lado del cliente como lo haría:
app.get(''/auth/facebook/callback'',
passport.authenticate(''facebook'', {
session: false
}), (req, res) => {
if (req.user.jwtoken) {
res.json({
success: true,
token: req.user.jwtoken
})
} else {
res.json({
success: false
})
}
}
)
Si el success === true
, almacene JWT en LocalStorage, de lo contrario redirija a la página de inicio de sesión.