As regras de segurança do Firebase permitem controlar o acesso aos dados armazenados. Com a sintaxe de regras flexíveis, é possível criar regras que correspondam a qualquer tipo de operação, desde todas as gravações no banco de dados inteiro até operações em um documento específico.
Veja neste guia alguns dos casos de uso mais básicos a serem implementados quando você for configurar seu aplicativo e proteger seus dados. No entanto, antes de começar a criar as regras, é recomendável saber mais sobre a linguagem em que são escritas e o comportamento delas.
Para acessar e atualizar suas regras, siga as etapas descritas em Gerenciar e implantar regras de segurança do Firebase.
Regras padrão: modo bloqueado
Ao criar um banco de dados ou uma instância de armazenamento no Console do Firebase, é possível escolher se as regras de segurança do produto restringirão o acesso aos dados (modo bloqueado) ou permitirão o acesso de qualquer pessoa (modo de teste). No Cloud Firestore e no Realtime Database, as regras padrão do modo bloqueado negam acesso a todos os usuários. No Cloud Storage, somente usuários autenticados podem acessar os buckets de armazenamento.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if false;
}
}
}
Realtime Database
{
"rules": {
".read": false,
".write": false
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Regras do ambiente de desenvolvimento
Enquanto você estiver trabalhando no seu aplicativo, é recomendável ter acesso relativamente aberto ou irrestrito aos dados. Não se esqueça de atualizar as regras antes de implantar o app em produção. Lembre-se também de que, se você o implantar, ele ficará acessível ao público, mesmo que você ainda não tenha feito o lançamento.
Note que o Firebase permite que os clientes tenham acesso direto aos seus dados, e as regras de segurança do Firebase são a única proteção contra usuários mal-intencionados. A definição de regras independentes da lógica do produto tem várias vantagens: os clientes não são responsáveis por aplicar as medidas de segurança, as implementações com bugs não comprometem seus dados e, o mais importante, você não fica dependente de um servidor intermediário para proteger seus dados do mundo.
Todos os usuários autenticados
Apesar de não ser recomendável deixar seus dados acessíveis para qualquer usuário que fez login, pode ser útil definir o acesso a qualquer usuário autenticado enquanto você desenvolve o aplicativo.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Realtime Database
{
"rules": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Regras prontas para produção
Na etapa de preparação para implantar o app, verifique se os dados estão protegidos e se o acesso foi devidamente concedido aos usuários. Use o Authentication para configurar o acesso com base em usuários e faça leituras diretamente no seu banco de dados para configurar o acesso com base em dados.
Crie as regras conforme você estrutura os dados, já que essa configuração afeta o modo de restringir o acesso a eles em diferentes caminhos.
Acesso somente ao proprietário do conteúdo
Essas regras restringem o acesso somente ao proprietário autenticado do conteúdo. Apenas um usuário pode ler e gravar dados, e o caminho dos dados contém o código do usuário.
Quando essa regra funciona: quando os dados são isolados por usuário e quando o único usuário que precisa acessar os dados é o mesmo que os criou.
Quando essa regra não funciona: quando vários usuários precisam gravar ou ler os mesmos dados. Como resultado, os usuários substituem os dados ou não conseguem acessar as informações criadas por eles.
Para configurar essa regra: crie uma regra que confirme que o usuário que está solicitando acesso para ler ou gravar dados é o proprietário deles.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{userId}/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == userId
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Allow only authenticated content owners access to their data
".read": "auth !== null && auth.uid === $uid",
".write": "auth !== null && auth.uid === $uid"
}
}
}
}
Cloud Storage
// Grants a user access to a node matching their user ID
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
Acesso público e privado misto
Essa regra permite que qualquer pessoa leia um conjunto de dados, mas restringe apenas ao proprietário autenticado do conteúdo a capacidade de criar ou modificar dados em um determinado caminho.
Quando essa regra funciona: para apps em que os elementos precisam estar legíveis publicamente, mas que tenham acesso de edição restrito aos proprietários desses elementos. Por exemplo, um blog ou app de chat.
Quando essa regra não funciona: assim como a regra de acesso somente ao proprietário do conteúdo, essa regra não funciona quando vários usuários precisam editar os mesmos dados. Os usuários acabam substituindo os dados uns dos outros.
Para configurar essa regra: crie uma regra que permita o acesso de leitura para todos os usuários (ou para todos que estejam autenticados) e que confirme se o usuário que está gravando dados é o proprietário deles.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// Allow public read access, but only content owners can write
match /some_collection/{document} {
allow read: if true
allow create: if request.auth.uid == request.resource.data.author_uid;
allow update, delete: if request.auth.uid == resource.data.author_uid;
}
}
}
Realtime Database
{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data
"rules": {
"some_path": {
"$uid": {
".read": true,
// or ".read": "auth.uid !== null" for only authenticated users
".write": "auth.uid === $uid"
}
}
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "user/<UID>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read;
allow write: if request.auth.uid == userId;
}
}
}
Acesso com base em atributos e papéis
Para que essa regra funcione, você precisa definir e designar atributos aos usuários nos seus dados. As regras de segurança do Firebase verificam a solicitação em relação aos dados do banco de dados ou aos metadados do arquivo para confirmar ou negar o acesso.
Quando essa regra funciona: se você atribuir um papel aos usuários, essa regra facilitará a limitação do acesso com base em papéis ou em grupos específicos de usuários. Por exemplo, ao armazenar notas, é possível atribuir diferentes níveis de acesso ao grupo de alunos (somente de leitura do conteúdo), ao grupo de professores (de leitura e gravação) e ao grupo de diretores (leitura de todo o conteúdo).
Quando essa regra não funciona: no Realtime Database e no Cloud Storage, suas regras não podem aproveitar o método get()
que as regras do Cloud Firestore podem incorporar.
Dessa forma, você precisa estruturar o banco de dados ou os metadados de arquivo de modo a representar os atributos que estão sendo usados nas regras.
Para configurar essa regra: no Cloud Firestore, inclua um campo nos documentos dos usuários em que você tenha acesso de leitura. Em seguida, estruture a regra para ler esse campo e conceder acesso de modo condicional. No Realtime Database, crie um caminho de dados que defina os usuários do app e conceda a eles um papel em um nó filho.
Também é possível configurar declarações personalizadas no Authentication
e recuperar essas informações da variável
auth.token
em qualquer regra de segurança do Firebase.
Atributos e papéis definidos por dados
Essas regras funcionam apenas no Cloud Firestore e no Realtime Database.
Cloud Firestore
Lembre-se de que, sempre que suas regras incluírem uma leitura, como as descritas abaixo, você receberá a cobrança de uma operação de leitura no Cloud Firestore.
service cloud.firestore {
match /databases/{database}/documents {
// For attribute-based access control, Check a boolean `admin` attribute
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
allow read: true;
// Alterntatively, for role-based access, assign specific roles to users
match /some_collection/{document} {
allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"${subpath}": {
//
".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
".read": true
}
}
}
}
Atributos e papéis de declaração personalizada
Para implementar essas regras, configure as declarações personalizadas no Firebase Authentication e utilize-as nas regras.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// For attribute-based access control, check for an admin claim
allow write: if request.auth.token.admin == true;
allow read: true;
// Alterntatively, for role-based access, assign specific roles to users
match /some_collection/{document} {
allow read: if request.auth.token.reader == "true";
allow write: if request.auth.token.writer == "true";
}
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Create a custom claim for each role or group
// you want to leverage
".write": "auth.uid !== null && auth.token.writer === true",
".read": "auth.uid !== null && auth.token.reader === true"
}
}
}
}
Cloud Storage
service firebase.storage {
// 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;
}
}
Atributos de locação
Para implementar essas regras, configure a multilocação no Google Cloud Identity Platform (GCIP)
e aproveite o locatário nas suas regras. Os exemplos a seguir permitem gravações
de um usuário em um locatário específico, por exemplo, tenant2-m6tyz
.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// For tenant-based access control, check for a tenantID
allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
allow read: true;
}
}
Realtime Database
{
"rules": {
"some_path": {
"$uid": {
// Only allow reads and writes if user belongs to a specific tenant
".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
".read": "auth.uid !== null
}
}
}
}
Cloud Storage
service firebase.storage {
// Only allow reads and writes if user belongs to a specific tenant
match /files/{tenantId}/{fileName} {
allow read: if request.auth != null;
allow write: if request.auth.token.firebase.tenant == tenantId;
}
}