Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

388
Views
NodeJS + Inicio de sesión de Google + Funciones de Firebase dan como resultado un error en la decodificación de la cookie de sesión de Firebase

Necesito un inicio de sesión de Google para una aplicación de Firebase, para hacer esto utilicé varias fuentes:

  • auth-sessions proporciona un buen ejemplo listo para usar con NodeJS + Firebase + Google Login.
  • La sesión de administración de firebase proporciona una muestra de funciones de NodeJS (no una solución de trabajo completa) para trabajar con las funciones de Firebase.

El problema:

Al intentar iniciar sesión en una cuenta de Google en producción, se produce el siguiente error al ejecutar la función de autenticación de código a continuación:

 admin .auth() .verifySessionCookie(sessionCookie, true /** checkRevoked */) .then((decodedClaims) => { log("Decode success"); // inbetween checks log("Successfully decoded and authenticated"); next(); }) .catch((error) => { log("Error authenticating"); < ---- THIS IS THE PROBLEM ... });

Este error SOLO ocurre cuando está en producción, es decir, se implementa en Firebase. Cuando se prueba localmente usando emuladores de Firebase que emulan el alojamiento y las funciones solamente (auth, firestore, base de datos, etc. son todos de producción), el inicio de sesión es exitoso. Al implementar, el inicio de sesión falla con el siguiente error.

Error:

Error al decodificar la cookie de sesión de Firebase. Asegúrese de pasar la cadena completa JWT que representa una cookie de sesión. Consulte https://firebase.google.com/docs/auth/admin/manage-cookies para obtener detalles sobre cómo recuperar una cookie de sesión.


Más detalles:

A continuación se muestra una descripción general de alto nivel de los pasos/acciones realizadas

Descripción general de los pasos de las acciones realizadas

 1. Visit any page eg /login 2. Click sign in with Google, execute the popup provider (see [here][3]) 2. 1. Sign in with Google account 2. Send token to firebase functions for verification ie `POST /sessionLogin` 3. Receive response (assume 200 OK) 4. Redirect to authenticated URL

El error está en el último paso, es decir, 4

Este error ocurre después de crear correctamente una sesión con el código de muestra /sessionLogin que se encuentra aquí en el sitio de firebase:

 const auth = admin.auth(); auth.verifyIdToken(idToken).then(value => { debug("Token verified") return auth.createSessionCookie(idToken, {expiresIn}) .then((sessionCookie) => { // Set cookie policy for session cookie. const options = {maxAge: expiresIn, httpOnly: true, secure: true}; res.cookie('session', sessionCookie, options); // res.json(JSON.stringify({status: 'success'})); res.status(200).send("OK"); }).catch((error) => { debug(error); res.status(401).send('UNAUTHORIZED REQUEST!'); }); }).catch(reason => { debug("Unable to verify token"); debug(reason); res.status(401).send('INVALID TOKEN!'); });

Los registros responden con un Token verified y se envía un estado 200 al cliente.

Luego, el cliente redirige a una URL autenticada /user/dashboard que realiza la verificación de autenticación (ver a continuación) que falla y redirige de nuevo a /login :

 const authenticate = (req, res, next) => { log("Authenticating"); // source: https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions const sessionCookie = req.cookies.session || ''; // Verify the session cookie. In this case an additional check is added to detect // if the user's Firebase session was revoked, user deleted/disabled, etc. return admin .auth() .verifySessionCookie(sessionCookie, true /** checkRevoked */) .then((decodedClaims) => { log("Decode success"); // inbetween checks log("Successfully decoded and authenticated"); next(); }) .catch((error) => { log("Error authenticating"); if(error.errorInfo && error.errorInfo.code && error.errorInfo.code === "auth/argument-error") { debug(error.errorInfo.message); res.redirect('/user/login'); return; } debug(error); // Session cookie is unavailable or invalid. Force user to login. req.flash("message", [{ status: false, message: "Invalid session, please login again!" }]) res.redirect('/user/login'); }); };

que es middleware para la aplicación express:

 admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://my-company-default-rtdb.firebaseio.com", storageBucket: "gs://my-company.appspot.com" }); const app = express(); app.use(cors({origin: true})); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.use(morgan('dev')); app.use(cookieParser('0000-0000-0000-0000-0000')) app.set('trust proxy', 1) // trust first proxy // Attach CSRF token on each request. app.use(attachCsrfToken('/', 'csrfToken', (Math.random()* 100000000000000000).toString())); app.use(session({ secret: '0000-0000-0000-0000-0000', resave: false, name: '__session', store: new FirebaseStore({ database: admin.database() }), })); app.use(flash()); app.use(authenticate); // routes exports.app = functions.https.onRequest(app);

Registros de ejecución:

1:12:02.796 Se inició la ejecución de la función de la aplicación PM

1:12:02.910 Autenticación de la aplicación PM

1:12:02.910 PM app Intentando verificar la cocción de la sesión

1:12:02.910 PM aplicación Cookies: {}

1:12:02.911 PM aplicación Error al autenticar

1:47:41.905 PM error de argumento/autenticación de la aplicación

1:12:02.911 PM [aplicación] Falló la descodificación de la cookie de sesión de Firebase. Asegúrese de pasar la cadena completa JWT que representa una cookie de sesión. Consulte https://firebase.google.com/docs/auth/admin/manage-cookies para obtener detalles sobre cómo recuperar una cookie de sesión.

1:12:02.937 PM [aplicación] La ejecución de la función tomó 141 ms, terminó con el código de estado: 302


Actualizar

Llame al backend para la autenticación:

 const postIdTokenToSessionLogin = (idToken, csrfToken) => { return axios({ url: "/user/sessionLogin", method: "POST", data: { idToken: idToken, csrfToken: csrfToken, }, }).then(value => { console.log(value); if(value.status === 200) { window.location.assign("/user/dashboard"); } }).catch(reason => { console.error(reason); alert("Failed to login"); }); }

Llamada del lado del cliente:

 var provider = new firebase.auth.GoogleAuthProvider(); firebase.auth() .signInWithPopup(provider) .then(async value => { firebase.auth().currentUser.getIdToken().then(idToken => { // const idToken = value.credential.idToken; const csrfToken = getCookie('_csrf'); return postIdTokenToSessionLogin(idToken, csrfToken); }).catch(reason => { console.error("Failed to get current user token"); alert(reason.message); }); })/*.then(value => { window.location.assign("/user/dashboard") })*/.catch((error) => { console.error("Failed to sign in with Google"); alert(error.message); });

Actualización 2:

Se actualizó la solicitud de axios del lado del cliente con lo siguiente, también se agregó el registro adicional de req.cookies

 return axios({ url: "/user/sessionLogin", method: "POST", withCredentials: true, data: { idToken: idToken, csrfToken: csrfToken, }, })

Registro adicional:

4:43:23.493 Aplicación PM Se inició la ejecución de la función

4:43:23.501 Autenticación de la aplicación PM

4:43:23.501 PM app Creando sesión

4:43:23.502 PM app /sessionLogin Cookies: {"csrfToken":"19888568527706150","session":"eyJhbGciOiJSUzI1NiIsImtpZCI6InRCME0yQSJ9.eyJpc3MiOiJodHRwczovL3Nlc3Npb24uZmlyZWJ..."}

4:43:23.503 Token de aplicación PM verificado

4:43:23.503 aplicación PM {"nombre":redactado ,"imagen":"","iss":"","aud":"",...}

4:43:23.503 PM aplicación ==============

4:43:23.503 PM app /sessionLogin#verifyIdToken Cookies: {"csrfToken":"19888568527706150","session":"eyJhbGciOiJSUzI1NiIsImtpZCI6InRCME0yQSJ9.eyJpc3MiOiJodHRwczovL3Nlc3Npb24uZmlyZWJ..."}

4:43:23.634 PM app /sessionLogin#createSessionCookie Cookies: {"csrfToken":"19888568527706150","session":"eyJhbGciOiJSUzI1NiIsImtpZCI6InRCME0yQSJ9.eyJpc3MiOiJodHRwczovL3Nlc3N..."}

4:43:23.634 PM aplicación Cookie:

4:43:23.634 PM aplicación "eyJhbGciOiJSUzI1NiIsImtpZCI6InRCME0yQSJ9.eyJpc3MiOiJodHRwczovL3Nlc3Npb24uZmlyZWJhc2UuZ29vZ..."

4:43:23.634 aplicación PM ==============

4:43:23.643 PM aplicación [0mPOST /user/sessionLogin [32m200[0m 139.036 ms - 2[0m

4:43:23.643 PM aplicación La ejecución de la función tomó 150 ms, finalizó con el código de estado: 200

4:43:24.131 Aplicación PM Se inició la ejecución de la función

4:43:24.153 Autenticación de la aplicación PM

4:43:24.153 Aplicación PM Intentando verificar la cocción de la sesión

4:43:24.153 PM aplicación Cookies: {}


Actualización 3

Reescribe el acceso habilitado de API y NodeJS exactamente como se muestra en firebase.json :

 { "database": { "rules": "database.rules.json" }, "firestore": { "rules": "firestore.rules", "indexes": "firestore.indexes.json" }, "hosting": { "site": "my-company-admin-portal", "public": "public", "rewrites": [ { "source": "/api/**", "function": "api" }, { "source": "**", "function": "app" } ], "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ] }, "storage": { "rules": "storage.rules" }, "emulators": { "auth": { "port": 9099 }, "functions": { "port": 5001 }, "database": { "port": 9000 }, "hosting": { "port": 5000 }, "storage": { "port": 9199 }, "ui": { "enabled": true } } }
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Le sugiero que revise esta publicación en la que tienen un problema similar.

En resumen, si revisa el repositorio quickstart-nodejs , debe agregar cookie-parser y body-parser . Aquí está el ejemplo que proporcionan en la publicación :

 const admin = require("firebase-admin"); const functions = require("firebase-functions"); const next = require("next"); const cors = require("cors"); const express = require("express"); const cookieParser = require("cookie-parser"); const bodyParser = require("body-parser"); const dev = process.env.NODE_ENV !== "production"; const app = next({ dev, conf: { distDir: "next" } }); const handle = app.getRequestHandler(); admin.initializeApp({ credential: admin.credential.cert("Service account key"), databaseURL: "Path to database" }); const server = express(); server.use(cors({ origin: true })); server.use(bodyParser.json()); // Support URL-encoded bodies. server.use(bodyParser.urlencoded({ extended: true })); // Support cookie manipulation. server.use(cookieParser()); // Attach CSRF token on each request. server.use(attachCsrfToken('/', 'csrfToken', (Math.random()* 100000000000000000).toString())); function attachCsrfToken(url, cookie, value) { return function(req, res, next) { if (req.url === url) { res.cookie(cookie, value); } next(); } } server.post("/login", (req, res) => { if (req.body && req.body.idToken) { const idToken = `${req.body.idToken}`; const expiresIn = 60 * 60 * 24 * 5 * 1000; admin.auth().createSessionCookie(idToken, { expiresIn }).then((sessionCookie) => { const options = { maxAge: expiresIn, httpOnly: true, secure: true }; res.cookie("session", sessionCookie, options); res.end(JSON.stringify({ sessionCookie })); }, error => { res.status(401).send(error); }); } else { res.status(401).send("Token empty"); } }); server.post("/profile", (req, res) => { if (req.cookies && req.cookies.session) { const sessionCookie = `${req.cookies.session}`; admin.auth().verifySessionCookie( sessionCookie, true /** checkRevoked */).then((decodedClaims) => { res.end(JSON.stringify({ decodedClaims })); }).catch(error => { res.status(401).send(error); }); } else { res.status(401).send("Session empty"); } }); exports.next = functions.https.onRequest((req, res) => { if (req.method === "POST") { if (!req.path) req.url = `/${request.url}`; return server(req, res); } return app.prepare().then(() => handle(req, res)); });
over 4 years ago · Santiago Trujillo Report

0

sessionCookie no está definido como en el código proporcionado en la pregunta.

 // Authenticate middleware right now const authenticate = (req, res, next) => { log("Authenticating"); // No sessionCookie declared return admin .auth() .verifySessionCookie(sessionCookie, true /** checkRevoked */) // undefined passed here ^^^ }

Debe pasar la cookie que configuró después de usar createSessionCookie en el método de verifySessionCookie como se muestra a continuación:

 // updated authenticate middleware const authenticate = async (req, res, next) => { try { log("Authenticating"); // Read the value of cookie here const sessionCookie = req.cookies.session // Return unauthorized error if cookie is absent if (!sessionCookie) return res.sendStatus(401) const decodedClaims = await admin.auth().verifySessionCookie(sessionCookie, true) // cookie verified, continue } catch (e) { console.log(e) return res.send("An error occurred") } }
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!