web-dev-qa-db-fra.com

Est-il toujours possible d'effectuer une vérification des jetons côté serveur dans Firebase 3?

Est-il toujours possible d'effectuer une vérification des jetons côté serveur dans Firebase 3?

Nous générons des jetons personnalisés (JWT) sur un serveur exécutant Golang à l'aide de notre système d'authentification existant (à l'aide d'un compte de service). Le jeton est utilisé sur un client iOS utilisant

FIRAuth.auth()?.signInWithCustomToken(customToken)

Jusque là tout fonctionne bien. Mais lorsque nous passons le jeton client au serveur extrait de:

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

nous ne pouvons pas le vérifier. Le jeton JWT est signé avec RS256 et possède un en-tête.kid que nous ne pouvons pas reconnaître. La clé publique du compte de service (utilisé pour signer le jeton personnalisé) ne vérifie pas le jeton client. La clé publique nécessaire pour valider le jeton client est-elle disponible?

Je sais qu'il est possible de valider les jetons client à l'aide de l'appel "verifyIdToken" en Java ou Javascript, mais nous espérons pouvoir le faire dans Golang à l'aide d'une bibliothèque JWT standard.

Tout cela a bien fonctionné dans Firebase 2 (en utilisant HS256 et le secret Firebase).

42
Tim Rob

La reponse courte est oui. La réponse complète est que, dans la plupart des cas, nous avons maintenant un outil plus approprié. Donc, beaucoup dépend du cas d'utilisation que vous essayez de résoudre.

La nouvelle version du Kit de développement logiciel (SDK) est un peu plus puissante et nous n’avons pas réussi à en résumer les capacités. Cela semble être un bon endroit pour mettre en contraste les outils disponibles et leurs utilisations, puis je m'attacherai à certaines notes spécifiques de tiers (c'est-à-dire Go) à la fin.

Utilisation d'un outil d'authentification externe pour l'authentification du client

La création de jetons personnalisés est principalement utilisée pour permettre aux utilisateurs de s’authentifier auprès d’un mécanisme d’authentification externe/existant que vous contrôlez, tel que votre serveur LDAP. Le processus de base pour cela est couvert ici: iOS , Android , Web .

Essentiellement, votre service extrait simplement le jeton JWT et le transmet au client. Le client effectue la vérification/authentification en utilisant le jeton personnalisé que vous fournissez.

Authentification de vos ouvriers privilégiés

Il n'est plus nécessaire d'utiliser des jetons personnalisés pour authentifier le processus de votre serveur. Pour ce faire, vous créez un compte de service, qui est décrit étape par étape Ajout de Firebase à votre serveur . Une fois terminé, vous vous retrouvez avec un fichier JSON contenant une clé privée.

Ensuite, vous incluez vos informations d'identification de compte de service en référençant ce JSON à l'aide de l'attribut serviceAccount de firebase.initializeApp(), et vous y êtes! C'est documenté ici et ressemble à ceci (voir le lien pour 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"
});

Emulation d'utilisateurs ou limitation de l'accès à partir d'un processus serveur

Il est assez simple d'émuler un utilisateur ou de limiter l'accès (fortement recommandé) à partir d'un processus serveur. Vous n'avez plus vraiment besoin de frapper un jeton personnalisé pour cela.

Cela nécessite simplement d'ajouter le databaseAuthVariableOverride à votre appel à database.initializeApp():

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

Validation de l'identité du client via la sécurité

Tout d'abord, vous pouvez généralement éviter de traiter avec la vérification côté serveur si vous utilisez la base de données Firebase, en demandant à votre client d'écrire dans la base de données et en utilisant des règles de sécurité pour valider leur identité. Si votre serveur écoute sur un chemin nécessitant une authentification, cela est déjà résolu sans aucune sécurité particulière sur le serveur.

En modélisant cela comme une file d'attente d'événements, il crée une stratégie de travail de serveur simple, modulaire et évolutive. Voir firebase-queue pour quelques bons outils Node.js. Ce supporte 3.x .

Vérification des jetons d'identifiant client sur le serveur

