Conectar dados seguros com autorização e atestado

O Firebase Data Connect oferece segurança robusta do lado do cliente com:

  • Autorização de clientes da Web e de dispositivos móveis
  • Controles de autorização individuais no nível da consulta e da mutação
  • Atestado de app com Firebase App Check.

O Data Connect amplia essa segurança com:

  • Autorização do lado do servidor
  • Projeto do Firebase e segurança do usuário do Cloud SQL com o IAM.

Autorizar consultas e mutações do cliente

O Data Connect está totalmente integrado ao Firebase Authentication. Assim, você pode usar dados avançados sobre os usuários que estão acessando seus dados (autenticação) no design para saber quais dados esses usuários podem acessar (autorização).

O Data Connect fornece uma diretiva @auth para consultas e mutações, que permite definir o nível de autenticação necessário para autorizar a operação. Este guia apresenta a diretiva @auth com exemplos.

Além disso, Data Connect oferece suporte à execução de consultas incorporadas a mutações, para que você possa recuperar outros critérios de autorização armazenados no banco de dados e usá-los em instruções @check para decidir se as mutações de fechamento estão autorizadas. Para este caso de autorização, a diretiva @redact permite controlar se os resultados da consulta são retornados aos clientes no protocolo de transmissão e a consulta incorporada omitida nos SDKs gerados. Encontre a introdução a essas diretivas, com exemplos.

Entender a diretiva @auth

É possível parametrizar a diretiva @auth para seguir um dos vários níveis de acesso predefinidos que abrangem muitos cenários de acesso comuns. Esses níveis variam de PUBLIC, que permite consultas e mutações de todos os clientes sem autenticação de qualquer tipo, a NO_ACCESS, que não permite consultas e mutações fora de ambientes de servidor privilegiados que usam o SDK Admin do Firebase. Cada um desses níveis está correlacionado com os fluxos de autenticação fornecidos por Firebase Authentication.

Nível Definição
PUBLIC A operação pode ser executada por qualquer pessoa, com ou sem autenticação.
PUBLIC A operação pode ser executada por qualquer pessoa, com ou sem autenticação.
USER_ANON Qualquer usuário identificado, incluindo aqueles que fizeram login anonimamente com Firebase Authentication, está autorizado a realizar a consulta ou mutação.
USER Qualquer usuário que tenha feito login com Firebase Authentication está autorizado a realizar a consulta ou mutação, exceto usuários de login anônimos.
USER_EMAIL_VERIFIED Qualquer usuário que fez login com Firebase Authentication e tem um endereço de e-mail verificado está autorizado a realizar a consulta ou mutação.
NO_ACCESS Essa operação não pode ser executada fora do contexto do SDK Admin.

Usando esses níveis de acesso predefinidos como ponto de partida, é possível definir verificações de autorização complexas e robustas na diretiva @auth usando filtros where e expressões da Common Expression Language (CEL) avaliadas no servidor.

Usar a diretiva @auth para implementar cenários de autorização comuns

Os níveis de acesso predefinidos são o ponto de partida para a autorização.

O nível de acesso USER é o nível básico mais útil para começar.

O acesso totalmente seguro será baseado no nível USER, além de filtros e expressões que verificam atributos de usuários, recursos, funções e outras verificações. Os níveis USER_ANON e USER_EMAIL_VERIFIED são variações do caso USER.

A sintaxe de expressão permite avaliar dados usando um objeto auth que representa dados de autenticação transmitidos com operações, dados padrão em tokens de autenticação e dados personalizados em tokens. Para conferir a lista de campos disponíveis no objeto auth, consulte a seção de referência.

Há casos de uso em que PUBLIC é o nível de acesso correto para começar. Novamente, um nível de acesso é sempre um ponto de partida, e outros filtros e expressões são necessários para uma segurança robusta.

Este guia agora oferece exemplos de como criar em USER e PUBLIC.

Um exemplo motivador

Os exemplos de práticas recomendadas a seguir se referem ao esquema abaixo para uma plataforma de blogs com determinados conteúdos bloqueados por um plano de pagamento.

Essa plataforma provavelmente modelaria Users ePosts.

type User @table(key: "uid") {
  uid: String!
  name: String
  birthday: Date
  createdAt: Timestamp! @default(expr: "request.time")
}

