¿Todavía es posible hacer la verificación del lado del servidor de los tokens en Firebase 3?

¿Todavía es posible hacer la verificación del lado del servidor de los tokens en Firebase 3?

Generamos tokens personalizados (JWT) en un servidor que ejecuta Golang utilizando nuestro sistema de autenticación existente (usando una cuenta de servicio). El token se usa en un cliente iOS que usa

FIRAuth.auth()?.signInWithCustomToken(customToken) 

Hasta allí todo funciona bien. Pero cuando pasamos el token de cliente al servidor recuperado de:

 FIRUser.getTokenWithCompletion({ token, error in ..}) 

no podemos verificarlo El token JWT está firmado usando RS256 y tiene un header.kid que no podemos reconocer. La clave pública de la cuenta de servicio (que se usó para firmar el token personalizado) no verifica el token del cliente. ¿La clave pública es necesaria para validar el token del cliente disponible?

Sé que es posible validar tokens de clientes utilizando la llamada “verifyIdToken” en Java o Javascript, pero esperamos poder hacerlo en Golang utilizando una biblioteca JWT estándar.

Todo funcionó bien en Firebase 2 (utilizando HS256 y el secreto de Firebase).

La respuesta corta es sí. La respuesta completa es que, en la mayoría de los casos, tenemos una herramienta más adecuada ahora. Entonces, mucho depende del caso de uso que intenta resolver.

La nueva versión de SDK es bastante más poderosa, y no hemos hecho un gran trabajo al resumir las capacidades. Este parece ser un buen lugar para contrastar las herramientas disponibles y sus usos, y luego incluiré notas específicas de terceros (es decir, Go) al final.

Usar una herramienta de autenticación externa para la autenticación del cliente

El uso principal de acuñar tokens personalizados es permitir que los usuarios se autentiquen contra un mecanismo de autenticación externo / heredado que usted controla, como su servidor LDAP. El proceso básico para esto se trata aquí: iOS , Android , Web .

Básicamente, su servicio solo acuña el token JWT y lo pasa al cliente. El cliente realiza la verificación / autenticación utilizando el token personalizado que usted proporciona.

Autenticando a sus trabajadores privilegiados

Ya no es necesario usar tokens personalizados para autenticar el proceso de su servidor. Esto se hace creando una cuenta de servicio, que se cubre paso a paso en Agregar Firebase a su Servidor . Cuando termine, terminará con un archivo JSON que contiene una clave privada.

Luego, incluya las credenciales de su cuenta de servicio haciendo referencia a ese JSON utilizando el atributo firebase.initializeApp() en firebase.initializeApp() , ¡y ya está! Esto está documentado aquí y se ve así (ver el enlace para la versión de Java):

 var firebase = require("firebase"); // Initialize the app with a service account, granting admin privileges firebase.initializeApp({ databaseURL: "https://databaseName.firebaseio.com", serviceAccount: "./serviceAccountCredentials.json" }); 

Emular usuarios o limitar el acceso desde un proceso de servidor

Es bastante trivial emular a un usuario o limitar el acceso (altamente recomendado) desde un proceso de servidor. En realidad, ya no necesitas acuñar un token personalizado para esto.

Esto solo requiere agregar la databaseAuthVariableOverride en su llamada a database.initializeApp() :

 firebase.initializeApp({ databaseURL: "https://databaseName.firebaseio.com", serviceAccount: "./serviceAccountCredentials.json", databaseAuthVariableOverride: { uid: "my-service-worker-or-user-uid" } }); 

Validar la identidad del cliente a través de la seguridad

En primer lugar, generalmente puede evitar tratar con la verificación del lado del servidor si está utilizando Firebase Database, haciendo que su cliente escriba en la base de datos y use las reglas de seguridad para validar su identidad. Si su servidor escucha en una ruta que requiere autenticación para escribir, entonces esto ya está resuelto sin ninguna seguridad especial en el servidor.

Al modelar esto como una cola de eventos, crea una estrategia de trabajo de servidor simple, modular y escalable. Consulta firebase-queue para ver algunas excelentes herramientas de Node.js. Es compatible con 3.x.

Verificación de tokens de ID de cliente en el servidor

