Firebase-tools: Ajouter un émulateur d'authentification Firebase à la suite d'émulateurs

Créé le 26 sept. 2019  ·  66Commentaires  ·  Source: firebase/firebase-tools

Est-il possible d'émuler l'API d'authentification pour un développement local plus rapide et des tests de bout en bout ? Avec l'émulateur Firestore, nous n'avons pas besoin de créer différents projets pour différents environnements (dev, testing, staging, prod), nous pouvons simplement utiliser l'émulateur, lui fournir des données à partir de fichiers JSON en mode veille pour le développement, ou l'amorçage pour chaque cas de test, etc. Pour pouvoir écrire un test de bout en bout avec une connexion utilisateur, une navigation basée sur le rôle, puis une action, nous devons créer un projet distinct pour isoler les utilisateurs de test, et également amorcer et effacer les utilisateurs là-bas pour chaque cas de test.

emulator-suite feature request

Commentaire le plus utile

Nous travaillons dur sur un émulateur d'authentification complet qui, espérons-le, sera ce que
tout le monde veut. Je ne peux pas proposer de calendrier pour le moment, mais c'est une priorité élevée
pour nous.

Le vendredi 22 mai 2020 à 8h12, ChuckB [email protected] a écrit :

@samtstern https://github.com/samtstern Tout progrès ou autre
solution à ce problème/fonctionnalité ? J'ai besoin de (1) setEmulatedUser pour travailler avec le
l'émulateur cloud Firestore pour que je puisse effectuer des tests manuels localement.

Par votre commentaire : le 17 octobre 2019
_Je pense clairement que (2) est la bonne histoire mais j'essayais d'avoir une idée de
combien de personnes seraient satisfaites de (1) puisqu'il est beaucoup plus simple de
mettre en œuvre et maintenir.

(1) Connectez-vous pour utiliser des services comme Firestore ou Realtime Database sans
créant réellement de vrais utilisateurs. En ce moment c'est ce que quelque chose comme
setEmulatedUser résoudrait. Cela vous permettrait juste d'avoir une fausse authentification
jeton localement que les émulateurs accepteraient mais il serait rejeté par
prod. Plus de sécurité, plus d'isolement, etc._

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

Tous les 66 commentaires