type Post @table {
  author: User!
  text: String!
  # "one of 'draft', 'public', or 'pro'"
  visibility: String! @default(value: "draft")
  # "the time at which the post should be considered published. defaults to
  # immediately"
  publishedAt: Timestamp! @default(expr: "request.time")
  createdAt: Timestamp! @default(expr: "request.time")
  updatedAt: Timestamp! @default(expr: "request.time")
}

Recursos pertencentes ao usuário

O Firebase recomenda que você escreva filtros e expressões que testem a propriedade do usuário de um recurso. Nos casos a seguir, a propriedade de Posts.

Nos exemplos abaixo, os dados dos tokens de autenticação são lidos e comparados usando expressões. O padrão típico é usar expressões como where: {authorUid: {eq_expr: "auth.uid"}} para comparar um authorUid armazenado com o auth.uid (ID do usuário) transmitido no token de autenticação.

Criar

Essa prática de autorização começa adicionando o auth.uid do token de autenticação a cada novo Post como um campo authorUid para permitir a comparação em testes de autorização de subseqência.

# Create a new post as the current user
mutation CreatePost($text: String!, $visibility: String) @auth(level: USER) {
  post_insert(data: {
    # set the author's uid to the current user uid
    authorUid_expr: "auth.uid"
    text: $text
    visibility: $visibility
  })
}
Atualizar

Quando um cliente tenta atualizar um Post, é possível testar o auth.uid transmitido com o authorUid armazenado.

# Update one of the current user's posts
mutation UpdatePost($id: UUID!, $text: String, $visibility: String) @auth(level:USER) {
  post_update(
    # only update posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
    data: {
      text: $text
      visibility: $visibility
      # insert the current server time for updatedAt
      updatedAt_expr: "request.time"
    }
  )
}
Excluir

A mesma técnica é usada para autorizar operações de exclusão.

# Delete one of the current user's posts
mutation DeletePost($id: UUID!) @auth(level: USER) {
  post_delete(
    # only delete posts whose author is the current user
    first: { where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}
    }}
  )
}
# Common display information for a post
fragment DisplayPost on Post {
  id, text, createdAt, updatedAt
  author { uid, name }
}
Lista
# List all posts belonging to the current user
query ListMyPosts @auth(level: USER) {
  posts(where: {
    userUid: {eq_expr: "auth.uid"}
  }) {
    # See the fragment above
    ...DisplayPost
    # also show visibility since it is user-controlled
    visibility
  }
}
Get
# Get a post only if it belongs to the current user
query GetMyPost($id: UUID!) @auth(level: USER) {
  post(key: {id: $id},
    first: {where: {
      id: {eq: $id}
      authorUid: {eq_expr: "auth.uid"}}
      }}, {
      # See the fragment above
      ...DisplayPost
      # also show visibility since it is user-controlled
      visibility
  }
}

Filtrar dados

O sistema de autorização do Data Connect permite criar filtros sofisticados combinados com níveis de acesso predefinidos, como PUBLIC, e usando dados de tokens de autenticação.

O sistema de autorização também permite usar apenas expressões, sem um nível de acesso básico, conforme mostrado em alguns dos exemplos a seguir.

Filtrar por atributos de recurso

Aqui, a autorização não é baseada em tokens de autenticação, já que o nível de segurança básico está definido como PUBLIC. No entanto, podemos definir explicitamente os registros no banco de dados como adequados para acesso público. Suponha que tenhamos registros Post no banco de dados com visibility definido como "público".

# List all posts marked as 'public' visibility
query ListPublicPosts @auth(level: PUBLIC) {
  posts(where: {
    # Test that visibility is "public"
    visibility: {eq: "public"}
    # Only display articles that are already published
    publishedAt: {lt_expr: "request.time"}
  }) {
    # see the fragment above
    ...DisplayPost
  }
}
Filtrar por declarações do usuário

Aqui, vamos supor que você tenha configurado declarações de usuário personalizadas que transmitem tokens de autenticação para identificar usuários em um plano "pro" do app, marcado com um campo auth.token.plan no token de autenticação. Suas expressões podem testar esse campo.

