Firebase Data Connect bietet eine robuste clientseitige Sicherheit mit:
- Autorisierung von Mobil- und Webclients
- Autorisierungssteuerung auf Ebene einzelner Abfragen und Mutationen
- App-Attestierung mit Firebase App Check
Data Connect erweitert diese Sicherheit durch:
- Serverseitige Autorisierung
- Sicherheit von Firebase-Projekten und Cloud SQL-Nutzern mit IAM
Clientabfragen und ‑mutationen autorisieren
Data Connect ist vollständig in Firebase Authentication integriert. Sie können also umfangreiche Daten zu Nutzern, die auf Ihre Daten zugreifen (Authentifizierung), in Ihrem Design verwenden, um festzulegen, auf welche Daten diese Nutzer zugreifen können (Autorisierung).
Data Connect bietet eine @auth
-Richtlinie für Abfragen und Mutationen, mit der Sie die Authentifizierungsebene festlegen können, die für die Autorisierung des Vorgangs erforderlich ist. In diesem Leitfaden wird die @auth
-Anweisung mit Beispielen vorgestellt.
Außerdem unterstützt Data Connect die Ausführung von Abfragen, die in Mutationen eingebettet sind. So können Sie zusätzliche Autorisierungskriterien abrufen, die Sie in Ihrer Datenbank gespeichert haben, und diese Kriterien in @check
-Richtlinien verwenden, um zu entscheiden, ob die umschließenden Mutationen autorisiert sind. Bei dieser Autorisierungsart können Sie mit der @redact
-Richtlinie festlegen, ob Abfrageergebnisse an Clients im Wire-Protokoll zurückgegeben und die eingebettete Abfrage in generierten SDKs ausgelassen werden. Einführung in diese Richtlinien mit Beispielen
@auth
-Richtlinie
Sie können die @auth
-Richtlinie so parametrisieren, dass sie einer der vordefinierten Zugriffsebenen folgt, die viele gängige Zugriffsszenarien abdecken. Diese Ebenen reichen von PUBLIC
(Zugriff auf Abfragen und Mutationen von allen Clients ohne Authentifizierung) bis NO_ACCESS
(Zugriff auf Abfragen und Mutationen nur in privilegierten Serverumgebungen mit dem Firebase Admin SDK). Jede dieser Ebenen ist mit Authentifizierungsabläufen von Firebase Authentication verknüpft.
Level | Definition |
---|---|
PUBLIC |
Der Vorgang kann von allen mit oder ohne Authentifizierung ausgeführt werden. |
PUBLIC |
Der Vorgang kann von allen mit oder ohne Authentifizierung ausgeführt werden. |
USER_ANON |
Jeder identifizierte Nutzer, einschließlich derer, die sich mit Firebase Authentication anonym angemeldet haben, ist berechtigt, die Abfrage oder Mutation auszuführen. |
USER |
Jeder Nutzer, der sich mit Firebase Authentication angemeldet hat, ist berechtigt, die Abfrage oder Mutation auszuführen, mit Ausnahme von Nutzern mit anonymer Anmeldung. |
USER_EMAIL_VERIFIED |
Jeder Nutzer, der sich mit Firebase Authentication und einer bestätigten E-Mail-Adresse angemeldet hat, ist berechtigt, die Abfrage oder Mutation auszuführen. |
NO_ACCESS |
Dieser Vorgang kann nicht außerhalb eines Admin SDK-Kontexts ausgeführt werden. |
Anhand dieser vordefinierten Zugriffsebenen können Sie komplexe und robuste Autorisierungsüberprüfungen in der @auth
-Richtlinie mit where
-Filtern und CEL-Ausdrücken (Common Expression Language) definieren, die auf dem Server ausgewertet werden.
@auth
-Anweisung zum Implementieren gängiger Autorisierungsszenarien verwenden
Die voreingestellten Zugriffsebenen sind der Ausgangspunkt für die Autorisierung.
Die Zugriffsebene USER
ist die am häufigsten verwendete grundlegende Ebene.
Der vollständig sichere Zugriff basiert auf der USER
-Ebene sowie auf Filtern und Ausdrücken, die Nutzerattribute, Ressourcenattribute, Rollen und andere Prüfungen prüfen. Die Ebenen USER_ANON
und USER_EMAIL_VERIFIED
sind Variationen des USER
-Falls.
Mit der Ausdruckssyntax können Sie Daten mit einem auth
-Objekt auswerten, das Authentifizierungsdaten darstellt, die mit Vorgängen übergeben werden. Dazu gehören sowohl Standarddaten in Authentifizierungstokens als auch benutzerdefinierte Daten in Tokens. Eine Liste der im auth
-Objekt verfügbaren Felder finden Sie im Referenzabschnitt.
Es gibt natürlich Anwendungsfälle, in denen PUBLIC
die richtige Zugriffsebene ist. Auch hier ist eine Zugriffsebene immer ein Ausgangspunkt. Für eine robuste Sicherheit sind zusätzliche Filter und Ausdrücke erforderlich.
In diesem Leitfaden finden Sie nun Beispiele dafür, wie Sie auf USER
und PUBLIC
aufbauen können.
Ein motivierendes Beispiel
Die folgenden Best Practices beziehen sich auf das folgende Schema für eine Blogging-Plattform, bei der bestimmte Inhalte nur mit einem kostenpflichtigen Abo zugänglich sind.
Eine solche Plattform würde wahrscheinlich Users
und Posts
modellieren.
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")
}
Dem Nutzer gehörende Ressourcen
Firebase empfiehlt, Filter und Ausdrücke zu schreiben, die die Inhaberschaft von Nutzern an einer Ressource prüfen, in den folgenden Fällen die Inhaberschaft an Posts
.
In den folgenden Beispielen werden Daten aus Authentifizierungstokens mithilfe von Ausdrücken gelesen und verglichen. Normalerweise werden Ausdrücke wie where: {authorUid:
{eq_expr: "auth.uid"}}
verwendet, um eine gespeicherte authorUid
mit der auth.uid
(User-ID) zu vergleichen, die im Authentifizierungstoken übergeben wird.
Erstellen
Bei dieser Autorisierungsmethode wird der auth.uid
aus dem Authentifizierungstoken jedem neuen Post
als authorUid
-Feld hinzugefügt, um einen Vergleich in nachfolgenden Autorisierungstests zu ermöglichen.
# 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
})
}
Aktualisieren
Wenn ein Client versucht, eine Post
zu aktualisieren, kannst du die übergebene auth.uid
mit der gespeicherten authorUid
vergleichen.
# 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"
}
)
}
Löschen
Dasselbe Verfahren wird verwendet, um Löschvorgänge zu autorisieren.
# 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 }
}
Liste
# 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
}
}
Daten filtern
Mit dem Autorisierungssystem von Data Connect können Sie komplexe Filter in Kombination mit vordefinierten Zugriffsebenen wie PUBLIC
erstellen und Daten aus Authentifizierungstokens verwenden.
Mit dem Autorisierungssystem können Sie auch nur Ausdrücke ohne Basiszugriffsebene verwenden, wie in einigen der folgenden Beispiele gezeigt.
Nach Ressourcenattributen filtern
Hier basiert die Autorisierung nicht auf Authentifizierungstokens, da die Basissicherheitsebene auf PUBLIC
festgelegt ist. Wir können jedoch Datensätze in unserer Datenbank explizit für den öffentlichen Zugriff freigeben. Angenommen, wir haben Post
Datensätze in unserer Datenbank, für die visibility
auf „öffentlich“ festgelegt ist.
# 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
}
}
Nach Nutzeransprüchen filtern
Angenommen, Sie haben benutzerdefinierte Nutzeransprüche eingerichtet, die Authentifizierungstokens übergeben, um Nutzer mit einem Pro-Abo für Ihre App zu identifizieren, die im Authentifizierungstoken mit einem auth.token.plan
-Feld gekennzeichnet sind. Ihre Ausdrücke können anhand dieses Felds getestet werden.
# 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
}
}
Nach Auftrag + Limit filtern
Möglicherweise haben Sie auch visibility
in Post
-Einträgen festgelegt, um anzugeben, dass es sich um Inhalte handelt, die nur für „Pro“-Nutzer verfügbar sind. Für eine Vorschau oder einen Teaser-Eintrag von Daten können Sie die Anzahl der zurückgegebenen Einträge weiter einschränken.
# 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
}
}
Nach Rolle filtern
Wenn Ihre benutzerdefinierte Anspruchsklasse eine admin
-Rolle definiert, können Sie Vorgänge entsprechend testen und autorisieren.
# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
posts { ...DisplayPost }
}
@check
- und @redact
-Richtlinien
Mit der Anweisung @check
wird geprüft, ob die angegebenen Felder in den Abfrageergebnissen vorhanden sind. Feldwerte werden mit einem CEL-Ausdruck (Common Expression Language) getestet. Standardmäßig werden mit der Anweisung Knoten mit dem Wert null
geprüft und abgelehnt.
Mit der @redact
-Richtlinie wird ein Teil der Antwort des Clients entfernt. Ausgeblendete Felder werden weiterhin auf Nebenwirkungen (einschließlich Datenänderungen und @check
) geprüft und die Ergebnisse sind für nachfolgende Schritte in CEL-Ausdrücken weiterhin verfügbar.
In Data Connect werden die Direktiven @check
und @redact
am häufigsten im Zusammenhang mit Autorisierungsüberprüfungen verwendet. Weitere Informationen finden Sie unter Suche nach Autorisierungsdaten.
@check
- und @redact
-Richtlinien hinzufügen, um Autorisierungsdaten abzurufen
Ein gängiger Anwendungsfall für die Autorisierung besteht darin, benutzerdefinierte Autorisierungsrollen in Ihrer Datenbank zu speichern, z. B. in einer speziellen Berechtigungstabelle, und diese Rollen zu verwenden, um Mutationen zum Erstellen, Aktualisieren oder Löschen von Daten zu autorisieren.
Mithilfe von Autorisierungsdatenabfragen können Sie anhand einer Nutzer-ID nach Rollen suchen und mit CEL-Ausdrücken entscheiden, ob die Mutation autorisiert ist. Beispiel: Sie möchten eine UpdateMovieTitle
-Mutation schreiben, mit der ein autorisierter Kunde Filmtitel aktualisieren kann.
Angenommen, in der Datenbank der Filmkritik-App wird eine Autorisierungsrolle in einer Tabelle MoviePermission
gespeichert.
# 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!
}
In der folgenden Beispielimplementierung enthält die UpdateMovieTitle
-Mutation ein query
-Feld, um Daten aus MoviePermission
abzurufen, sowie die folgenden Anweisungen, um für eine sichere und robuste Ausführung zu sorgen:
- Eine
@transaction
-Richtlinie, die dafür sorgt, dass alle Autorisierungsanfragen und ‑prüfungen atomar abgeschlossen oder fehlschlagen. - Die
@redact
-Richtlinie zum Auslassen von Abfrageergebnissen aus der Antwort. Das bedeutet, dass unsere Autorisierungsüberprüfung auf dem Data Connect-Server ausgeführt wird, aber vertrauliche Daten nicht für den Client freigegeben werden. Zwei
@check
-Direktiven zur Auswertung der Autorisierungslogik für Abfrageergebnisse, z. B. zum Testen, ob eine bestimmte Nutzer-ID eine geeignete Rolle für Änderungen hat.
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
})
}
Antimuster bei der Autorisierung, die Sie vermeiden sollten
Im vorherigen Abschnitt wurden Muster beschrieben, die bei der Verwendung der @auth
-Richtlinie beachtet werden sollten.
Außerdem sollten Sie wichtige Antimuster kennen, die Sie vermeiden sollten.
IDs von Nutzerattributen und Authentifizierungstoken-Parameter nicht in Abfrage- und Mutationsargumente übergeben
Firebase Authentication ist ein leistungsstarkes Tool zum Präsentieren von Authentifizierungsabläufen und zum sicheren Erfassen von Authentifizierungsdaten wie registrierten Nutzer-IDs und zahlreichen Feldern, die in Authentifizierungstokens gespeichert sind.
Es wird nicht empfohlen, Nutzer-IDs und Authentifizierungstokendaten in Abfrage- und Mutationsargumente zu übergeben.
# 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
}
}
Verwenden Sie die Zugriffsebene USER
nicht ohne Filter.
Wie bereits mehrfach in diesem Leitfaden erwähnt, sind die Hauptzugriffsebenen wie USER
, USER_ANON
und USER_EMAIL_VERIFIED
Ausgangspunkte für Autorisierungsüberprüfungen, die mit Filtern und Ausdrücken erweitert werden können. Die Verwendung dieser Ebenen ohne entsprechenden Filter oder Ausdruck, der prüft, welcher Nutzer die Anfrage ausführt, entspricht im Wesentlichen der Verwendung der Ebene PUBLIC
.
# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
documents {
id
title
text
}
}
Verwenden Sie für das Prototyping nicht die Zugriffsebene PUBLIC
oder USER
.
Um die Entwicklung zu beschleunigen, kann es verlockend sein, alle Vorgänge auf die Zugriffsebene PUBLIC
oder USER
festzulegen, ohne weitere Verbesserungen vorzunehmen, um alle Vorgänge zu autorisieren und den Code schnell zu testen.
Nachdem Sie auf diese Weise die ersten Prototypen erstellt haben, sollten Sie von NO_ACCESS
zu einer produktionsbereiten Autorisierung mit den Ebenen PUBLIC
und USER
wechseln.
Sie sollten sie jedoch nicht als PUBLIC
oder USER
bereitstellen, ohne wie in diesem Leitfaden beschrieben zusätzliche Logik hinzuzufügen.
# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
post: post_delete(
id: $id,
)
}
Firebase App Check für die App-Attestierung verwenden
Authentifizierung und Autorisierung sind wichtige Komponenten derData Connect Sicherheit. Authentifizierung und Autorisierung in Kombination mit App-Attestierung sorgen für eine sehr robuste Sicherheitslösung.
Bei der Attestierung über Firebase App Check verwenden Geräte, auf denen Ihre App ausgeführt wird, einen App- oder Geräteattestierungsanbieter, der bestätigt, dass Data Connect-Vorgänge von Ihrer authentischen App stammen und Anfragen von einem authentischen, nicht manipulierten Gerät stammen. Diese Attestierung ist jeder Anfrage Ihrer App an Data Connect angehängt.
Weitere Informationen zum Aktivieren von App Check für Data Connect und zum Einbinden des Client-SDKs in Ihre App finden Sie in der App Check-Übersicht.
Authentifizierungsebenen für die @auth(level)
-Richtlinie
In der folgenden Tabelle sind alle Standardzugriffsebenen und ihre CEL-Entsprechungen aufgeführt. Die Authentifizierungsebenen sind von allgemein nach spezifisch aufgelistet. Jede Ebene umfasst alle Nutzer, die den folgenden Ebenen entsprechen.
Level | Definition |
---|---|
PUBLIC |
Der Vorgang kann von allen mit oder ohne Authentifizierung ausgeführt werden.
Hinweise:Daten können von allen Nutzern gelesen oder geändert werden. Firebase empfiehlt diese Autorisierungsebene für öffentlich zugängliche Daten wie Produkt- oder Medieneinträge. Best Practices und Alternativen Entspricht @auth(expr: "true")
@auth -Filter und ‑Ausdrücke können mit dieser Zugriffsebene nicht verwendet werden. Solche Ausdrücke schlagen mit dem Fehler 400 Bad Request fehl.
|
USER_ANON |
Jeder identifizierte Nutzer, einschließlich derer, die sich anonym mit Firebase Authentication angemeldet haben, ist berechtigt, die Abfrage oder Mutation auszuführen.
Hinweis: USER_ANON ist ein Oberbegriff für USER .
Hinweise:Ihre Abfragen und Mutationen müssen für diese Autorisierungsebene sorgfältig konzipiert werden. Auf dieser Ebene können Nutzer anonym (automatische Anmeldung, die nur mit einem Nutzergerät verknüpft ist) mit Authentication angemeldet werden. Es werden keine anderen Prüfungen durchgeführt, z. B. ob die Daten dem Nutzer gehören. Best Practices und Alternativen Da bei anonymen Anmeldeflüssen von Authentication eine uid ausgegeben wird, entspricht die USER_ANON -Ebene @auth(expr: "auth.uid != nil") .
|
USER |
Jeder Nutzer, der sich mit Firebase Authentication angemeldet hat, ist berechtigt, die Abfrage oder Mutation auszuführen, mit Ausnahme von Nutzern mit anonymer Anmeldung.
Hinweise:Ihre Abfragen und Mutationen müssen für diese Autorisierungsebene sorgfältig konzipiert werden. Auf dieser Ebene wird nur geprüft, ob der Nutzer mit Authentication angemeldet ist. Es werden keine anderen Prüfungen durchgeführt, z. B. ob die Daten dem Nutzer gehören. Best Practices und Alternativen Entspricht @auth(expr: "auth.uid != nil &&
auth.token.firebase.sign_in_provider != 'anonymous'")"
|
USER_EMAIL_VERIFIED |
Jeder Nutzer, der sich mit Firebase Authentication und einer bestätigten E-Mail-Adresse angemeldet hat, ist berechtigt, die Abfrage oder Mutation auszuführen.
Hinweise:Da die E-Mail-Bestätigung mit Authentication durchgeführt wird, basiert sie auf einer robusteren Authentication-Methode. Daher bietet dieses Sicherheitsniveau im Vergleich zu USER oder USER_ANON zusätzliche Sicherheit. Auf dieser Ebene wird nur geprüft, ob der Nutzer mit einer bestätigten E-Mail-Adresse bei Authentication angemeldet ist. Es werden keine weiteren Prüfungen durchgeführt, z. B. ob die Daten dem Nutzer gehören. Best Practices und Alternativen
Entspricht @auth(expr: "auth.uid != nil &&
auth.token.email_verified")" |
NO_ACCESS |
Dieser Vorgang kann nicht außerhalb eines Admin SDK-Kontexts ausgeführt werden.
Entspricht @auth(expr: "false") |
CEL-Referenz für @auth(expr)
und @check(expr)
Wie in den Beispielen an anderer Stelle in diesem Leitfaden gezeigt, können und sollten Sie Ausdrücke verwenden, die in der Common Expression Language (CEL) definiert sind, um die Autorisierung für Data Connect mithilfe von @auth(expr:)
- und @check
-Direktiven zu steuern.
In diesem Abschnitt wird die CEL-Syntax behandelt, die für das Erstellen von Ausdrücken für diese Richtlinien relevant ist.
Vollständige Referenzinformationen zu CEL finden Sie in der CEL-Spezifikation.
Testvariablen, die in Abfragen und Mutationen übergeben werden
Mit der @auth(expr)
-Syntax können Sie auf Variablen aus Abfragen und Mutationen zugreifen und sie testen.
Sie können beispielsweise eine Vorgangsvariable wie $status
mit vars.status
einfügen.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
Für Ausdrücke verfügbare Daten
Sowohl @auth(expr:)
als auch @check(expr:)
können CEL-Ausdrücke für Folgendes auswerten:
request.operationName
vars
(Alias fürrequest.variables
)auth
(Alias fürrequest.auth
)
Außerdem können @check(expr:)
-Ausdrücke Folgendes auswerten:
this
(Wert des aktuellen Felds)
Das Objekt „request.operationName“
Im request.operarationName
-Objekt wird der Vorgangstyp gespeichert, also „Abfrage“ oder „Mutation“.
Das vars
-Objekt
Über das vars
-Objekt können Ihre Ausdrücke auf alle Variablen zugreifen, die in Ihrer Abfrage oder Mutation übergeben wurden.
Sie können vars.<variablename>
in einem Ausdruck als Alias für die vollständige request.variables.<variablename>
verwenden:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
Das auth
-Objekt
Authentication identifiziert Nutzer, die Zugriff auf Ihre Daten anfordern, und stellt diese Informationen als Objekt bereit, auf das Sie in Ihren Ausdrücken aufbauen können.
In Ihren Filtern und Ausdrücken können Sie auth
als Alias für request.auth
verwenden.
Das Auth-Objekt enthält die folgenden Informationen:
uid
: Eine eindeutige Nutzer-ID, die dem anfragenden Nutzer zugewiesen ist.token
: Eine Zuordnungstabelle der von Authentication erfassten Werte.
Weitere Informationen zum Inhalt von auth.token
finden Sie unter Daten in Auth-Tokens.
Die this
-Bindung
Die Bindung this
wird auf das Feld angewendet, an das die Anweisung @check
angehängt ist. In einem einfachen Fall können Sie Ergebnisse von Abfragen mit nur einem Wert auswerten.
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
})
}
Wenn das zurückgegebene Feld mehrmals vorkommt, weil ein Vorfahr eine Liste ist, wird jedes Vorkommen mit this
getestet, das an jeden Wert gebunden ist.
Wenn ein Vorfahr eines bestimmten Pfades null
oder []
ist, wird das Feld nicht erreicht und die CEL-Bewertung für diesen Pfad übersprungen. Mit anderen Worten: Die Auswertung erfolgt nur, wenn this
null
oder nicht null
ist, aber niemals undefined
.
Wenn das Feld selbst eine Liste oder ein Objekt ist, folgt this
derselben Struktur (einschließlich aller ausgewählter Abkömmlinge bei Objekten), wie im folgenden Beispiel dargestellt.
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
})
}
Syntax komplexer Ausdrücke
Sie können komplexere Ausdrücke formulieren, indem Sie sie mit den Operatoren &&
und ||
kombinieren.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
Im folgenden Abschnitt werden alle verfügbaren Operatoren beschrieben.
Operatoren und Operatorrangfolge
In der folgenden Tabelle finden Sie eine Übersicht über die Operatoren und ihre jeweilige Priorität.
Es sind beliebige Ausdrücke a
und b
, ein Feld f
und ein Index i
gegeben.
Operator | Beschreibung | Assoziativität |
---|---|---|
a[i] a() a.f |
Index, Aufruf, Feldzugriff | von links nach rechts |
!a -a |
Unäre Negation | von rechts nach links |
a/b a%b a*b |
Multiplikative Operatoren | von links nach rechts |
a+b a-b |
Additivoperatoren | von links nach rechts |
a>b a>=b a<b a<=b |
Relationale Operatoren | von links nach rechts |
a in b |
Vorhandensein in Liste oder Karte | von links nach rechts |
type(a) == t |
Typvergleich, wobei t „bool“, „int“, „float“, „number“, „string“, „list“, „map“, „timestamp“ oder „duration“ sein kann |
von links nach rechts |
a==b a!=b |
Vergleichsoperatoren | von links nach rechts |
a && b |
Bedingtes AND | von links nach rechts |
a || b |
Bedingtes ODER | von links nach rechts |
a ? true_value : false_value |
Ternärer Ausdruck | von links nach rechts |
Daten in Auth-Tokens
Das auth.token
-Objekt kann die folgenden Werte enthalten:
Feld | Beschreibung |
---|---|
email |
Die mit dem Konto verknüpfte E-Mail-Adresse, sofern vorhanden. |
email_verified |
true , wenn der Nutzer bestätigt hat, dass er Zugriff auf die email -Adresse hat. Einige Anbieter bestätigen E-Mail-Adressen, die ihnen gehören, automatisch. |
phone_number |
Die mit dem Konto verknüpfte Telefonnummer, falls vorhanden. |
name |
Der Anzeigename des Nutzers, falls festgelegt. |
sub |
Die Firebase-UID des Nutzers. Dieser Wert ist innerhalb eines Projekts eindeutig. |
firebase.identities |
Wörterbuch aller Identitäten, die mit dem Konto dieses Nutzers verknüpft sind. Die Schlüssel des Wörterbuchs können einen der folgenden Werte haben: email , phone , google.com , facebook.com , github.com oder twitter.com . Die Werte des Wörterbuchs sind Arrays eindeutiger IDs für jeden Identitätsanbieter, der mit dem Konto verknüpft ist. auth.token.firebase.identities["google.com"][0] enthält beispielsweise die erste Google-Nutzer-ID, die mit dem Konto verknüpft ist. |
firebase.sign_in_provider |
Der Anmeldeanbieter, der zum Abrufen dieses Tokens verwendet wurde. Kann einer der folgenden Strings sein: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant |
Die mit dem Konto verknüpfte „tenantId“, falls vorhanden. Beispiel: tenant2-m6tyz |
Zusätzliche Felder in JWT-ID-Tokens
Sie können auch auf die folgenden auth.token
-Felder zugreifen:
Benutzerdefinierte Token-Anforderungen | ||
---|---|---|
alg |
Algorithmus | "RS256" |
iss |
Aussteller | Die E-Mail-Adresse des Dienstkontos Ihres Projekts |
sub |
Betreff | Die E-Mail-Adresse des Dienstkontos Ihres Projekts |
aud |
Zielgruppe | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Ausstellungszeit | Die aktuelle Zeit in Sekunden seit der UNIX-Epoche |
exp |
Ablaufzeit |
Die Zeit in Sekunden seit der UNIX-Epoche, zu der das Token abläuft. Dies kann maximal 3.600 Sekunden später als iat sein.
Beachten Sie, dass damit nur der Zeitpunkt gesteuert wird, zu dem das benutzerdefinierte Token selbst abläuft. Wenn Sie jedoch einen Nutzer mit signInWithCustomToken() anmelden, bleiben er so lange auf dem Gerät angemeldet, bis die Sitzung ungültig wird oder der Nutzer sich abmeldet.
|
<claims> (optional) |
Optionale benutzerdefinierte Ansprüche, die in das Token aufgenommen werden sollen. Auf diese kann in Ausdrücken über auth.token (oder request.auth.token ) zugegriffen werden. Wenn du beispielsweise einen benutzerdefinierten Anspruch adminClaim erstellst, kannst du über auth.token.adminClaim darauf zugreifen.
|
Nächste Schritte
- Firebase Data Connect bietet ein Admin SDK, mit dem Sie Abfragen und Mutationen aus privilegierten Umgebungen ausführen können.
- Informationen zur IAM-Sicherheit finden Sie im Leitfaden zum Verwalten von Diensten und Datenbanken.