Proteggere i dati degli utenti

Firebase Security Rules per Cloud Storage si integra con Firebase Authentication per fornire autenticazione avanzata basata sugli utenti per Cloud Storage. Ciò consente un controllo dell'accesso granulare basato sulle rivendicazioni di un token Firebase Authentication.

Autenticazione degli utenti

Quando un utente autenticato esegue una richiesta contro Cloud Storage, la variabile request.auth viene compilata con la classe uid dell'utente (request.auth.uid) nonché le dichiarazioni del Firebase Authentication JWT (request.auth.token).

Inoltre, quando si utilizza l'autenticazione personalizzata, vengono visualizzate ulteriori dichiarazioni. nel campo request.auth.token.

Quando un utente non autenticato esegue una richiesta, la variabile request.auth è null.

Utilizzando questi dati, esistono diversi modi comuni per usare l'autenticazione a scopo di protezione file:

  • Pubblico: ignora request.auth
  • Autenticazione privata: verifica che request.auth non sia null
  • Utente privato: verifica che request.auth.uid sia uguale a un percorso uid
  • Gruppo privato: controlla le rivendicazioni del token personalizzato per trovare una rivendicazione scelta o leggi i metadati del file per verificare se esiste un campo dei metadati

Pubblico

Qualsiasi regola che non considera il contesto request.auth può essere considerata una public, poiché non prende in considerazione il contesto di autenticazione dell'utente. Queste regole possono essere utili per mostrare dati pubblici come asset di giochi, file audio o altri contenuti statici.

// 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");
}

Autenticato privato

In alcuni casi, potresti volere che i dati siano visualizzabili da tutti gli utenti autenticati della tua applicazione, ma non da quelli non autenticati. Poiché la variabile request.auth è null per tutti gli utenti non autenticati, devi solo verificare che la variabile request.auth esista per richiedere l'autenticazione:

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

Utente privato

Il caso d'uso più comune di request.auth sarà di gran lunga quello di fornire dati utenti con autorizzazioni granulari sui propri file: dal caricamento delle immagini del profilo alla lettura di documenti privati.

Poiché i file in Cloud Storage hanno un percorso completo, per fare in modo che un file sia controllato da un utente è sufficiente un'informazione univoca che identifichi l'utente nel percorso del file (ad esempio il uid dell'utente) che può essere controllata al momento della valutazione della regola:

// 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;
}

Gruppo privato

Un altro caso d'uso altrettanto comune è consentire le autorizzazioni di gruppo per un oggetto, ad esempio consentendo a più membri di un team di collaborare a un documento condiviso. Là esistono diversi approcci per farlo:

  • Genera un token personalizzato Firebase Authentication contenente informazioni aggiuntive sul membro del gruppo (ad esempio un ID gruppo)
  • Includi informazioni sul gruppo (ad esempio un ID gruppo o un elenco di uid autorizzati) nella i metadati del file

Una volta archiviati nel token o nei metadati del file, questi dati possono essere utilizzati come riferimento dall'interno di una regola:

// 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;
}

Esempio completo

Sono mostrati alcuni semplici casi dei quattro tipi comuni di restrizioni dell'autenticazione nell'esempio seguente:

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;
      }
    }
  }
}