# List all public or pro posts, only permitted if user has "pro" plan claim
query ProListPosts @auth(expr: "auth.token.plan == 'pro'") {
  posts(where: {
    # display both public posts and "pro" posts
    visibility: {in: ['public', 'pro']},
    # only display articles that are already published
    publishedAt: {lt_expr: "request.time"},
  }) {
    # see the fragment above
    ...DisplayPost
    # show visibility so pro users can see which posts are pro\
    visibility
  }
}
Filtrar por ordem e limite

Ou, ainda, você pode ter definido visibility nos registros Post para identificar se o conteúdo está disponível para usuários "pro", mas, para uma lista de dados de pré-visualização ou teaser, limite ainda mais o número de registros retornados.

# Show 2 oldest Pro post as a preview
query ProTeaser @auth(level: USER) {
  posts(
    where: {
      # show only pro posts
      visibility: {eq: "pro"}
      # that have already been published more than 30 days ago
      publishedAt: {lt_time: {now: true, sub: {days: 30}}}
    },
    # order by publish time
    orderBy: [{publishedAt: DESC}],
    # only return two posts
    limit: 2
  ) {
    # See the fragment above
    ...DisplayPost
  }
}
Filtrar por função

Se a declaração personalizada definir um papel admin, será possível testar e autorizar operações.

# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
  posts { ...DisplayPost }
}

Entender as diretivas @check e @redact

A diretiva @check verifica se os campos especificados estão presentes nos resultados da consulta. Uma expressão Common Expression Language (CEL) é usada para testar valores de campo. O comportamento padrão da diretiva é verificar e rejeitar nós com valor null.

A diretiva @redact oculta parte da resposta do cliente. Os campos revisados ainda são avaliados quanto a efeitos colaterais (incluindo mudanças de dados e @check), e os resultados ainda estão disponíveis para etapas posteriores nas expressões CEL.

Em Data Connect, as diretivas @check e @redact são mais usadas no contexto de verificações de autorização. Consulte a discussão sobre a pesquisa de dados de autorização.

Adicionar as diretivas @check e @redact para consultar dados de autorização

Um caso de uso comum de autorização envolve armazenar papéis de autorização personalizados no banco de dados, por exemplo, em uma tabela de permissões especial, e usar esses papéis para autorizar mutações a fim de criar, atualizar ou excluir dados.

Usando pesquisas de dados de autorização, é possível consultar papéis com base em um ID do usuário e usar expressões CEL para decidir se a mutação está autorizada. Por exemplo, você pode escrever uma mutação UpdateMovieTitle que permite que um cliente autorizado atualize títulos de filmes.

Para o restante desta discussão, suponha que o banco de dados do app de avaliação de filmes armazene uma função de autorização em uma tabela MoviePermission.

# MoviePermission
# Suppose a user has an authorization role with respect to records in the Movie table
type MoviePermission @table(key: ["doc", "userId"]) {
  movie: Movie! # implies another field: movieId: UUID!
  userId: String! # Can also be a reference to a User table, doesn't matter
  role: String!
}