Si no está utilizando Realtime Database y necesita recibir tokens de clientes (por ejemplo, mediante llamadas REST) ​​y verifica que sean válidos, puede hacerlo utilizando verifyIdToken() como se describe aquí . Esto se vería así:

 auth.verifyIdToken(idToken).then(function(decodedToken) { var uid = decodedToken.sub; }); 

Si luego desea autenticarse como ese usuario para escribir en la base de datos y aplicar la seguridad, debería usar la sección Emular usuarios que aparece arriba. En otras palabras, llame a initializeApp() con una databaseAuthVariableOverride de datosAuthVariableOverride establecida en el uid apropiado.

Tenga en cuenta que, si intenta llamar a initializeApp() varias veces y se produce un error similar al siguiente: Error: Firebase App named '[DEFAULT]' already exists. Puede inicializar múltiples contextos de aplicación agregando un segundo argumento a la llamada initializeApp () (por ejemplo, database.initializeApp({...}, 'asUser'+uid) ) y luego hacer referencia a esa instancia de la aplicación usando firebase.database('asUser'+uid) .ref (…). Para leer más sobre el uso de varias instancias de aplicaciones, mira aquí .

Código de Java disponible en los enlaces de arriba. Go y otras soluciones de terceros cubiertas a continuación.

Crear un token para usar en la API REST

Michael Bleigh cubrió este escenario aquí y merece un representante para resolverlo.

Crear tokens o verificarlos a través de REST

Esto no es compatible. Lo siento.

Golang y otros: más por venir

Estamos trabajando en una biblioteca de minería y verificación de tokens Go. También vamos a agregar herramientas de Python para esto pronto también. No hay fecha de lanzamiento o estadios para esto. Mientras tanto, si desea verificar los tokens de ID de cliente sin utilizar las bibliotecas oficiales de Firebase Node.js o Java (que tienen métodos de verificación incorporados), deberá asegurarse de que el token de identificación (que es un JWT) se ajusta a lo siguiente:

  • Su encabezado descodificado tiene un reclamo de alg (algoritmo) igual a "RS256" .
  • Su carga útil decodificada tiene una reclamación de aud (audiencia) igual a su ID de proyecto de Firebase.
  • Su carga útil decodificada tiene un reclamo iss (emisor) igual a "https://securetoken.google.com/" .
  • Su carga útil decodificada tiene un reclamo de sub (sujeto) no vacía. Tenga en cuenta que este es el uid para ese usuario de Firebase.
  • Su encabezado descodificado tiene un reclamo kid (ID de clave) que corresponde a una de las claves públicas enumeradas en https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com .
  • También necesita usar una biblioteca JWT para verificar el token con la clave pública para comprobar que el token se firmó con la clave privada correspondiente de las claves públicas.

Para Go, parece que puede usar jwt-go para descodificar y validar el token de identificación del cliente.

Well firebase no permite la verificación de custom tokens Lo que hacen es permitir la verificación de los id tokens de id tokens que se generan una vez que el usuario inicia sesión utilizando tokens personalizados. Así que, como sucedió en mi caso, si pasas los tokens personalizados de Firebase a otros servicios para que se autentiquen con tu backend, ¡la responsabilidad de la verificación de token personalizada recae sobre ti! Además, el X509 cert cuenta de servicio de google no tiene el formato adecuado. Tiene estos delimitadores \n (new line) que no se reemplazan con nuevas líneas en los editores de texto (yo uso vim ). Por lo tanto, lo que hice fue esto:

  val factory = CertificateFactory.getInstance("X.509") val certificateFile = this.getClass.getResourceAsStream(Play.current.configuration.getString("firebase.certificate").get) val publicKey = factory.generateCertificate(certificateFile).asInstanceOf[X509Certificate].getPublicKey val claimBody = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(compactJws).getBody 
  1. Obtenga el certificado del enlace de la cuenta de servicio de google especificado en el json descargado mientras configura firebase
  2. Sustituir manualmente \n por una nueva línea
  3. Obtener la biblioteca JWT. Utilicé esta gran biblioteca para hacer la verificación Java JWT
  4. Lea el certificado y extraiga la clave pública.
  5. Usa la clave pública para verificar el token
  6. Asegúrate de tener otra API para actualizar los tokens, ya que solo son válidos por una hora

¡Espero que ayude!