Firebase Data Connect memberikan keamanan sisi klien yang andal dengan:
- Otorisasi klien seluler dan web
- Kontrol otorisasi tingkat kueri dan mutasi individual
- Pengesahan aplikasi dengan Firebase App Check.
Data Connect memperluas keamanan ini dengan:
- Otorisasi sisi server
- Keamanan pengguna project Firebase dan Cloud SQL dengan IAM.
Memberi otorisasi kueri dan mutasi klien
Data Connect terintegrasi sepenuhnya dengan Firebase Authentication, sehingga Anda dapat menggunakan data lengkap tentang pengguna yang mengakses data Anda (autentikasi) dalam desain untuk data yang dapat diakses pengguna tersebut (otorisasi).
Data Connect menyediakan perintah @auth
untuk kueri dan
mutasi yang memungkinkan Anda menetapkan tingkat autentikasi yang diperlukan untuk memberikan otorisasi
pada operasi. Panduan ini
memperkenalkan perintah @auth
, dengan contoh.
Selain itu, Data Connect mendukung eksekusi kueri yang disematkan dalam mutasi, sehingga Anda dapat mengambil kriteria otorisasi tambahan yang telah disimpan dalam database, dan menggunakan kriteria tersebut dalam perintah @check
untuk memutuskan apakah mutasi yang menyertainya diotorisasi. Untuk kasus otorisasi ini, perintah @redact
memungkinkan Anda mengontrol apakah hasil kueri ditampilkan kepada klien dalam
protokol wire dan kueri tersemat dihilangkan dalam SDK yang dihasilkan. Temukan
pengantar perintah ini, beserta contohnya.
Memahami perintah @auth
Anda dapat membuat parameter perintah @auth
untuk mengikuti salah satu dari beberapa tingkat akses
preset yang mencakup banyak skenario akses umum. Tingkat ini berkisar dari PUBLIC
(yang mengizinkan kueri dan mutasi dari semua klien tanpa autentikasi apa pun) hingga NO_ACCESS
(yang tidak mengizinkan kueri dan mutasi di luar lingkungan server dengan hak istimewa menggunakan Firebase Admin SDK). Setiap level ini berkorelasi dengan alur autentikasi
yang disediakan oleh Firebase Authentication.
Tingkat | Definisi |
---|---|
PUBLIC |
Operasi ini dapat dijalankan oleh siapa saja dengan atau tanpa autentikasi. |
PUBLIC |
Operasi ini dapat dijalankan oleh siapa saja dengan atau tanpa autentikasi. |
USER_ANON |
Setiap pengguna yang diidentifikasi, termasuk pengguna yang telah login secara anonim dengan Firebase Authentication, diberi otorisasi untuk menjalankan kueri atau mutasi. |
USER |
Setiap pengguna yang telah login dengan Firebase Authentication diberi otorisasi untuk menjalankan kueri atau mutasi, kecuali pengguna login anonim. |
USER_EMAIL_VERIFIED |
Setiap pengguna yang telah login dengan Firebase Authentication dengan alamat email yang terverifikasi diberi otorisasi untuk melakukan kueri atau mutasi. |
NO_ACCESS |
Operasi ini tidak dapat dijalankan di luar konteks Admin SDK. |
Dengan menggunakan tingkat akses preset ini sebagai titik awal, Anda dapat menentukan pemeriksaan otorisasi yang kompleks dan
andal dalam perintah @auth
menggunakan filter where
dan
ekspresi Common Expression Language (CEL) yang dievaluasi di server.
Menggunakan perintah @auth
untuk menerapkan skenario otorisasi umum
Tingkat akses preset adalah titik awal untuk otorisasi.
Tingkat akses USER
adalah tingkat dasar yang paling berguna untuk memulai.
Akses yang sepenuhnya aman akan dibuat di tingkat USER
beserta filter dan ekspresi
yang memeriksa atribut pengguna, atribut resource, peran, dan pemeriksaan lainnya. Level
USER_ANON
dan USER_EMAIL_VERIFIED
adalah variasi pada kasus USER
.
Sintaksis ekspresi memungkinkan Anda mengevaluasi data menggunakan objek auth
yang mewakili data autentikasi yang diteruskan dengan operasi, baik data standar dalam token autentikasi maupun data kustom dalam token. Untuk mengetahui daftar kolom yang tersedia di objek auth
, lihat bagian referensi.
Tentu saja ada kasus penggunaan saat PUBLIC
adalah tingkat akses yang benar untuk
dimulai. Sekali lagi, tingkat akses selalu menjadi titik awal, dan filter serta ekspresi tambahan diperlukan untuk keamanan yang andal.
Panduan ini sekarang memberikan contoh cara mem-build di USER
dan PUBLIC
.
Contoh motivasi
Contoh praktik terbaik berikut merujuk pada skema berikut untuk platform blog dengan konten tertentu yang dikunci di balik paket pembayaran.
Platform semacam itu kemungkinan akan membuat model Users
danPosts
.
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")
}
Resource milik pengguna
Firebase merekomendasikan agar Anda menulis filter dan ekspresi yang menguji kepemilikan pengguna atas resource, dalam kasus berikut, kepemilikan Posts
.
Dalam contoh berikut, data dari token autentikasi dibaca dan dibandingkan menggunakan
ekspresi. Pola umumnya adalah menggunakan ekspresi seperti where: {authorUid:
{eq_expr: "auth.uid"}}
untuk membandingkan authorUid
yang disimpan dengan auth.uid
(ID pengguna) yang diteruskan dalam token autentikasi.
Buat
Praktik otorisasi ini dimulai dengan menambahkan auth.uid
dari
token autentikasi ke setiap Post
baru sebagai kolom authorUid
untuk memungkinkan perbandingan dalam
pengujian otorisasi urutan berikutnya.
# 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
})
}
Perbarui
Saat klien mencoba mengupdate Post
, Anda dapat menguji auth.uid
yang diteruskan
dengan authorUid
yang disimpan.
# 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"
}
)
}
Hapus
Teknik yang sama digunakan untuk memberikan otorisasi operasi penghapusan.
# 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 }
}
Daftar
# 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
}
}
Dapatkan
# 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
}
}
Memfilter Data
Sistem otorisasi Data Connect memungkinkan Anda menulis filter
yang canggih yang digabungkan dengan tingkat akses preset seperti PUBLIC
serta dengan menggunakan
data dari token autentikasi.
Sistem otorisasi juga memungkinkan Anda menggunakan ekspresi saja, tanpa tingkat akses dasar, seperti yang ditunjukkan dalam beberapa contoh berikut.
Memfilter menurut atribut resource
Di sini, otorisasi tidak didasarkan pada token autentikasi karena tingkat keamanan dasar
ditetapkan ke PUBLIC
. Namun, kita dapat menetapkan data di database secara eksplisit sebagai
cocok untuk akses publik; asumsikan kita memiliki data Post
di database dengan
visibility
ditetapkan ke "public".
# 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
}
}
Memfilter menurut klaim pengguna
Di sini, asumsikan Anda telah menyiapkan klaim pengguna kustom yang meneruskan token autentikasi untuk
mengidentifikasi pengguna dalam paket "pro" untuk aplikasi Anda, yang ditandai dengan kolom auth.token.plan
di token autentikasi. Ekspresi Anda dapat diuji terhadap kolom ini.
# 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
}
}
Filter menurut urutan + batas
Atau lagi, Anda mungkin telah menetapkan visibility
dalam data Post
untuk mengidentifikasi bahwa data tersebut adalah konten yang tersedia untuk pengguna "pro", tetapi untuk pratinjau atau listingan teaser data, batasi lebih lanjut jumlah data yang ditampilkan.
# 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
}
}
Memfilter menurut peran
Jika klaim kustom menentukan peran admin
, Anda dapat menguji dan memberikan otorisasi
pada operasi yang sesuai.
# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
posts { ...DisplayPost }
}
Memahami perintah @check
dan @redact
Perintah @check
memverifikasi bahwa kolom yang ditentukan ada dalam hasil
kueri. Ekspresi Common Expression Language (CEL) digunakan untuk menguji nilai kolom. Perilaku default perintah ini adalah memeriksa dan menolak node bernilai null
.
Perintah @redact
menyamarkan bagian respons dari klien. Kolom yang disamarkan
masih dievaluasi untuk efek samping (termasuk perubahan data dan
@check
) dan hasilnya masih tersedia untuk langkah berikutnya dalam ekspresi CEL.
Di Data Connect, perintah @check
dan @redact
paling sering
digunakan dalam konteks pemeriksaan otorisasi; lihat
diskusi pencarian data otorisasi.
Menambahkan perintah @check
dan @redact
untuk mencari data otorisasi
Kasus penggunaan otorisasi umum melibatkan penyimpanan peran otorisasi kustom di database Anda, misalnya dalam tabel izin khusus, dan menggunakan peran tersebut untuk memberikan otorisasi mutasi guna membuat, memperbarui, atau menghapus data.
Dengan menggunakan pencarian data otorisasi, Anda dapat membuat kueri untuk peran berdasarkan userID dan
menggunakan ekspresi CEL untuk memutuskan apakah mutasi diotorisasi. Misalnya, Anda
mungkin ingin menulis mutasi UpdateMovieTitle
yang memungkinkan klien
yang diotorisasi memperbarui judul film.
Untuk sisa diskusi ini, asumsikan database aplikasi ulasan film menyimpan
peran otorisasi dalam tabel 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!
}
Dalam contoh implementasi berikut, mutasi UpdateMovieTitle
menyertakan kolom query
untuk mengambil data dari MoviePermission
, dan
perintah berikut untuk memastikan operasi aman dan andal:
- Perintah
@transaction
untuk memastikan semua kueri dan pemeriksaan otorisasi selesai atau gagal secara atomik. - Perintah
@redact
untuk menghapus hasil kueri dari respons, yang berarti pemeriksaan otorisasi kami dilakukan di server Data Connect, tetapi data sensitif tidak ditampilkan kepada klien. Sepasang perintah
@check
untuk mengevaluasi logika otorisasi pada hasil kueri, seperti menguji apakah userID tertentu memiliki peran yang sesuai untuk melakukan perubahan.
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
})
}
Antipola yang harus dihindari dalam otorisasi
Bagian sebelumnya membahas pola yang harus diikuti saat menggunakan perintah @auth
.
Anda juga harus mengetahui antipola penting yang harus dihindari.
Hindari meneruskan ID atribut pengguna dan parameter token autentikasi dalam argumen kueri dan mutasi
Firebase Authentication adalah alat yang canggih untuk menampilkan alur autentikasi dan mengambil data autentikasi dengan aman seperti ID pengguna terdaftar dan banyak kolom yang disimpan dalam token autentikasi.
Sebaiknya jangan meneruskan ID pengguna dan data token autentikasi dalam argumen kueri dan mutasi.
# 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
}
}
Hindari penggunaan tingkat akses USER
tanpa filter
Seperti yang telah dibahas beberapa kali dalam panduan ini, tingkat akses inti seperti USER
,
USER_ANON
, USER_EMAIL_VERIFIED
adalah dasar pengukuran dan titik awal untuk
pemeriksaan otorisasi, yang akan ditingkatkan dengan filter dan ekspresi. Menggunakan level ini tanpa filter atau ekspresi yang sesuai yang memeriksa pengguna yang melakukan permintaan pada dasarnya setara dengan menggunakan level PUBLIC
.
# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
documents {
id
title
text
}
}
Menghindari penggunaan tingkat akses PUBLIC
atau USER
untuk pembuatan prototipe
Untuk mempercepat pengembangan, Anda mungkin ingin menetapkan semua operasi ke
level akses PUBLIC
atau ke level akses USER
tanpa peningkatan lebih lanjut untuk
memberi otorisasi semua operasi dan memungkinkan Anda menguji kode dengan cepat.
Setelah Anda melakukan pembuatan prototipe awal dengan cara ini, mulai beralih dari
NO_ACCESS
ke otorisasi siap produksi dengan level PUBLIC
dan USER
.
Namun, jangan deploynya sebagai PUBLIC
atau USER
tanpa menambahkan logika tambahan
seperti yang ditunjukkan dalam panduan ini.
# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
post: post_delete(
id: $id,
)
}
Menggunakan Firebase App Check untuk pengesahan aplikasi
Autentikasi dan otorisasi adalah komponen penting dari keamanan Data Connect. Autentikasi dan otorisasi yang dikombinasikan dengan atestasi aplikasi akan menghasilkan solusi keamanan yang sangat andal.
Dengan pengesahan melalui Firebase App Check, perangkat yang menjalankan aplikasi Anda akan menggunakan penyedia pengesahan aplikasi atau perangkat yang menyatakan bahwa operasi Data Connect berasal dari aplikasi asli Anda dan permintaan berasal dari perangkat asli yang tidak dimodifikasi. Pengesahan ini dilampirkan ke setiap permintaan yang dibuat aplikasi Anda ke Data Connect.
Untuk mempelajari cara mengaktifkan App Check untuk Data Connect dan menyertakan SDK kliennya di aplikasi Anda, lihat ringkasan App Check.
Tingkat autentikasi untuk perintah @auth(level)
Tabel berikut mencantumkan semua tingkat akses standar dan CEL yang setara. Tingkat autentikasi dicantumkan dari yang luas ke yang sempit -- setiap tingkat mencakup semua pengguna yang cocok dengan tingkat berikut.
Tingkat | Definisi |
---|---|
PUBLIC |
Operasi ini dapat dijalankan oleh siapa saja dengan atau tanpa autentikasi.
Pertimbangan: Data dapat dibaca atau diubah oleh pengguna mana pun. Firebase merekomendasikan tingkat otorisasi ini untuk data yang dapat dijelajahi secara publik seperti listingan produk atau media. Lihat contoh dan alternatif praktik terbaik. Setara dengan filter dan ekspresi @auth(expr: "true")
@auth tidak dapat digunakan bersama
dengan tingkat akses ini. Ekspresi tersebut akan gagal dengan error permintaan buruk 400.
|
USER_ANON |
Setiap pengguna yang diidentifikasi, termasuk pengguna yang telah login secara anonim
dengan Firebase Authentication, diberi otorisasi untuk menjalankan kueri atau mutasi.
Catatan: USER_ANON adalah superset dari USER .
Pertimbangan: Perhatikan bahwa Anda harus mendesain kueri dan mutasi dengan cermat untuk tingkat otorisasi ini. Tingkat ini memungkinkan pengguna login secara anonim (login otomatis yang hanya terikat dengan perangkat pengguna) dengan Authentication, dan tidak melakukan pemeriksaan lain secara mandiri, misalnya, apakah data milik pengguna. Lihat contoh dan alternatif praktik terbaik. Karena alur login anonim Authentication menerbitkan uid , level
USER_ANON setara dengan
@auth(expr: "auth.uid != nil")
|
USER |
Setiap pengguna yang telah login dengan Firebase Authentication diberi otorisasi untuk
menjalankan kueri atau mutasi, kecuali pengguna login anonim.
Pertimbangan: Perhatikan bahwa Anda harus mendesain kueri dan mutasi dengan cermat untuk tingkat otorisasi ini. Tingkat ini hanya memeriksa apakah pengguna login dengan Authentication, dan tidak secara mandiri melakukan pemeriksaan lain, misalnya, apakah data milik pengguna. Lihat contoh dan alternatif praktik terbaik. Setara dengan @auth(expr: "auth.uid != nil &&
auth.token.firebase.sign_in_provider != 'anonymous'")"
|
USER_EMAIL_VERIFIED |
Setiap pengguna yang telah login dengan Firebase Authentication dengan alamat email yang terverifikasi diberi otorisasi untuk melakukan kueri atau mutasi.
Pertimbangan: Karena verifikasi email dilakukan menggunakan Authentication, verifikasi ini didasarkan pada metode Authentication yang lebih andal, sehingga tingkat ini memberikan keamanan tambahan dibandingkan dengan USER atau
USER_ANON . Tingkat ini hanya memeriksa apakah pengguna login
dengan Authentication menggunakan email terverifikasi, dan tidak melakukan
pemeriksaan lain secara mandiri, misalnya, apakah data milik pengguna. Lihat
contoh dan alternatif praktik terbaik.
Setara dengan @auth(expr: "auth.uid != nil &&
auth.token.email_verified")" |
NO_ACCESS |
Operasi ini tidak dapat dijalankan di luar konteks Admin SDK.
Setara dengan @auth(expr: "false") |
Referensi CEL untuk @auth(expr)
dan @check(expr)
Seperti yang ditunjukkan dalam contoh di tempat lain dalam panduan ini, Anda dapat dan harus menggunakan
ekspresi yang ditentukan dalam Common Expression Language (CEL) untuk mengontrol otorisasi
untuk Data Connect menggunakan perintah @auth(expr:)
dan @check
.
Bagian ini membahas sintaksis CEL yang relevan dengan pembuatan ekspresi untuk perintah ini.
Informasi referensi lengkap untuk CEL disediakan dalam spesifikasi CEL.
Menguji variabel yang diteruskan dalam kueri dan mutasi
Sintaksis @auth(expr)
memungkinkan Anda mengakses dan menguji variabel dari kueri dan mutasi.
Misalnya, Anda dapat menyertakan variabel operasi, seperti $status
, menggunakan
vars.status
.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
Data yang tersedia untuk ekspresi
Ekspresi CEL @auth(expr:)
dan @check(expr:)
dapat mengevaluasi hal berikut:
request.operationName
vars
(alias untukrequest.variables
)auth
(alias untukrequest.auth
)
Selain itu, ekspresi @check(expr:)
dapat mengevaluasi:
this
(nilai kolom saat ini)
Objek request.operationName
Objek request.operarationName
menyimpan jenis operasi, baik kueri maupun mutasi.
Objek vars
Objek vars
memungkinkan ekspresi Anda mengakses semua variabel
yang diteruskan dalam kueri atau mutasi.
Anda dapat menggunakan vars.<variablename>
dalam ekspresi sebagai alias untuk
request.variables.<variablename>
yang sepenuhnya memenuhi syarat:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
Objek auth
Authentication mengidentifikasi pengguna yang meminta akses ke data Anda dan memberikan informasi tersebut sebagai objek yang dapat Anda buat dalam ekspresi.
Dalam filter dan ekspresi, Anda dapat menggunakan auth
sebagai alias untuk
request.auth
.
Objek auth berisi informasi berikut:
uid
: ID pengguna unik, yang ditetapkan untuk pengguna yang meminta.token
: Peta nilai yang dikumpulkan oleh Authentication.
Untuk mengetahui detail selengkapnya tentang konten auth.token
, lihat
Data dalam token autentikasi
Binding this
this
pengikatan dievaluasi ke kolom tempat perintah @check
disertakan. Dalam kasus dasar, Anda dapat mengevaluasi hasil kueri bernilai tunggal.
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
})
}
Jika kolom yang ditampilkan muncul beberapa kali karena setiap ancestor adalah daftar, setiap
kejadian akan diuji dengan this
yang terikat ke setiap nilai.
Untuk jalur tertentu, jika ancestor adalah null
atau []
, kolom tidak akan
dijangkau dan evaluasi CEL akan dilewati untuk jalur tersebut. Dengan kata lain,
evaluasi hanya terjadi jika this
adalah null
atau non-null
, tetapi tidak pernah
undefined
.
Jika kolom itu sendiri adalah daftar atau objek, this
akan mengikuti struktur yang sama (termasuk semua turunan yang dipilih jika berupa objek), seperti yang diilustrasikan dalam contoh berikut.
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
})
}
Sintaksis ekspresi kompleks
Anda dapat menulis ekspresi yang lebih kompleks dengan menggabungkannya dengan operator
&&
dan ||
.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
Bagian berikut menjelaskan semua operator yang tersedia.
Operator dan prioritas operator
Gunakan tabel berikut sebagai referensi untuk operator dan prioritasnya yang sesuai.
Ekspresi arbitrer tertentu a
dan b
, kolom f
, dan indeks i
.
Operator | Deskripsi | Asosiativitas |
---|---|---|
a[i] a() a.f |
Akses indeks, panggilan, kolom | kiri ke kanan |
!a -a |
Negasi unary | kanan ke kiri |
a/b a%b a*b |
Operator multiplikatif | kiri ke kanan |
a+b a-b |
Operator aditif | kiri ke kanan |
a>b a>=b a<b a<=b |
Operator relasional | kiri ke kanan |
a in b |
Keberadaan dalam daftar atau peta | kiri ke kanan |
type(a) == t |
Perbandingan jenis, dengan t dapat berupa bool, int, float, angka, string, daftar, peta, stempel waktu, atau durasi |
kiri ke kanan |
a==b a!=b |
Operator perbandingan | kiri ke kanan |
a && b |
AND kondisional | kiri ke kanan |
a || b |
OR kondisional | kiri ke kanan |
a ? true_value : false_value |
Ekspresi ternary | kiri ke kanan |
Data dalam token autentikasi
Objek auth.token
dapat berisi nilai berikut:
Kolom | Deskripsi |
---|---|
email |
Alamat email yang terhubung dengan akun, jika ada. |
email_verified |
true jika pengguna telah memverifikasi bahwa mereka memiliki akses ke alamat email . Beberapa penyedia secara otomatis memverifikasi alamat email yang mereka miliki. |
phone_number |
Nomor telepon yang terkait dengan akun, jika ada. |
name |
Nama tampilan pengguna, jika ditetapkan. |
sub |
UID Firebase pengguna. UID ini bersifat unik dalam sebuah project. |
firebase.identities |
Kamus yang memuat semua identitas terkait akun pengguna ini. Kunci kamus dapat berupa salah satu dari berikut ini: email , phone , google.com , facebook.com , github.com , twitter.com . Nilai kamus adalah array ID unik untuk setiap penyedia identitas yang terkait dengan akun. Misalnya, auth.token.firebase.identities["google.com"][0] berisi ID pengguna Google pertama yang dikaitkan dengan akun. |
firebase.sign_in_provider |
Penyedia login yang digunakan untuk mendapatkan token ini. Dapat berupa salah satu string berikut: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant |
tenantId yang terkait dengan akun, jika ada. Contoh, tenant2-m6tyz |
Kolom tambahan di token ID JWT
Anda juga dapat mengakses kolom auth.token
berikut:
Klaim Token Kustom | ||
---|---|---|
alg |
Algoritme | "RS256" |
iss |
Penerbit | Alamat email akun layanan project Anda |
sub |
Subjek | Alamat email akun layanan project Anda |
aud |
Audience | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Waktu penerbitan | Waktu saat ini, dalam satuan detik sejak epoch UNIX |
exp |
Waktu habis masa berlaku |
Waktu saat token sudah tidak berlaku lagi, dalam satuan detik sejak epoch UNIX. Waktu ini bisa mencapai maksimum 3600 detik lebih lama daripada iat .
Catatan: ini hanya mengontrol kapan token kustom berhenti berlaku. Namun, setelah Anda memproses login menggunakan signInWithCustomToken() , pengguna akan tetap login di perangkatnya hingga validitas sesi berakhir atau pengguna tersebut logout.
|
<claims> (opsional) |
Klaim kustom opsional yang akan disertakan dalam token, yang dapat diakses melalui
auth.token (atau request.auth.token ) dalam
ekspresi. Misalnya, jika Anda membuat adminClaim
klaim kustom, Anda dapat mengaksesnya dengan
auth.token.adminClaim .
|
Apa langkah selanjutnya?
- Firebase Data Connect menyediakan Admin SDK untuk memungkinkan Anda melakukan kueri dan mutasi dari lingkungan istimewa.
- Pelajari keamanan IAM di panduan untuk mengelola layanan dan database.