No exemplo de implementação a seguir, a mutação UpdateMovieTitle inclui um campo query para extrair dados de MoviePermission e as seguintes diretivas para garantir que a operação seja segura e robusta:

  • Uma diretiva @transaction para garantir que todas as consultas e verificações de autorização sejam concluídas ou falhem atomicamente.
  • A diretiva @redact para omitir os resultados da consulta da resposta, o que significa que nossa verificação de autorização é realizada no servidor Data Connect, mas os dados sensíveis não são expostos ao cliente.
  • Um par de diretivas @check para avaliar a lógica de autorização nos resultados da consulta, como testar se um determinado ID de usuário tem um papel adequado para fazer modificações.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    # Step 1a: Use @check to test if the user has any role associated with the movie
    # Here the `this` binding refers the lookup result, i.e. a MoviePermission object or null
    # The `this != null` expression could be omitted since rejecting on null is default behavior
    ) @check(expr: "this != null", message: "You do not have access to this movie") {
      # Step 1b: Check if the user has the editor role for the movie
      # Next we execute another @check; now `this` refers to the contents of the `role` field
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

Antipadrões a evitar na autorização

A seção anterior aborda os padrões a serem seguidos ao usar a diretiva @auth.

Você também precisa conhecer os antipadrões importantes a serem evitados.

Evitar passar IDs de atributos do usuário e parâmetros de token de autenticação em argumentos de consulta e mutação

O Firebase Authentication é uma ferramenta poderosa para apresentar fluxos de autenticação e capturar dados de autenticação com segurança, como IDs de usuários registrados e vários campos armazenados em tokens de autenticação.

Não é uma prática recomendada transmitir IDs de usuário e dados de token de autenticação em argumentos de consulta e mutação.

# Antipattern!
# This incorrectly allows any user to view any other user's posts
query AllMyPosts($userId: String!) @auth(level: USER) {
  posts(where: {authorUid: {eq: $userId}}) {
    id, text, createdAt
  }
}

Evitar o uso do nível de acesso USER sem filtros

Como discutido várias vezes no guia, os níveis de acesso principais, como USER, USER_ANON e USER_EMAIL_VERIFIED, são pontos de partida e de referência para verificações de autorização, que podem ser aprimoradas com filtros e expressões. O uso desses níveis sem um filtro ou expressão correspondente que verifique qual usuário está realizando a solicitação é essencialmente equivalente ao uso do nível PUBLIC.

# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
  documents {
    id
    title
    text
  }
}

Evite usar o nível de acesso PUBLIC ou USER para prototipagem

Para acelerar o desenvolvimento, pode ser tentador definir todas as operações no nível de acesso PUBLIC ou USER sem outras melhorias para autorizar todas as operações e permitir que você teste rapidamente o código.

Depois de criar protótipos iniciais dessa forma, comece a mudar de NO_ACCESS para a autorização pronta para produção com os níveis PUBLIC e USER. No entanto, não implante-os como PUBLIC ou USER sem adicionar outra lógica, conforme mostrado neste guia.

# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
  post: post_delete(
    id: $id,
  )
}

Usar Firebase App Check para atestado de app

A autenticação e a autorização são componentes essenciais da segurança do Data Connect. A autenticação e a autorização combinadas com o atestado do app formam uma solução de segurança muito robusta.

Com o atestado pelo Firebase App Check, os dispositivos que executam seu app usarão um app ou provedor de atestado de dispositivos que atesta que as operações de Data Connect são originadas do app autêntico e as solicitações são originadas de um dispositivo autêntico e não adulterado. Esse atestado é anexado a todas as solicitações que o app faz para Data Connect.

Para saber como ativar o App Check para Data Connect e incluir o SDK do cliente no app, confira a visão geral do App Check.

Níveis de autenticação para a diretiva @auth(level)

A tabela a seguir lista todos os níveis de acesso padrão e os equivalentes do CEL. Os níveis de autenticação são listados de forma ampla a restrita. Cada nível abrange todos os usuários que correspondem aos níveis seguintes.

Nível Definição
PUBLIC A operação pode ser executada por qualquer pessoa, com ou sem autenticação.

Considerações:os dados podem ser lidos ou modificados por qualquer usuário. O Firebase recomenda esse nível de autorização para dados que podem ser acessados publicamente, como listas de produtos ou mídia. Consulte os exemplos e alternativas de práticas recomendadas.

Equivalente a @auth(expr: "true")

Os filtros e as expressões @auth não podem ser usados em combinação com esse nível de acesso. Todas essas expressões vão falhar com um erro 400 de solicitação inválida.
USER_ANON Qualquer usuário identificado, incluindo aqueles que fizeram login anonimamente com Firebase Authentication, está autorizado a realizar a consulta ou mutação.

Observação: USER_ANON é um superconjunto de USER.

Considerações:é necessário projetar cuidadosamente as consultas e mutações para esse nível de autorização. Esse nível permite que o usuário faça login anônimo (login automático vinculado apenas a um dispositivo do usuário) com Authentication e não realiza outras verificações, por exemplo, se os dados pertencem ao usuário. Confira os exemplos e alternativas de práticas recomendadas.

Como os fluxos de login anônimo Authentication emitem um uid, o nível USER_ANON é equivalente a
@auth(expr: "auth.uid != nil")
USER Qualquer usuário que tenha feito login com Firebase Authentication está autorizado a realizar a consulta ou mutação, exceto usuários de login anônimos.

