web-dev-qa-db-fra.com

Utilisation de NodeJs avec Firebase - Sécurité

En raison de la nécessité de faire du code côté serveur - principalement pour envoyer des e-mails, j'ai décidé d'utiliser Nodejs & Express pour l'élément côté serveur avec Firebase pour conserver les données - en partie à partir d'une expérience d'apprentissage.

Ma question est quelle est la meilleure approche en ce qui concerne l'utilisation de la bibliothèque Firebase côté client et de la bibliothèque Nodejs lors de l'authentification à l'aide de l'API Simple Email & Password. Si je fais le côté client d'authentification et que j'appelle ensuite une route différente du côté NodeJS, l'authentification de cet utilisateur sera transmise dans la demande. Quelle serait l'approche pour tester l'utilisateur est authentifié dans Node.

Une approche, je suppose, consiste à obtenir le nom d'utilisateur et le mot de passe des utilisateurs actuels de Firebase, puis à les publier sur NodeJS, puis à utiliser l'API de sécurité Firebase sur le serveur pour tester.

41
markbarton

Essentiellement, le problème ici est que vous devez transmettre en toute sécurité à votre serveur NodeJS qui le client est authentifié quant à Firebase. Il existe plusieurs façons de procéder, mais la plus simple consiste probablement à faire passer toutes les communications de vos clients <-> NodeJS par Firebase lui-même.

Ainsi, au lieu que le client atteigne un point de terminaison REST servi par votre serveur NodeJS, demandez au client d'écrire dans un emplacement Firebase que votre serveur NodeJS surveille. Ensuite, vous pouvez utiliser les règles de sécurité Firebase pour valider la les données écrites par le client et votre serveur peuvent y faire confiance.

Par exemple, si vous vouliez faire en sorte que les utilisateurs puissent envoyer des e-mails arbitraires via votre application (avec votre serveur NodeJS prenant réellement en charge l'envoi des e-mails), vous pourriez avoir un emplacement/emails_to_send avec des règles comme ceci:

{
  "rules": {
    "emails_to_send": {
      "$id": {
        ".write": "!data.exists() && newData.child('from').val() == auth.email",
        ".validate": "newData.hasChildren(['from', 'to', 'subject', 'body'])"
      }
    }
  }
}

Ensuite, dans le client, vous pouvez faire:

ref.child('emails_to_send').Push({
  from: '[email protected]', 
  to: '[email protected]', 
  subject: 'hi', 
  body: 'Hey, how\'s it going?'
});

Et dans votre code NodeJS, vous pouvez appeler .auth () avec votre Firebase Secret (afin que vous puissiez tout lire et écrire), puis faire:

ref.child('emails_to_send').on('child_added', function(emailSnap) {
  var email = emailSnap.val();
  sendEmailHelper(email.from, email.to, email.subject, email.body);

  // Remove it now that we've processed it.
  emailSnap.ref().remove();
});

Cela va être la solution la plus simple et la plus correcte. Par exemple, si l'utilisateur se déconnecte via Firebase, il ne pourra plus écrire sur Firebase et ne pourra donc plus envoyer votre serveur NodeJS envoyer des e-mails, ce qui est très probablement le comportement que vous souhaitez. Cela signifie également que si votre serveur est temporairement hors service, lorsque vous le redémarrerez, il "rattrapera" l'envoi des e-mails et tout continuera à fonctionner.

56
Michael Lehenbauer

Ce qui précède semble être une manière détournée de faire les choses, j'utiliserais quelque chose comme https://www.npmjs.com/package/connect-session-firebase et garder Firebase comme modèle, gérer tous les itinéraires par express. Plus facile si votre serveur express rend des modèles et ne se comporte pas uniquement comme une API JSON.

1
Andrew Plummer