Implementación del inicio de sesión con Google: Passport + OAuth
Al finalizar este tema
Podrás configurar un cliente OAuth en la Consola de Google Cloud e implementar el inicio de sesión social utilizando la estrategia de Google de Passport.js.
Requisitos previos
Se requiere conocimiento de los temas anteriores:
- Flujo OAuth 2.0: los cuatro elementos clave del flujo de autorización.
- Passport.js: el patrón Strategy y las funciones
serializeUser/deserializeUser. - Express Session: la autenticación basada en sesiones.
La combinación de estos tres elementos permite el inicio de sesión con Google.
Paso 1: Configuración de la Consola de Google Cloud
Debemos registrar nuestra aplicación en Google. Este proceso no implica código, sino que es una tarea en la consola web.
- Ve a la Consola de Google Cloud y crea un nuevo proyecto.
- En "Pantalla de consentimiento de OAuth", ingresa el nombre de la aplicación y el correo electrónico.
- En "Credenciales de autenticación", crea un ID de cliente de OAuth 2.0.
- Agrega
http://localhost:3000/auth/google/callbacka los URI de redireccionamiento autorizados.
Como resultado, obtendrás dos valores: ID de cliente y secreto de cliente. Guarda estos valores en .env.
GOOGLE_CLIENT_ID=abc123...
GOOGLE_CLIENT_SECRET=xyz789...Paso 2: Instalación del paquete
npm install passport-google-oauth20Asumiremos que ya se han instalado passport y express-session.
Paso 3: Registrar la estrategia
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: '/auth/google/callback',
},
(accessToken, refreshToken, profile, done) => {
// La información del usuario de Google está en el perfil
// Buscar o crear un nuevo usuario en la base de datos
const user = {
googleId: profile.id,
name: profile.displayName,
email: profile.emails[0].value,
photo: profile.photos[0].value,
};
// En realidad, consulta/guarda en la base de datos
done(null, user);
}
));Esta función de devolución de llamada se invoca una vez que Google ha completado el intercambio del código de autorización por un token. Passport se encarga de todo el flujo complejo de OAuth, y nosotros solo necesitamos recibir la información del usuario.
Paso 4: Conexión de rutas
// Iniciar inicio de sesión con Google
app.get('/auth/google',
passport.authenticate('google', { scope: ['profile', 'email'] })
);
// Lugar donde Google devuelve el código de autorización
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
(req, res) => {
res.redirect('/');
}
);
// Cerrar sesión
app.get('/logout', (req, res) => {
req.logout(() => {
res.redirect('/');
});
});Seguimos el flujo:
- El usuario accede a
/auth/google→ se le redirige a la pantalla de inicio de sesión de Google. - El usuario inicia sesión en Google y otorga los permisos necesarios → Google redirige a
/auth/google/callback?code=xxx. - Passport intercambia el token con
code→ se llama a la función de devolución de llamada de la estrategia → se guarda la información del usuario en la sesión. res.redirect('/')→ se redirige a la página principal con la sesión iniciada.
Paso 5: Serialización y deserialización.
passport.serializeUser((user, done) => {
done(null, user.googleId);
});
passport.deserializeUser((googleId, done) => {
// En realidad, consulta por googleId en la base de datos
done(null, { googleId, name: '...' });
});serialize define qué se debe guardar en la sesión, mientras que deserialize define cómo restaurar el objeto de usuario a partir de los datos recuperados de la sesión.
En lugar de guardar el objeto de usuario completo en la sesión, guarde solo el ID. Cuanto menor sea el tamaño de los datos de la sesión, menor será la carga del servidor.
Resumen de la estructura general
Usuario Nuestro servidor Google
│ │ │
├─ /auth/google ─────→│ │
│ ├─ redirect ────────→│
│ │ │
│←── Pantalla de inicio de sesión con Google ─┤ │
│ │ │
├─ Iniciar sesión+Permitir ───────→│ │
│ │←── code ──────────┤
│ ├─ code+secret ─────→│
│ │←── access_token ──┤
│ ├─ token ───────────→│
│ │←── profile ───────┤
│←── Creación de sesión, / ─────┤ │Passport se encarga de los cinco pasos principales (recepción del código, intercambio de tokens y solicitud de perfil). Nosotros solo registramos la estrategia y conectamos las rutas.
Errores comunes
- URI de redirección incorrecto: El URI registrado en la consola y el
callbackURLen el código deben ser exactamente iguales. Incluso una pequeña diferencia, como una barra diagonal adicional, puede provocar un error. - Ámbito (scope) omitido: Si no se incluye
scope: ['profile', 'email'],profile.emailsno estará definido. - Exposición del secreto del cliente: Incluya
.envy agregue.enven.gitignore. Si el secreto se sube a GitHub, Google lo desactivará automáticamente.
Aspectos clave
Passport.js + la estrategia de Google simplifican el complejo flujo de OAuth 2.0 en una sola estrategia. Solo debemos realizar la configuración en la consola, registrar la estrategia y conectar dos rutas; eso es todo. Flujo principal:
/auth/google→ inicio de sesión en Google →/auth/google/callback→ creación de sesión → redirección a la página de inicio.