Considerações:é necessário projetar cuidadosamente as consultas e mutações para esse nível de autorização. Esse nível apenas verifica se o usuário fez login com Authentication e não realiza outras verificações, como, por exemplo, se os dados pertencem ao usuário. Confira os exemplos e alternativas de práticas recomendadas.

Equivalente a @auth(expr: "auth.uid != nil && auth.token.firebase.sign_in_provider != 'anonymous'")"
USER_EMAIL_VERIFIED Qualquer usuário que tenha feito login com Firebase Authentication com um endereço de e-mail verificado está autorizado a realizar a consulta ou mutação.

Considerações:como a verificação de e-mail é realizada usando Authentication, ela é baseada em um método Authentication mais robusto. Portanto, esse nível oferece mais segurança em comparação com USER ou USER_ANON. Esse nível verifica apenas se o usuário fez login com Authentication e tem um e-mail verificado. Ele não realiza outras verificações, como, por exemplo, se os dados pertencem ao usuário. Consulte os exemplos e alternativas de práticas recomendadas.

Equivalente a @auth(expr: "auth.uid != nil && auth.token.email_verified")"
NO_ACCESS Essa operação não pode ser executada fora do contexto do SDK Admin.

Equivalente a @auth(expr: "false")

Referência da CEL para @auth(expr) e @check(expr)

Como mostrado em exemplos em outras partes deste guia, é possível e recomendável usar expressões definidas na Common Expression Language (CEL) para controlar a autorização de Data Connect usando as diretivas @auth(expr:) e @check.

Esta seção aborda a sintaxe do CEL relevante para a criação de expressões para essas diretivas.

As informações completas de referência da CEL estão disponíveis na especificação da CEL.

Testar variáveis transmitidas em consultas e mutações

A sintaxe @auth(expr) permite acessar e testar variáveis de consultas e mutações.

Por exemplo, é possível incluir uma variável de operação, como $status, usando vars.status.

mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")

Dados disponíveis para expressões

As expressões CEL @auth(expr:) e @check(expr:) podem avaliar o seguinte:

  • request.operationName
  • vars (alias para request.variables)
  • auth (alias para request.auth)

Além disso, as expressões @check(expr:) podem avaliar:

  • this (o valor do campo atual)

O objeto request.operationName

O objeto request.operarationName armazena o tipo de operação, consulta ou mutação.

O objeto vars

O objeto vars permite que as expressões acessem todas as variáveis transmitidas na consulta ou mutação.

É possível usar vars.<variablename> em uma expressão como um alias para o request.variables.<variablename> totalmente qualificado:

# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")

O objeto auth

Authentication identifica os usuários que solicitam acesso aos seus dados e fornece essas informações como um objeto que pode ser usado nas suas expressões.

Nos filtros e expressões, é possível usar auth como um alias para request.auth.

O objeto de autenticação contém as seguintes informações:

  • uid: um ID de usuário exclusivo, atribuído ao usuário solicitante.
  • token: um mapa de valores coletados por Authentication.

Para mais detalhes sobre o conteúdo de auth.token, consulte Dados em tokens de autenticação.

A vinculação this

A vinculação this é avaliada como o campo ao qual a diretiva @check está anexada. Em um caso básico, você pode avaliar resultados de consulta de valor único.

