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

253
Views
Validación manual de tokens de Firebase Auth

Estoy tratando de usar trabajadores de Cloudflare para realizar acciones autenticadas.

Estoy usando firebase para la autenticación y tengo acceso a los tokens de acceso, pero dado que firebase-admin usa módulos nodejs, no puede funcionar en la plataforma, así que me quedo validando manualmente el token.

He estado intentando autenticarme con Crypto API y finalmente logré importar la clave pública, firmar el token para verificar si es válido, pero sigo obteniendo FALSO. Estoy luchando por descubrir por qué siempre devuelve falso para la validez.

La clave criptográfica que importé viene como tipo "secreto" donde esperaría que fuera "público".

Cualquier pensamiento o ayuda sería enorme. He estado golpeando mi cabeza contra una mesa durante los últimos días tratando de resolver esto.

Esto es lo que tengo hasta ahora:

 function _utf8ToUint8Array(str) { return Base64URL.parse(btoa(unescape(encodeURIComponent(str)))) } class Base64URL { static parse(s) { return new Uint8Array(Array.prototype.map.call(atob(s.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')), c => c.charCodeAt(0))) } static stringify(a) { return btoa(String.fromCharCode.apply(0, a)).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_') } } export async function verify(userToken: string) { let jwt = decodeJWT(userToken) var jwKey = await fetchPublicKey(jwt.header.kid); let publicKey = await importPublicKey(jwKey); var isValid = await verifyPublicKey(publicKey, userToken); console.log('isValid', isValid) // RETURNS FALSE return isValid; } function decodeJWT(jwtString: string): IJWT { // @ts-ignore const jwt: IJWT = jwtString.match( /(?<header>[^.]+)\.(?<payload>[^.]+)\.(?<signature>[^.]+)/ ).groups; // @ts-ignore jwt.header = JSON.parse(atob(jwt.header)); // @ts-ignore jwt.payload = JSON.parse(atob(jwt.payload)); return jwt; } async function fetchPublicKey(kid: string) { var key: any = await (await fetch('https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com')).json(); key = key[kid]; key = _utf8ToUint8Array(key) return key; } function importPublicKey(jwKey) { return crypto.subtle.importKey('raw', jwKey, { name: 'HMAC', hash: { name: 'SHA-256' } }, false, ['sign']); } async function verifyPublicKey(publicKey: CryptoKey, token: string) { const tokenParts = token.split('.') let res = await crypto.subtle.sign({ name: 'HMAC', hash: { name: 'SHA-256' } }, publicKey, _utf8ToUint8Array(tokenParts.slice(0, 2).join('.'))) return Base64URL.stringify(new Uint8Array(res)) === tokenParts[2]; }
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Tenga en cuenta que puede obtener los jwks desde el extremo no documentado https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com .

 async function fetchPublicKey(kid) { const result = await ( await fetch( "https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com" ) ).json(); return result.keys.find((key) => key.kid === kid); }

Usando la clave (llamada jwk a continuación), puede verificar la firma:

 const encoder = new TextEncoder(); const data = encoder.encode([token.raw.header, token.raw.payload].join(".")); const signature = new Uint8Array( Array.from(token.signature).map((c) => c.charCodeAt(0)) ); const key = await crypto.subtle.importKey( "jwk", jwk, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"] ); return crypto.subtle.verify("RSASSA-PKCS1-v1_5", key, signature, data);
about 4 years ago · Juan Pablo Isaza Report

0

Hay algunos problemas con su código:

  1. La URL a la que llama para obtener claves públicas devuelve una lista de certificados x509. Estas no son claves públicas utilizadas para verificar firmas. ¿Estás seguro de que no tienes acceso directo a las claves públicas? Parece que es posible obtener la información de la clave pública de un certificado x509 (como se describe aquí: Extraer la clave pública PEM del certificado X.509 ), aunque no estoy seguro de si eso es posible de un trabajador de Cloudflare.

  2. En importPublicKey , le está diciendo al método de import que la clave está en formato sin formato y que es una clave HMAC . Esto significa que crypto trata su clave como una clave HMAC simétrica, no como una clave pública. De acuerdo con los documentos: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#subjectpublickeyinfo , debe usar el formato spki , ya que este es el que importa una clave pública. Debería saber por adelantado si el token de acceso JWT está firmado con el algoritmo RSA o Elliptic Curve. (por ejemplo, verifique el reclamo del encabezado alg )

  3. Está utilizando el método de sign para verificar la firma. Así no es cómo funciona. Debe usar el método de verify de crypto.subtle y este método verificará la firma por usted.

Creo que no debería intentar verificar los JWT manualmente, ya que lo más probable es que lo haga mal (y cree problemas de seguridad para su aplicación). Debería usar bibliotecas que se ocupen de la verificación de firmas JWT. Será mucho más fácil para ti y más seguro para tu aplicación. Una cosa que debe averiguar es de dónde debe tomar la clave pública.

about 4 years ago · Juan Pablo Isaza 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!