Données utilisateur sécurisées

Firebase Security Rules pour Cloud Storage s'intègre à Firebase Authentication pour fournir une authentification puissante basée sur l'utilisateur pour Cloud Storage. Cela permet un contrôle d'accès précis basé sur les revendications d'un jeton Firebase Authentication.

Authentification des utilisateurs

Lorsqu'un utilisateur authentifié exécute une requête sur Cloud Storage, La variable request.auth est renseignée avec la valeur uid de l'utilisateur. (request.auth.uid), ainsi que les revendications du jeton JWT Firebase Authentication (request.auth.token).

De plus, lorsque vous utilisez l'authentification personnalisée, d'autres revendications sont émises dans le champ request.auth.token.

Lorsqu'un utilisateur non authentifié effectue une requête, la variable request.auth est null

À l’aide de ces données, il existe plusieurs façons courantes d’utiliser l’authentification pour sécuriser :

  • Public : ignorer request.auth
  • Authentification privée: vérifiez que request.auth n'est pas null
  • Utilisateur privé: vérifiez que request.auth.uid est égal à un chemin d'accès uid
  • Groupe privé: vérifiez que les revendications du jeton personnalisé correspondent à la revendication choisie. Lire les métadonnées du fichier pour voir si un champ de métadonnées existe

Public

Toute règle qui ne tient pas compte du contexte request.auth peut être considérée comme public, car elle ne prend pas en compte le contexte d'authentification de l'utilisateur. Ces règles peuvent être utiles pour afficher des données publiques, comme les éléments de jeu, ou tout autre contenu statique.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Privée authentifiée

Dans certains cas, vous pouvez souhaiter que les données soient visibles par tous les utilisateurs authentifiés de votre application, mais pas par les utilisateurs non authentifiés. Depuis le request.auth est null pour tous les utilisateurs non authentifiés, il vous suffit de vérifier la variable request.auth existe pour exiger une authentification:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Utilisateur privé

Le cas d'utilisation de request.auth le plus courant consiste, de loin, à fournir aux utilisateurs aux utilisateurs disposant d'autorisations précises sur leurs fichiers, qu'il s'agisse de l'importation de photos de profil, à la lecture de documents privés.

Étant donné que les fichiers dans Cloud Storage ont un chemin d'accès complet, il suffit d'une information unique permettant d'identifier l'utilisateur dans le chemin d'accès du fichier (comme le uid de l'utilisateur) pour qu'un fichier soit contrôlé par un utilisateur. Cette information peut être vérifiée lors de l'évaluation de la règle :

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth != null && request.auth.uid == userId;
}

Groupe privé

Un autre cas d'utilisation tout aussi courant consiste à accorder des autorisations de groupe sur un objet, comme permettre à plusieurs membres de l'équipe de collaborer sur un document partagé. Il y Pour ce faire, plusieurs approches s'offrent à vous:

  • Générer un jeton personnalisé Firebase Authentication contenant des informations supplémentaires sur un membre du groupe (comme un ID de groupe)
  • Incluez des informations sur le groupe (telles qu'un ID de groupe ou une liste de uid autorisés) dans les métadonnées de fichier.

Une fois ces données stockées dans les métadonnées de jeton ou de fichier, elles peuvent être référencées à partir d'une règle:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

Exemple complet

L'exemple ci-dessous présente des cas simples des quatre types courants de restrictions d'authentification :

service firebase.storage {
  match /b/{bucket}/o {
    match /images {
      // Anyone can view any image (no auth, publicly readable)
      match /{allImages=**} {
        allow read;
      }

      // Only authenticated users can write to "public" images
      match /public/{imageId} {
        allow write: if request.auth != null;
      }

      // Only an individual user can write to "their" images
      match /{userId}/{imageId} {
        allow write: if request.auth.uid == userId;
      }

      // Allow a "group" of users to read/write to shared images
      // An owner metadata property on the object contains the groupId for reads
      // A custom token has been minted with a groupId property for writes
      match /{groupId}/{imageId} {
        allow read: if resource.metadata.owner == request.auth.token.groupId;
        allow write: if request.auth.token.groupId == groupId;
      }
    }
  }
}