As Firebase Security Rules para Cloud Storage integram-se ao Firebase Authentication para fornecer autenticação avançada com base no usuário para o Cloud Storage. Isso permite o controle de acesso granular com base nas declarações de um token do Firebase Authentication.
Autenticação do usuário
Quando um usuário autenticado faz uma solicitação no Cloud Storage, a variável request.auth
é preenchida com o uid
do usuário (request.auth.uid
), bem como as declarações do JWT Firebase Authentication (request.auth.token
).
Além disso, ao usar a autenticação personalizada, outras declarações são exibidas no campo request.auth.token
.
Quando um usuário não autenticado realiza uma solicitação, a variável request.auth
é null
.
Com esses dados, há várias maneiras comuns de usar a autenticação para proteger os arquivos:
- Público: ignora
request.auth
- Particular autenticado: verifica se
request.auth
não énull
- Particular por usuário: verifica se
request.auth.uid
é igual a um caminhouid
- Particular por grupo: verifica as declarações do token personalizado para confirmar se elas correspondem a uma declaração escolhida ou lê os metadados do arquivo para ver se existe um campo de metadados
Público
Qualquer regra que não considere o contexto request.auth
pode ser considerada uma regra public
, pois não considera o contexto de autenticação do usuário.
Essas regras podem ser úteis para expor dados públicos, como recursos de um jogo, arquivos de som ou outros conteúdos estáticos.
// 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"); }
Particular autenticado
Em determinados casos, os dados devem ser visíveis somente para os usuários autenticados do seu aplicativo. Como a variável request.auth
é null
para todos os usuários não autenticados, basta verificar se a variável request.auth
existe para exigir autenticação:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Particular por usuário
De longe, o caso de uso mais comum para request.auth
será conceder permissões granulares aos arquivos para cada usuário, desde o upload de imagens de perfil até a leitura de documentos particulares.
Como os arquivos do Cloud Storage têm um caminho completo até o arquivo, para permitir que um usuário controle um arquivo, basta uma informação exclusiva que identifique o usuário no caminho (como o uid
do usuário). Essa informação pode ser verificada quando a regra é avaliada:
// 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; }
Particular por grupo
Outro caso de uso igualmente comum é conceder permissões de acesso a um objeto para um grupo. Por exemplo, permitir que vários membros da equipe colaborem em um documento compartilhado. Há várias abordagens para fazer isso, como:
- produzir um token personalizado do Firebase Authentication que contenha informações adicionais sobre um membro do grupo (por exemplo, um ID do grupo);
- incluir informações do grupo (como um ID do grupo ou uma lista de
uid
s autorizados) nos metadados do arquivo.
Depois que esses dados são armazenados no token ou nos metadados do arquivo, eles podem ser referenciados dentro de uma regra:
// 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; }
Exemplo completo
Veja no exemplo abaixo casos simples dos quatro tipos comuns de restrições de autenticação:
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; } } } }