firebase - array - undefined offset 8
¿Todavía es posible hacer la verificación del lado del servidor de tokens en Firebase 3? (2)
¿Todavía es posible hacer la verificación del lado del servidor de tokens en Firebase 3?
Generamos tokens personalizados (JWT) en un servidor que ejecuta Golang usando nuestro sistema de autenticación existente (usando una cuenta de servicio). El token se usa en un cliente iOS usando
FIRAuth.auth()?.signInWithCustomToken(customToken)
Hasta allí todo funciona bien. Pero cuando pasamos el token del cliente al servidor recuperado de:
FIRUser.getTokenWithCompletion({ token, error in ..})
No podemos verificarlo. El token JWT está firmado con RS256 y tiene un encabezado.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. ¿Se necesita la clave pública para validar el token del cliente disponible?
Sé que es posible validar tokens de cliente utilizando la llamada "generateIdToken" en Java o Javascript, pero esperamos poder hacerlo en Golang utilizando una biblioteca JWT estándar.
Todo esto funcionó bien en Firebase 2 (usando HS256 y el secreto de Firebase).
Bueno, 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 con tokens personalizados.
Entonces, como fue mi caso, si pasas tokens personalizados de Firebase a otros servicios para autenticarse con tu back-end, ¡entonces tú eres el responsable de la verificación de tokens personalizados!
Además, el
X509 cert
cuenta de servicio de Google
X509 cert
no tiene el formato adecuado.
Tiene estos delimitadores de
/n (new line)
que no se reemplazan con nuevas líneas en los editores de texto (uso
vim
).
Por lo tanto, lo que hice es 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
- Obtenga el certificado del enlace de la cuenta del servicio de Google especificado en el json descargado mientras configura Firebase
-
Reemplazar manualmente
/n
con una nueva línea - Obtenga la biblioteca JWT. Usé esta gran biblioteca para hacer la verificación Java JWT
- Lea el certificado y extraiga la clave pública.
- Use la clave pública para verificar el token
- Asegúrese de tener otra API para actualizar los tokens, ya que solo son válidos durante una hora
¡Espero que ayude!
La respuesta corta es sí. La respuesta completa es que, en la mayoría de los casos, tenemos una herramienta más apropiada ahora. Por lo tanto, mucho depende del caso de uso que intente resolver.
La nueva versión del SDK es bastante más potente, 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 agregaré algunas notas específicas de terceros (es decir, Ir) al final.
Usar una herramienta de autenticación externa para la autenticación del cliente
El uso principal de la creación de tokens personalizados es permitir a los usuarios autenticarse contra un mecanismo de autenticación externo / heredado que controle, como su servidor LDAP. El proceso básico para esto está cubierto aquí: iOS , Android , Web .
Esencialmente, 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 proporciona.
Autenticando a sus trabajadores privilegiados
Ya no es necesario usar tokens personalizados para autenticar el proceso de su servidor. Esto se hace mediante la creación de 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, incluye las credenciales de su cuenta de servicio haciendo referencia a ese JSON utilizando el atributo
firebase.initializeApp()
en
firebase.initializeApp()
, ¡y ya está!
Eso está documentado
here
y tiene este aspecto (ver 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 (muy recomendable) desde un proceso de servidor. Realmente ya no necesitas acuñar un token personalizado para esto.
Esto solo requiere agregar
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 lidiar 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 reglas de seguridad para validar su identidad. Si su servidor escucha en una ruta que requiere autenticación para escribir, 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. Vea firebase-queue para 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 la base de datos en tiempo real y necesita recibir tokens de clientes (por ejemplo, a través de llamadas REST) y verificar que son válidos, puede hacerlo mediante
verifyIdToken()
como se describe
here
.
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 hacer cumplir la seguridad, usaría la sección
Emulación de usuarios
anterior.
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 encuentra con 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 múltiples instancias de aplicaciones,
mira aquí
.
Código Java disponible en los enlaces de arriba. Ir y otras soluciones de terceros cubiertas a continuación.
Crear un token para usar en la API REST
Michael Bleigh cubrió este escenario here y merece algún representante por 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 verificación y acuñación de tokens Go. También agregaremos herramientas 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 usar las bibliotecas oficiales de Firebase Node.js o Java (que tienen métodos de verificación incorporados), deberá asegurarse de que el token de ID (que es un JWT) cumple con lo siguiente:
-
Su encabezado decodificado tiene un reclamo
alg
(algoritmo) igual a"RS256"
. -
Su carga útil decodificada tiene un reclamo
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/<projectId>"
. -
Su carga útil decodificada tiene un reclamo de
sub
(sujeto) de cadena no vacía. Tenga en cuenta que este es eluid
para ese usuario de Firebase. -
Su encabezado decodificado tiene un reclamo
kid
(ID de clave) que corresponde a una de las claves públicas enumeradas enhttps://www.googleapis.com/robot/v1/metadata/x509/[email protected]
. - También debe usar una biblioteca JWT para verificar el token con la clave pública para demostrar que el token se firmó con la clave privada correspondiente de las claves públicas.
Para Go, parece que puede usar
jwt-go
para decodificar y validar el token de ID de cliente.