@vladimirdjurdjevic merci d'avoir soulevé cette question ! C'est sur notre liste de choses à faire, mais nous n'avons pas encore décidé de la quantité de service d'authentification à émuler et de la meilleure stratégie pour le faire. Certaines choses (comme l'authentification anonyme) sont très faciles à émuler tandis que d'autres (comme l'authentification SMS) sont très difficiles.

Mais nous voulons absolument activer le cas d'utilisation de bout en bout que vous avez mentionné !

Question : trouveriez-vous utile s'il existait une bibliothèque vous permettant de vous moquer localement d'un utilisateur Firebase à utiliser avec les émulateurs ? Quelque chose comme:

firebase.auth().setEmulatedUser({
   uid: 'abc123',
   // ...
});

@samtstern L'appel à setEmulatedUser() déclencherait-il également des fonctions cloud émulées functions.auth.user().onCreate() ? Si oui, ce serait très utile.

@samtstern Cela aiderait certainement certains scénarios de test, mais nécessiterait toujours une instance réelle pour le développement. Mon idée est d'éviter de créer plusieurs projets firebase pour différents environnements, et de pouvoir développer localement (hors ligne peut-être). Une autre approche consisterait à prendre en charge différents environnements pour les services. Si nous pouvions créer des environnements différents pour, disons, firestore et auth sous le même projet, cela résoudrait de nombreux problèmes. Je sais que je peux créer un projet par environnement, mais c'est vraiment chiant. Configuration de chaque environnement, réplication des données, etc. Idéalement, j'aimerais pouvoir créer un projet firebase, et si j'ai besoin de données factices pour les tests manuels, je pourrais simplement créer un environnement de transfert pour firestore et y télécharger des données.

@noelmansour bonne question ! Ce ne serait pas trop difficile à faire, nous voudrions probablement deux appels différents comme signInAsEmulatedUser et signUpAsEmulatedUser où seul le second déclenche la fonction.

@vladimirdjurdjevic est tout à fait d'accord pour dire qu'un émulateur complet est le meilleur. Pourriez-vous expliquer de quelles choses vous auriez besoin d'une "instance réelle pour le développement" qui ne sont pas résolues en étant capable de définir l'utilisateur localement ?

Question : trouveriez-vous utile s'il existait une bibliothèque vous permettant de vous moquer localement d'un utilisateur Firebase à utiliser avec les émulateurs ?

Vraiment utile, cela aiderait beaucoup.
En ce moment, je règle simplement sur true la fonction de règle validant l'utilisateur connecté chaque fois que je dois tester quelque chose localement, c'est assez dangereux mais probablement la chose la plus simple que je puisse faire sans utilisateur actuel émulé.

Oui ce serait incroyablement utile

Je voudrais aussi tester unitairement functions.auth.user().onCreate() . Je suppose qu'à l'heure actuelle, la meilleure solution de contournement consiste essentiellement à exporter la fonction de rappel transmise à onCreate et à lui fournir un faux objet user .

Pour ce type de test unitaire, consultez le firebase-functions-test
bibliothèque, qui vous aide à appeler vos gestionnaires de fonctions avec des données fictives.

Le dimanche 13 octobre 2019, 05h44, Daniel K. [email protected] a écrit :

Je voudrais aussi tester unitairement functions.auth.user().onCreate(). je
supposons qu'actuellement la meilleure solution de contournement consiste essentiellement à exporter le rappel
fonction transmise à onCreate et lui fournir un faux objet utilisateur.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/firebase/firebase-tools/issues/1677?email_source=notifications&email_token=ACATB2QYJLX2LNVDTWJV25TQOMJ4VA5CNFSM4I27PTFKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWWSH2K
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/ACATB2SO3IR6UB73F4EMZPTQOMJ4VANCNFSM4I27PTFA
.

@samtstern Cela t -il réellement avec l'émulateur Firestore ? Sur cette base, j'ai l'impression que c'est à des fins différentes.

image
https://firebase.google.com/docs/functions/unit-testing#initializing

Je ne veux certainement pas de mode en ligne pour les tests unitaires, ce serait un ralentissement. Et je ne sais pas si je peux accéder à l'émulateur Firestore par "stubbing".

@FredyC merci d'avoir signalé ces documents. Les mots utilisés prêtent à confusion car les "modes" ne sont pas un commutateur que vous pouvez activer, ils décrivent simplement des stratégies que vous pouvez adopter.

Si vous deviez démarrer l'émulateur Firestore en même temps que vos tests unitaires, votre code pourrait certainement s'y connecter. Si vous définissez la variable d'environnement FIRESTORE_EMULATOR_HOST , le SDK Admin Firebase se connectera automatiquement à l'émulateur Firestore ( firebase emulators:exec fait pour vous).

@samtstern J'ai toujours du mal à connecter des points et comment tout cela va-t-il m'aider à tester functions.auth.user().onCreate() ? Je veux dire, c'est bien que les fonctions se connectent à l'émulateur au lieu d'une version de production, mais ce n'est que Firestore, non? Comment puis-je invoquer la création d'utilisateurs à partir de tests pour avoir réellement le code de fonction à lancer ?

Il semble y avoir une méthode cryptique makeUserRecord dans le firebase-functions-test mentionné, mais cela n'a pas beaucoup de sens comment cela fonctionnerait ou comment l'utiliser réellement.

J'ai essayé d'appeler auth.createUserWithEmailAndPassword() partir du package @firebase/testing , mais cela se plaint d'une clé API invalide, donc je suppose que cela ne fonctionnerait qu'avec la version en ligne.

Lorsque je recherche dans org cette variable d'environnement que vous avez mentionnée, ce n'est qu'à trois endroits et aucun ne semble vraiment pertinent pour auth. À moins qu'il ne soit masqué par une concaténation de chaînes.

J'ai également parcouru le https://github.com/firebase/functions-samples mais je n'y ai trouvé aucun exemple de test unitaire.

Pouvez-vous s'il vous plaît donner un sens à cela? :)

J'ai aussi un autre cas, un peu opposé, où le code de la fonction cloud utilise l'appel admin.auth().getUserByEmail() . Étonnamment, cela ne se termine pas par l'erreur, mais je n'ai aucune idée de la façon dont je créerais cet utilisateur pour qu'il puisse être renvoyé. Sauf bien sûr se moquer de tout le module d'administration, mais c'est fou :)

@samtstern Désolé pour le retard. Quand je dis instance réelle, je veux dire instance réelle :D Idéalement, je veux juste échanger la configuration dans mon fichier d'environnement angulaire pour le développement, et continuer à implémenter des fonctionnalités d'authentification comme mon application parle à une API réelle, mais en fait, l'émulateur s'exécute sur mon machine, et je peux le faire hors ligne. Maintenant, je comprends les défis avec l'envoi de SMS par exemple. Il serait idiot de s'attendre à ce que l'émulateur envoie de vrais SMS sur mon téléphone, mais vous pouvez peut-être simplement l'imprimer sur la console (le contenu du SMS qui serait envoyé). C'est probablement plus compliqué que la valeur avec ça. C'est pourquoi je pense que le simple fait de prendre en charge plusieurs environnements par projet pourrait rendre les choses bien meilleures. Il faut beaucoup de temps pour répliquer les configurations entre plusieurs projets pour différents environnements. De plus, la gestion de plusieurs comptes de service pour que les scripts puissent introduire des données dans différents projets Firestore est pénible. C'est pourquoi j'ai enseigné que si nous avions une plate-forme Firebase entière émulée, nous pourrions l'utiliser pour chaque environnement hors production et gérer un seul projet Firebase réel. Mais peut-être que le simple fait de prendre en charge plusieurs environnements par projet est une meilleure solution avec un résultat acceptable.

@FredyC merci pour tous vos retours ! C'est vraiment utile pour nous de voir à quel point cela peut être déroutant. Il y a deux choses principales que les gens veulent faire dans leurs tests liés à l'authentification :

  1. Connectez-vous pour utiliser des services tels que Firestore ou Realtime Database sans créer de véritables utilisateurs. À l'heure actuelle, c'est ce que quelque chose comme setEmulatedUser résoudrait. Cela vous permettrait simplement d'avoir un faux jeton d'authentification localement que les émulateurs accepteraient mais il serait rejeté par prod. Plus de sécurité, plus d'isolement, etc.
  2. En fait, testez directement l'authentification. Cela aurait quelques morceaux:
    une. Un émulateur d'authentification qui répond à tous les appels d'API nécessaires afin que vous puissiez y pointer les SDK d'authentification.
    b. Intégration entre cet émulateur et l'émulateur de fonctions afin que les fonctions .onCreate soient déclenchées correctement.
    c. Mocking automatique à l'intérieur de l'émulateur de fonctions afin que admin.auth() pointe vers l'émulateur Auth, tout comme nous le faisons pour Firestore et RTDB aujourd'hui.

Je pense clairement que (2) est la bonne histoire, mais j'essayais d'avoir une idée du nombre de personnes qui seraient satisfaites de (1) car c'est considérablement plus simple à mettre en œuvre et à maintenir.

@samtstern je vois. Corrigez-moi si je me trompe, mais le (1) n'est-il pas déjà résolu ? Je veux dire que dans les tests, je peux simplement appeler ce qui suit et l'émulateur Firestore me reconnaîtra comme cet utilisateur afin que je puisse tester les règles de sécurité. Je n'ai pas encore essayé ça, mais ça a l'air prometteur pour l'instant :)

  const app = firebase.initializeTestApp({
    projectId,
    auth: {
      uid: 'owner'
    }
  })

Le (2) semble certainement très utile, mais beaucoup plus complexe à aborder à coup sûr. Malheureusement, ma compréhension du produit complet est si limitée que je ne peux pas vraiment proposer d'idées utiles ici.

Je pense qu'il devrait être construit progressivement. Au lieu d'essayer de couvrir tous les scénarios à la fois, construisez-le en fonction de cas d'utilisation connus et ajoutez-le à tout moment. À mon avis limité, émuler la "base de données utilisateur" avec des déclencheurs de fonction ne semble pas si difficile à faire.

@FredyC, vous avez raison, (1) est résolu pour être utilisé dans les suites de tests. Mais l'autre cas d'utilisation consiste en fait à connecter votre application Android/iOS/Web directement à l'émulateur pour le développement local. Dans ce cas, vous ne pouvez pas utiliser @firebase/testing .

Je vois. Honnêtement, ce serait génial si @firebase/testing pouvait être utilisé sur plusieurs plates-formes au lieu d'avoir des solutions séparées. Je veux dire à quel point il peut être difficile de rediriger la communication vers l'émulateur ? Le FIRESTORE_EMULATOR_HOST n'est-il pas exactement pour cela ? Bien que je pense que quelque chose comme FIREBASE_EMULATOR_HOST serait plus approprié si l'émulateur doit également avoir d'autres services.

@vladimirdjurdjevic Je pense que cela ne fonctionnerait pas réellement pour signInWithPhone afin que vous puissiez contrôler son comportement? Ensuite, vous n'avez pas à vous soucier d'un émulateur et d'obtenir un code SMS simulé dans la console :)

Bien sûr, vous avez besoin d'un moyen de vous authentifier auprès de l'émulateur pour Firestore (et de vous y connecter). Quelque chose comme je l'ai décrit dans le précédent https://github.com/firebase/firebase-tools/issues/1677#issuecomment -542897671. Il existe une méthode sous-jacente pour générer des jetons non sécurisés : https://github.com/firebase/firebase-js-sdk/blob/master/packages/testing/src/api/index.ts#L64. Pas sûr que ça marche.

Bien sûr, se moquer des bibliothèques tierces n'est pas toujours aussi simple, mais une fois compris, cela peut apporter d'excellents résultats. Finalement, il pourrait être extrait dans une bibliothèque pour le rendre généralement plus facile.

Je pense également que ces méthodes de connexion peuvent générer une pléthore de codes d'erreur, ce que les tests appropriés devraient également prendre en compte. C'est aussi facile à faire avec la moquerie.

@samtstern Étendre le contexte de l'espace firebase.auth() noms setEmulatedUser semble être un anti-modèle avec les stratégies d'émulation existantes. Cette recommandation est-elle peut-être influencée par la facilité d'extensibilité du côté de l'emballage ?

En ligne avec les autres émulateurs, je m'attendrais à ce qu'un niveau de service d'authentification distinct soit lancé sur HTTP et qu'une configuration côté client puisse rediriger la surface API existante à utiliser.

Je préférerais de loin que les cas AuthN excentriques renvoient des erreurs avec l'API Admin et Client prenant en charge au minimum CRUD pour les utilisateurs de base par rapport au nom d'utilisateur/mot de passe. Zut, je pense que même en commençant par la prise en charge des jetons personnalisés dans l'administrateur et signInWithCustomToken irait très loin. Peut-être implémenter des fruits à portée de main avec une matrice de prise en charge des API publiée dans la documentation.

Au point @FredyC , la stratégie actuelle pour les tests d' @firebase/testing dans le code de l'application pour l'acheminer vers l'appel personnalisé initializeTestApp . Cette action met à la fois l'accent sur l'exclusion des packages au moment de la construction pour les équipes de projet et répartit également les configurations de redirection de l'émulateur sur deux API de package ( initializeTestApp et firestore.settings / functions.useFunctionsEmulator )

Piratez la planète !

la stratégie actuelle pour les tests d'authentification d'intégration consiste à importer sous condition le @firebase/testing dans le code de l'application pour l'acheminer vers l'appel initializeTestApp .

Euh, j'appelle cette méthode dans les tests. L'astuce est que le initializeApp régulier réside dans index.ts qui importe les fonctions. Il est appelé au démarrage de l'émulateur, mais lorsque les tests s'exécutent, c'est un processus différent et il n'entre pas en conflit les uns avec les autres. Il n'y a donc vraiment pas de fardeau d'importation conditionnelle.

Bien sûr, cela peut être différent pour tester l'authentification dans, par exemple. application Web où le testeur partagerait le processus avec le code de l'application. Cependant, avec les tests unitaires, vous n'importez généralement pas une application entière dans un test. Le initializeApp est probablement fait dans du code qui n'est pas pertinent pour les tests et n'est pas du tout importé.

@FredyC D'accord sur les utilisations documentées pour les tests unitaires. Parlait vraiment de scénarios d'application complète où les API divergent et les importations dynamiques sortent de la carte documentée.

Je voulais juste vous donner une attribution pour Honestly, it would be kinda superb if @firebase/testing could be used cross-platform instead of having separate solutions . high five numérique

@FredyC merci pour tous vos retours ! C'est vraiment utile pour nous de voir à quel point cela peut être déroutant. Il y a deux choses principales que les gens veulent faire dans leurs tests liés à l'authentification :

  1. Connectez-vous pour utiliser des services tels que Firestore ou Realtime Database sans créer de véritables utilisateurs. À l'heure actuelle, c'est ce que quelque chose comme setEmulatedUser résoudrait. Cela vous permettrait simplement d'avoir un faux jeton d'authentification localement que les émulateurs accepteraient mais il serait rejeté par prod. Plus de sécurité, plus d'isolement, etc.
  2. En fait, testez directement l'authentification. Cela aurait quelques morceaux:
    une. Un émulateur d'authentification qui répond à tous les appels d'API nécessaires afin que vous puissiez y pointer les SDK d'authentification.
    b. Intégration entre cet émulateur et l'émulateur de fonctions afin que les fonctions .onCreate soient déclenchées correctement.
    c. Mocking automatique à l'intérieur de l'émulateur de fonctions afin que admin.auth() pointe vers l'émulateur Auth, tout comme nous le faisons pour Firestore et RTDB aujourd'hui.

Je pense clairement que (2) est la bonne histoire, mais j'essayais d'avoir une idée du nombre de personnes qui seraient satisfaites de (1) car c'est considérablement plus simple à mettre en œuvre et à maintenir.

@samtstern tout d'abord je voudrais ❤️avoir ce genre d'émulation.

Je verrais non. 1 très utile pour écrire des tests e2e. Actuellement, je dois utiliser une instance réelle pour l'authentification, tandis que je peux utiliser un émulateur pour l'hébergement, les règles, le firestore et les fonctions.

Je pense qu'il devrait être possible d'utiliser setEmulatedUser pour se moquer de l'utilisateur de la même manière que dans firebase.initializeTestApp. Il devrait être possible de soumettre, par exemple, des jetons personnalisés et d'autres données relatives à l'utilisateur.

Il devrait également être possible d'obtenir des exemples d'informations d'identification qui pourraient être utilisées dans l'application cliente avec firebase.auth().signInWithCredential(credential)

Merci @vladimirdjurdjevic d'avoir soulevé ce problème ! Nous cherchions une solution depuis presque un an déjà.

Nous aimerions voir un véritable émulateur pour trois choses :

  1. tests e2e pour l'ensemble de l'application, nous n'avons donc pas à créer différents environnements comme l' a dit
  2. Tests d'intégration pour le backend, où les API sont appelées et l'utilisateur doit être validé sur Firebase.
  3. Tous nos développeurs utilisent un environnement Firebase central pendant le développement, ce qui provoque de nombreuses collisions. Bien sûr, chaque développeur peut créer son propre projet Firebase, mais il doit toujours gérer ses utilisateurs de test dans le tableau de bord Firebase, ce qui n'est pas idéal. De plus, nous aimerions développer notre application hors ligne, ce qui n'est pas possible aujourd'hui en raison de l'absence d'un véritable émulateur.

J'espère que vous publierez bientôt quelque chose pour nous, cela rendrait votre produit plus précieux ! La productivité des développeurs est très importante dans de tels services !

Cela semble être une caractéristique sur la liste de souhaits de nombreuses personnes. L'authentification Firebase semble être l'IDaaS n°1 en ce moment en termes de prix, c'est donc vraiment pénible que vous ne puissiez pas développer localement avec Cloud Functions. J'espère que l'équipe FB aura des mises à jour pour nous bientôt! ??

Edit: Ping @mbleigh de @firebase-ops puisque ce fil est enterré sous des problèmes ...

J'ai aussi cette erreur ... fonction ignorée car l'émulateur d'authentification n'existe pas ou n'est pas en cours d'exécution.

c'est déclenché par ce code :

fonctions.auth.user().onDelete()

des infos à ce sujet...

@dominikfoldi

Je suis d'accord avec tes propos. Une astuce qui pourrait vous aider en attendant :

Bien sûr, chaque développeur peut créer son propre projet Firebase, mais il doit toujours gérer ses utilisateurs de test dans le tableau de bord Firebase, ce qui n'est pas idéal.

Vous pouvez amorcer et gérer les utilisateurs par programmation à l'aide du SDK d'administration Firebase, par exemple auth().createUser , voir également https://firebase.google.com/docs/auth/admin/manage-users

Après avoir lu ce fil, je pense que les gens ici pourraient trouver Foundry utile.

Je suis l'un des co-fondateurs de Foundry. Foundry est un outil CLI qui prend vos fonctions Firebase Cloud et crée une copie de votre application Firebase de production sur nos serveurs qui agissent comme votre environnement de développement dans lequel vous exécutez directement votre code. Aucune configuration n'est requise.

Foundry surveille vos fichiers de code source et chaque fois que vous enregistrez votre code localement, nous l'exécutons sur nos serveurs et vous renvoyons les résultats en quelques secondes seulement. Tout est ultra rapide.
Vous spécifiez quelles données Firestore, RealtimeDB et Auth Users doivent être copiées à partir de votre application de production via notre fichier YAML afin que vous les ayez disponibles pendant le développement.

 users:
      - getFromProd: 5 # Copy first 5 users from your Firebase project
      - getFromProd: ['id-1', 'id-2'] # Copy users with the specified IDs from your Firebase project

 # Copy first 3 documents from production from the collection 'userWorkspaces'
 # also add a custom document with id 'new-user-workspace' with a new data
 # format that you want to use
 firestore:
     - collection: userWorkspaces
       docs:
         - getFromProd: 3
         - id: new-user-workspace
           data: {"newDataFormat": 42}

Vous spécifiez également comment nous devons déclencher vos fonctions cloud lorsque nous exécutons votre code. Cela fonctionne un peu comme un REPL pour vos fonctions cloud. De cette façon, vous êtes toujours sûr que vos fonctions cloud fonctionneront correctement avec les données de production et dans l'environnement de production une fois que vous les aurez déployées.
De plus, vos fonctions cloud agissent comme si elles étaient déployées.

Ces environnements de développement sont créés ad-hoc une fois que vous démarrez votre session. Ainsi, tous les membres de votre équipe opèrent dans leur propre environnement où ils peuvent s'amuser.

Je ne veux pas spammer la discussion ici, alors n'hésitez pas à m'envoyer un e-mail pour toute question [email protected]
Je suis plus qu'heureux de vous aider à mettre en place Foundry dans vos projets, envoyez-moi simplement un e-mail !

Pourtant, d'après la façon dont vous l'avez décrit et ce que j'ai lu sur la page d'accueil, ce service est basé sur le cloud.
L'émulateur Firebase fonctionne même hors ligne, d'où son utilité pour les tests automatiques.

@samtstern Des progrès ou une autre solution à ce problème/fonctionnalité ? J'ai besoin de (1) setEmulatedUser pour travailler avec l'émulateur Cloud Firestore afin de pouvoir effectuer des tests manuels localement. Une autre option serait d'avoir un argument de ligne de commande qui définit l'identifiant de l'utilisateur au démarrage de l'émulateur. De cette façon, l'émulateur fonctionnerait sous l'ID utilisateur transmis lors du démarrage. De cette façon, les règles pourraient être testées localement.

Par votre commentaire : le 17 octobre 2019
_Je pense clairement que (2) est la bonne histoire, mais j'essayais d'avoir une idée du nombre de personnes qui seraient satisfaites de (1) car c'est considérablement plus simple à mettre en œuvre et à maintenir.

(1) Connectez-vous pour utiliser des services tels que Firestore ou Realtime Database sans créer de véritables utilisateurs. À l'heure actuelle, c'est ce que quelque chose comme setEmulatedUser résoudrait. Cela vous permettrait simplement d'avoir un faux jeton d'authentification localement que les émulateurs accepteraient mais il serait rejeté par prod. Plus de sécurité, plus d'isolement, etc._

Nous travaillons dur sur un émulateur d'authentification complet qui, espérons-le, sera ce que
tout le monde veut. Je ne peux pas proposer de calendrier pour le moment, mais c'est une priorité élevée
pour nous.

Le vendredi 22 mai 2020 à 8h12, ChuckB [email protected] a écrit :

@samtstern https://github.com/samtstern Tout progrès ou autre
solution à ce problème/fonctionnalité ? J'ai besoin de (1) setEmulatedUser pour travailler avec le
l'émulateur cloud Firestore pour que je puisse effectuer des tests manuels localement.

Par votre commentaire : le 17 octobre 2019
_Je pense clairement que (2) est la bonne histoire mais j'essayais d'avoir une idée de
combien de personnes seraient satisfaites de (1) puisqu'il est beaucoup plus simple de
mettre en œuvre et maintenir.

(1) Connectez-vous pour utiliser des services comme Firestore ou Realtime Database sans
créant réellement de vrais utilisateurs. En ce moment c'est ce que quelque chose comme
setEmulatedUser résoudrait. Cela vous permettrait juste d'avoir une fausse authentification
jeton localement que les émulateurs accepteraient mais il serait rejeté par
prod. Plus de sécurité, plus d'isolement, etc._

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

1. Connectez-vous pour utiliser des services tels que Firestore ou Realtime Database sans créer de véritables utilisateurs. À l'heure actuelle, c'est ce que quelque chose comme setEmulatedUser résoudrait. Cela vous permettrait simplement d'avoir un faux jeton d'authentification localement que les émulateurs accepteraient mais il serait rejeté par prod. Plus de sécurité, plus d'isolement, etc.

Je serais heureux avec le numéro 1 ici, dans l'intervalle

@rishisingh-dev, il n'est pas possible de faire fonctionner un émulateur d'authentification car les émulateurs Firebase n'en fournissent actuellement pas.

Mais il est parfaitement possible de tester des fonctions cloud qui impliquent une authentification. Vous pouvez refactoriser la fonction qui a besoin d'une API d'authentification et la simuler sur les tests, tout en fournissant la vraie dans le fichier de fonctions Firebase. La fidélité de votre configuration de test est plus faible, mais cela devient alors une question de degré, pas une question de nature : vous testez simplement les appels d'authentification directement, mais vous pouvez tester ce que vous attendez d'eux.

Dans cette question SO, ce serait quelque chose comme:

function sendWelcomeEmail(user) {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
}

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => sendWelcomeEmail(user));

Et lors de vos tests, vous appelez directement sendWelcomeEmail pour vous assurer qu'il fait ce que vous en avez besoin.

Imaginez que vous ayez une fonction cloud plus compliquée appelée addFriend , où l'utilisateur saisit un e-mail d'amis et vous voulez l'uid. Vous pouvez l'obtenir via auths getUserByEmail .

function addFriend(email, getUserByEmail ) {
  const friendUid = getUserByEmail(email);
  // do things with friendUid;
}

exports.addFriend = functions.https.onCall(async (data, context) => {
  const email = data.email;
  const getUserByEmail = (email) => admin.auth().getUserByEmail(email);
  return { res: await addFriend(email, getUserByEmail ) };
}

Sur la déclaration cloud fn, vous envoyez le vrai getUserByEmail , mais sur vos tests, vous envoyez à la place un faux :

async function testAddFriend() {
  const emails = {"[email protected]": "test-uid")
  const fakeGetUserByEmail = (email) => emails[email];
  addFriend("[email protected]);
  // verify the things were done with friendUid
}

Je ne pense pas que ce soit très différent du test d'une API tierce dans un test unitaire. Le fait que les émulateurs Firebase fournissent l'authentification supprime les scénarios de test de bout en bout, mais cela ne modifie pas de manière significative les tests unitaires, car vous ne voudriez pas de toute façon que l'état persistant soit conservé entre les tests.

J'aimerais pouvoir l'exécuter localement sans avoir à télécharger sur le cloud pour vérifier

export const onCreate = functions.auth.user().onCreate((user) => {
    addGravatarURLtoUserData(user.uid, user.email)
})

export const addGravatarURLtoUserData = async (uid, email) => {
    const hash = crypto.createHash("md5").update(email).digest("hex")
    await admin.database().ref(`users/${uid}`).update({ gravatarURL: uid })
}

Au fait, puis-je obtenir user.displayName dans la fonction onCreate ?

oui si c'est réglé je pense, tu l'as essayé ?

Oui, il retourne null.
Je l'ai essayé sur le cloud (pas localement).

Screen Shot 2020-07-10 at 2 43 12 AM

Mon code est ici.

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
});

Intéressant bien je n'utilise pas le nom d'affichage, j'utilise les utilisateurs personnalisés displayName pour
db en temps réel

/**
 * updates Custom data in the realtime datastore users object, except for the username
 * <strong i="7">@param</strong> data
 * <strong i="8">@returns</strong> {Promise<void>}
 */
export async function updatePersonalData(data) {
    const { displayName } = data
    try {
        await firebase
            .database()
            .ref("users/" + firebase.auth().currentUser.uid)
            .update({
                displayName: displayName,
            })

        userDataStore.update((user) => {
            return { ...user, displayName: displayName }
        })
    } catch (e) {
        alert(e.message)
    }
}

Le ven. 10 juil. 2020 à 10:44, rishisingh-dev [email protected]
a écrit:

Oui, il retourne null.
Je l'ai essayé sur le cloud (pas localement).

[image : Capture d'écran 2020-07-10 à 2 43 h 00]
https://user-images.githubusercontent.com/56976320/87140958-29f3ac80-c257-11ea-98d3-084fad619de7.png

Mon code est ici.

console.log(user.uid);
console.log(utilisateur.email);
console.log(user.displayName);
});```

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-656587759 ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AABU35Q27EMMHYAYU5CNZR3R23PIDANCNFSM4I27PTFA
.

>

Bien à vous

Nikos Katsikanis

Oui, mon objectif principal était de mettre à jour la base de données avec les informations utilisateur dans la fonction onCreate .
Mais comme je ne peux pas obtenir displayName , j'ai créé une fonction onCallable et je l'ai fait.

Merci.

@samtstern Je suis très heureux de vous voir travailler dessus :) Je viens de commencer un nouveau projet avec firebase, et l'expérience de développement est déjà bien meilleure (avec l'interface utilisateur de l'émulateur et l'option --inspect-functions). J'ai hâte de voir l'émulateur d'authentification en action :) Excellent travail !

une autre des meilleures choses est que je n'ai pas à ouvrir Chrome sans sécurité

@samtstern

Deux mois plus tard, est-il désormais possible de donner une estimation approximative ?

Nous aimerions expédier au début de l'année prochaine. Nous sommes maintenant confrontés à la décision si nous commençons à écrire des tests d'intégration sur un projet réel ou si nous attendons quelques mois l'émulateur d'authentification. Pourriez-vous nous aider un peu ici?

Meilleur,

Niklas

Notre politique chez Firebase est de ne pas donner d'estimations sur le lancement de quelque chose à moins que nous ne soyons sûrs à 100 %. En ce moment, nous travaillons dur sur l'émulateur Auth, mais nous ne sommes pas assez près d'avoir terminé pour choisir une date de lancement.

C'est l'une de nos priorités, mais je pense que vous ne devriez pas attendre que nous commencions à tester votre application. Ecrivez vos tests contre prod aujourd'hui, changez-les pour cibler l'émulateur lorsqu'il sera disponible.

D'accord, merci @samtstern. Qui aide!

Nous aimerions vraiment utiliser un émulateur d'authentification pour tester les requêtes Cloud Functions et Firestore qui impliquent des revendications personnalisées sur les jetons utilisateur. Nous pouvons en quelque sorte tester les revendications personnalisées avec Firestore dans le terrain de jeu des règles de la console Firebase, mais un émulateur d'authentification à part entière nous permettrait théoriquement de faire beaucoup plus de tests en ce qui concerne les jetons utilisateur.

Pour être clair : nous nous engageons à utiliser un émulateur d'authentification à part entière qui émule les points de terminaison de service réels (dans la mesure du possible). Nous n'envisageons plus quelque chose de léger comme mes commentaires précédents le suggéraient.

@samtstern c'est bon à entendre (avec les revendications personnalisées, car elles sont souvent utilisées avec des intégrations tierces). Y a-t-il un endroit où nous pouvons suivre les progrès/ETA ?

@fandy non désolé nous n'avons encore rien à partager...

Merci Sam, actuellement je fais tous mes tests manuellement car ce n'est pas le cas
Cela vaut la peine d'écrire des tests e2e sans simulations Auth

Le mercredi 26 août 2020 à 14h32, Sam Stern [email protected] a écrit :

>
>

@fandy https://github.com/fandy non désolé nous n'avons rien à faire
partager encore...

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-680850282 ,
ou se désinscrire
https://github.com/notifications/unsubscribe-auth/AABU35UAQDBYEXKKINJSM43SCT6E7ANCNFSM4I27PTFA
.

--

Bien à vous

Nikos Katsikanis

Pour contourner ce problème, j'ai expérimenté l'importation de @firebase/testing dans le navigateur. Cela n'a pas vraiment fonctionné. Ceci, cependant, fait : mangle @firebase/testing source pour copier le morceau légèrement modifié suivant :

import firebase from "firebase/app"
import * as component from "@firebase/component"
import * as util from "@firebase/util"
import { __awaiter, __generator } from "tslib"

function createUnsecuredJwt(auth) {
    // Unsecured JWTs use "none" as the algorithm.
    var header = {
        alg: 'none',
        kid: 'fakekid'
    };
    // Ensure that the auth payload has a value for 'iat'.
    auth.iat = auth.iat || 0;
    // Use `uid` field as a backup when `sub` is missing.
    auth.sub = auth.sub || auth.uid;
    if (!auth.sub) {
        throw new Error("auth must be an object with a 'sub' or 'uid' field");
    }
    // Unsecured JWTs use the empty string as a signature.
    var signature = '';
    return [
        util.base64.encodeString(JSON.stringify(header), /*webSafe=*/ false),
        util.base64.encodeString(JSON.stringify(auth), /*webSafe=*/ false),
        signature
    ].join('.');
}

function initializeApp(accessToken, options) {
    var _this = this;
    var app = firebase.initializeApp(options);
    if (accessToken) {
        var mockAuthComponent = new component.Component('auth-internal', function () {
            return ({
                getToken: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                    return [2 /*return*/, ({ accessToken: accessToken })];
                }); }); },
                getUid: function () { return null; },
                addAuthTokenListener: function (listener) {
                    // Call listener once immediately with predefined accessToken.
                    listener(accessToken);
                },
                removeAuthTokenListener: function () { }
            });
        }, "PRIVATE" /* PRIVATE */);
        app._addOrOverwriteComponent(mockAuthComponent);
    }
    return app;
}

export function initializeTestApp(options) {
  let accessToken = undefined
  if (options.auth !== undefined) {
    accessToken = createUnsecuredJwt(options.auth)
  }
  return initializeApp(accessToken, options)
}

Maintenant, dans le code côté navigateur de votre application, vous pouvez l'importer, et

  let app
  if (dev) {
    app = initializeTestApp({projectId: "test", auth: {uid: "testuser"}})
    app.firestore().settings({
      host: "localhost:8080",
      ssl: false,
    })
  } else {
    app = firebaseProduction.initializeApp({ firebase config here })
    app.firestore().settings({ firestore config here })
  }
  window.firebase = app

Cela fonctionne très bien ! Maintenant, quand je suis en développement, j'ai un faux utilisateur local que l'émulateur pense être "testuser" (comme le montre le guide de test des règles de sécurité Firestore).

Une autre solution de contournement que j'utilise consiste à remplacer votre authentification (j'utilise de faux utilisateurs générés pour les tests).

Exemple de TypeScript :

import type { User as AuthUser } from '@firebase/auth-types'
// not importing a type, but a module of types
import { auth as authTypes} from 'firebase/app'
type Auth = authTypes.Auth

export const authStub = {
    getUser(uid: string) {
        // for uids like `testuser1234uid`
        let n = uid ? uid.replace("testuser", '').replace("uid", '') : ''
        return Promise.resolve({
            uid,
            email: `test.user${n}@foo.com`,
            emailVerified: true,
            providerData: [{
                providerId: 'google.com',
                email: `test.user${n}@foo.com`,
                uid: `testuser${n}provideruid`,
                phoneNumber: null,
                displayName: `Test User ${n}`.trim(),
                photoURL: 'https://thispersondoesnotexist.com/image',
            }],
            metadata: {
                // https://firebase.google.com/docs/reference/admin/node/admin.auth.UserMetadata
                createTime: new Date().toUTCString(),
                lastSignInTime: new Date().toUTCString()
            },
            customClaims: {
                username: `testuser${n}`
            }
        })
    },
    deleteUser(uid: string) {
        return Promise.resolve()
    },
    async updateUser(uid: string, data: AuthUser) {
        let user = await this.getUser(uid)
        return { ...user, data }
    },
    setCustomUserClaims(uid: string, customUserClaims: Object): Promise<void> {
        return Promise.resolve()
    }
}

export const auth = <Auth><unknown>authStub

Modifiez également vos règles car auth.token n'est pas émulé. Par exemple:

const rules = fs.readFileSync(__dirname + '/src/firebase/firestore/firestore.rules', 'utf8')
const modifiedRules =
    rules
        .replace(/request\.auth\.token\.email_verified/g, "true")
        .replace(/request\.auth\.token\.firebase\.sign_in_provider/g, "'password'")

await firebase.loadFirestoreRules({ projectId, rules: modifiedRules })

Cela fonctionne très bien pour moi. J'espère que ça aide…

Si vous suivez ce fil et souhaitez devenir un testeur Alpha de l'émulateur d'authentification Firebase, procédez comme suit :

  1. Inscrivez-vous au programme Firebase Alpha : https://services.google.com/fb/forms/firebasealphaprogram/
  2. Envoyez-moi un e-mail à l'adresse [email protected] , assurez-vous de l'envoyer à partir de l'adresse e-mail que vous utiliserez pour le test.

Veuillez ne le faire que si vous êtes sérieusement intéressé à essayer un émulateur à un stade précoce et à fournir des commentaires ! Il y aura des bugs et certaines parties de la configuration seront difficiles, mais nous voulons savoir ce que vous en pensez.

@samtstern C'est une excellente nouvelle ! J'adorerais l'essayer, mais je vais en production avec mon projet actuel d'ici la fin de la semaine, donc je ne peux pas me permettre de jouer avec pour le moment. Je m'inscrirai à l'alpha dès que possible :) Merci pour l'excellent travail.

100% voudront essayer ça! tu es l'homme Sam !

@samtstern hâte de l'essayer et d'aider tout ce que je peux !

J'ai besoin d'utiliser la fonctionnalité d'authentification pour tester les fonctions localement à partir d'Android, le contexte d'authentification est toujours nul

Bonne nouvelle, l'émulateur d'authentification fait partie de la nouvelle version 8.14.0 ! ??

Merci pour le travail acharné les gars et @samtstern 💪

des types impressionnants!

Je ne suis que le messager ! L'émulateur Auth a été construit à 99% par @yuchenshi ... et c'est pourquoi je vais lui laisser l'honneur de clore ce problème à son réveil.

Existe-t-il de la documentation sur ce nouvel émulateur ? (comment installer, configurer les clients, etc.)

PSMerci beaucoup pour tout le travail acharné sur ce point. Cela va nous permettre toutes sortes de trucs sympas.

@nicoburns très bientôt ! Annonce officielle, docs et toutes ces bonnes choses à venir très prochainement.

Bonne nouvelle! :) J'ai hâte d'essayer :)

Je sais que vous attendiez cela, alors allons droit au but :

  • L'émulateur d'authentification Firebase est maintenant disponible. Vous pouvez l'obtenir en installant Firebase CLI >= v8.14.0.
  • Suivez le guide Emulator Suite pour commencer et connectez vos applications .
  • Pour des annonces passionnantes comme celle-ci et bien plus encore, connectez-vous MAINTENANT au livestream Firebase Summit .**

** Prise sans vergogne : je fais également une session sur « Comment configurer CI à l'aide de la suite Firebase Emulator » plus tard dans la journée. Le repérage sur le programme de la


_P.S. Je ne peux vraiment pas prendre 99% du crédit puisque l'émulateur d'authentification est bien sûr un travail d'équipe. Diverses personnes chez Firebase et les développeurs Firebase (vous) ont également joué un grand rôle dans cela. Merci!_

@yuchenshi Est-il possible d'exporter les utilisateurs créés à la sortie, comme avec l'émulateur Firestore ?

@vdjurdjevic pas encore, nous y travaillons.

C'est un problème très populaire et chaque mise à jour notifie 50 à 100 personnes. Puisque nous avons maintenant publié l'émulateur Auth, je vais verrouiller ce problème pour les futures mises à jour. Si vous avez une question, un bug ou une demande de fonctionnalité, veuillez commencer un nouveau problème !

Cette page vous a été utile?
0 / 5 - 0 notes