mutation UpdateMovieTitle($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query @redact {
    moviePermission( # Look up a join table called MoviePermission with a compound key.
      key: {movieId: $movieId, userId_expr: "auth.uid"}
    ) {
      # Check if the user has the editor role for the movie. `this` is the string value of `role`.
      # If the parent moviePermission is null, the @check will also fail automatically.
      role @check(expr: "this == 'editor'", message: "You must be an editor of this movie to update title")
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

Se o campo retornado ocorrer várias vezes porque algum ancestral é uma lista, cada ocorrência será testada com this vinculado a cada valor.

Para qualquer caminho, se um ancestral for null ou [], o campo não será alcançado e a avaliação do CEL será ignorada para esse caminho. Em outras palavras, a avaliação só acontece quando this é null ou não é null, mas nunca undefined.

Quando o campo é uma lista ou um objeto, this segue a mesma estrutura (incluindo todos os descendentes selecionados no caso de objetos), conforme ilustrado no exemplo a seguir.

mutation UpdateMovieTitle2($movieId: UUID!, $newTitle: String!) @auth(level: USER) @transaction {
  # Step 1: Query and check
  query {
    moviePermissions( # Now we query for a list of all matching MoviePermissions.
      where: {movieId: {eq: $movieId}, userId: {eq_expr: "auth.uid"}}
    # This time we execute the @check on the list, so `this` is the list of objects.
    # We can use the `.exists` macro to check if there is at least one matching entry.
    ) @check(expr: "this.exists(p, p.role == 'editor')", message: "You must be an editor of this movie to update title") {
      role
    }
  }
  # Step 2: Act
  movie_update(id: $movieId, data: {
    title: $newTitle
  })
}

Sintaxe de expressão complexa

É possível escrever expressões mais complexas combinando com os operadores && e ||.

mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")

A seção a seguir descreve todos os operadores disponíveis.

Operadores e precedência do operador

Use a tabela a seguir como referência para os operadores e a precedência correspondente.

Expressões arbitrárias fornecidas a e b, um campo f e um índice i.

Operador Descrição Associatividade
a[i] a() a.f Índice, chamada, acesso ao campo da esquerda para a direita
!a -a Negação unária da direita para a esquerda
a/b a%b a*b Operadores multiplicativos da esquerda para a direita
a+b a-b Operadores aditivos da esquerda para a direita
a>b a>=b a<b a<=b Operadores relacionais da esquerda para a direita
a in b Existência na lista ou no mapa da esquerda para a direita
type(a) == t Comparação de tipos, em que t pode ser bool, int, float, number, string, list, map, timestamp ou duration da esquerda para a direita
a==b a!=b Operadores de comparação da esquerda para a direita
a && b Condicional E da esquerda para a direita
a || b Condicional OU da esquerda para a direita
a ? true_value : false_value Expressão ternária da esquerda para a direita

Dados em tokens de autenticação

O objeto auth.token pode conter os seguintes valores:

Campo Descrição
email O endereço de e-mail associado à conta, se essa informação existir.
email_verified true se o usuário tiver verificado que tem acesso ao endereço email. Alguns provedores verificam automaticamente esses endereços de e-mail.
phone_number O número de telefone associado à conta, se essa informação existir.
name O nome de exibição do usuário, se ele tiver sido definido.
sub O UID do Firebase do usuário. Ele é exclusivo dentro de um projeto.
firebase.identities O dicionário de todas as identidades associadas à conta desse usuário. As chaves do dicionário podem ser qualquer uma das seguintes: email, phone, google.com, facebook.com, github.com, twitter.com. Os valores do dicionário são matrizes de identificadores exclusivos de cada provedor de identidade associado à conta. Por exemplo, auth.token.firebase.identities["google.com"][0] contém o primeiro ID de usuário do Google associado à conta.
firebase.sign_in_provider O provedor de entrada usado para receber esse token. Pode ser uma das seguintes strings: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com.
firebase.tenant O ID do locatário associado à conta, se houver. Por exemplo, tenant2-m6tyz.

Outros campos em tokens de ID JWT

Também é possível acessar os seguintes campos auth.token:

Declarações de tokens personalizados
alg Algoritmo "RS256"
iss Emissor Endereço de e-mail da conta de serviço do seu projeto
sub Assunto Endereço de e-mail da conta de serviço do seu projeto
aud Público "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
iat Hora de emissão A hora atual, em segundos, desde a época do UNIX
exp Tempo de expiração O tempo, em segundos, desde a época do UNIX, em que o token expira. Pode ser no máximo 3.600 segundos depois de iat.
Observação: ele controla o tempo apenas quando o token personalizado expira. No entanto, quando você faz o login de um usuário utilizando signInWithCustomToken(), ele permanece conectado ao dispositivo até que a sessão seja invalidada ou que o usuário se desconecte.
<claims> (opcional) Declarações personalizadas opcionais a serem incluídas no token, que podem ser acessadas por auth.token (ou request.auth.token) nas expressões. Por exemplo, se você criar uma reivindicação personalizada adminClaim, poderá acessá-la com auth.token.adminClaim.

A seguir