Si vous n'utilisez pas la base de données Realtime et que vous devez recevoir des jetons clients (par exemple via des appels REST)) et vérifier qu'ils sont valides, vous pouvez le faire en utilisant verifyIdToken() comme décrit ici . Cela ressemblerait à ce qui suit:

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

Si vous souhaitez ensuite vous authentifier en tant qu'utilisateur pour écrire dans la base de données et appliquer la sécurité, utilisez la section Émulation d'utilisateurs ci-dessus. En d'autres termes, appelez initializeApp() avec un databaseAuthVariableOverride défini sur l'uid approprié.

Notez que si vous essayez d'appeler initializeApp() plusieurs fois et que vous rencontrez une erreur similaire à celle-ci: Error: Firebase App named '[DEFAULT]' already exists., Vous pouvez initialiser plusieurs contextes d'application en ajoutant un deuxième argument à l'appel initializeApp (). (par exemple, database.initializeApp({...}, 'asUser'+uid)), puis référencez cette instance d'application à l'aide de firebase.database('asUser'+uid). ref (...). Pour en savoir plus sur l'utilisation de plusieurs instances d'application, regardez ici .

Code Java disponible sur les liens ci-dessus. Go et d'autres solutions tierces couvertes ci-dessous.

Création d'un jeton à utiliser dans l'API REST

Michael Bleigh a couvert ce scénario ici et mérite un représentant pour résoudre ce problème.

Création de jetons ou vérification via REST

Ce n'est pas pris en charge. Désolé.

Golang et autres: plus à venir

Nous travaillons sur une bibliothèque de frappe et de vérification de jetons Go. Nous ajouterons également Python outils pour cela aussi bientôt. Pas de date de sortie ni de paramètres de ballon pour cela. En attendant, si vous souhaitez vérifier les jetons d’ID client sans utiliser l’agent officiel Firebase Node.js ou Java (dotées de méthodes de vérification intégrées), vous devez vous assurer que le jeton ID (qui est un JWT) est conforme à ce qui suit:

  • Son en-tête décodé a une revendication alg (algorithme) égale à "RS256".
  • Sa charge utile décodée a une revendication aud (audience) égale à votre ID de projet Firebase.
  • Sa charge utile décodée a une revendication iss (émetteur) égale à "https://securetoken.google.com/<projectId>".
  • Sa charge décodée a une revendication non-chaîne sub (sujet) non-vide. Notez qu'il s'agit de uid pour cet utilisateur Firebase.
  • Son en-tête décodé a une revendication kid (ID de clé) qui correspond à l'une des clés publiques listées sous https://www.googleapis.com/robot/v1/metadata/x509/[email protected].
  • Vous devez également utiliser une bibliothèque JWT pour vérifier le jeton avec la clé publique afin de prouver que le jeton a été signé avec la clé privée correspondante des clés publiques.

Pour Go, il semble que vous puissiez utiliser jwt-go pour décoder et valider le jeton d’ID client.

51
Kato

Bien que firebase ne permette pas la vérification de custom tokens, Ce qu'ils font est de permettre la vérification de id tokens. Ils sont générés une fois que l'utilisateur s'est connecté à l'aide de jetons personnalisés. Donc, comme cela a été le cas avec moi, si vous transmettez des jetons personnalisés Firebase à d'autres services pour vous authentifier avec votre backend, alors la vérification des jetons personnalisés incombe à vous! De plus, le compte de service Google X509 cert N’est pas au format correct. Il a ces \n (new line) délimiteurs qui ne sont pas remplacés par de nouvelles lignes dans les éditeurs de texte (j'utilise vim). D'où ce que j'ai fait est la suivante:

  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. Obtenez le lien du certificat du compte de service Google spécifié dans le JSON téléchargé lors de la configuration de Firebase.
  2. Remplacer manuellement \n Par une nouvelle ligne
  3. Obtenez la bibliothèque JWT. J'ai utilisé cette superbe bibliothèque pour effectuer la vérification Java JWT
  4. Lisez le certificat et extrayez la clé publique.
  5. Utiliser la clé publique pour vérifier le jeton
  6. Assurez-vous d'avoir une autre api pour actualiser les jetons, car ils ne sont valables que pendant une heure.

J'espère que ça t'as aidé!

0
Richeek