Firebase Data Connect aşağıdaki özelliklerle güçlü bir istemci tarafı güvenliği sağlar:
- Mobil ve web istemcisi yetkilendirmesi
- Ayrı ayrı sorgu ve mutasyon düzeyinde yetkilendirme kontrolleri
- Firebase App Check ile uygulama onayı.
Data Connect, bu güvenliği şu özelliklerle genişletir:
- Sunucu tarafı yetkilendirme
- IAM ile Firebase projesi ve Cloud SQL kullanıcı güvenliği.
İstemci sorgularını ve mutasyonlarını yetkilendirme
Data Connect, Firebase Authentication ile tamamen entegre olduğundan verilerinize erişen kullanıcılar (kimlik doğrulama) hakkındaki zengin verileri, bu kullanıcıların hangi verilere erişebileceği (yetkilendirme) ile ilgili tasarımınızda kullanabilirsiniz.
Data Connect, sorgular ve mutasyonlar için @auth yönergesi sağlar. Bu yönerge, işlemi yetkilendirmek için gereken kimlik doğrulama düzeyini ayarlamanıza olanak tanır. Bu kılavuzda, @auth yönergesi örneklerle açıklanmaktadır.
Ayrıca, Data Connect mutasyonlara yerleştirilmiş sorguların yürütülmesini destekler. Böylece, veritabanınızda depoladığınız ek yetkilendirme ölçütlerini alabilir ve bu ölçütleri, kapsayan mutasyonların yetkili olup olmadığını belirlemek için @check yönergelerinde kullanabilirsiniz. Bu yetkilendirme durumunda, @redact yönergesi, sorgu sonuçlarının kablo protokolünde istemcilere döndürülüp döndürülmeyeceğini ve oluşturulan SDK'larda yerleştirilmiş sorgunun atlanıp atlanmayacağını kontrol etmenize olanak tanır. Bu yönergelerin örneklerle birlikte tanıtımını inceleyin.
@auth direktifini anlama
Birçok yaygın erişim senaryosunu kapsayan önceden ayarlanmış çeşitli erişim düzeylerinden birini takip etmek için @auth yönergesini parametrelendirebilirsiniz. Bu düzeyler, PUBLIC (herhangi bir kimlik doğrulama olmadan tüm istemcilerden gelen sorgulara ve mutasyonlara izin verir) ile NO_ACCESS (Firebase Admin SDK'sını kullanan ayrıcalıklı sunucu ortamları dışındaki sorgulara ve mutasyonlara izin vermez) arasında değişir. Bu seviyelerin her biri, Firebase Authentication tarafından sağlanan kimlik doğrulama akışlarıyla ilişkilidir.
| Seviye | Tanım |
|---|---|
PUBLIC |
İşlem, kimlik doğrulama yapılarak veya yapılmadan herkes tarafından yürütülebilir. |
PUBLIC |
İşlem, kimlik doğrulama yapılarak veya yapılmadan herkes tarafından yürütülebilir. |
USER_ANON |
Firebase Authentication ile anonim olarak giriş yapanlar da dahil olmak üzere tanımlanan tüm kullanıcılar sorgu veya mutasyon gerçekleştirmeye yetkilidir. |
USER |
Firebase Authentication ile giriş yapan tüm kullanıcılar, anonim giriş yapan kullanıcılar hariç sorgu veya mutasyon gerçekleştirmek için yetkilidir. |
USER_EMAIL_VERIFIED |
Doğrulanmış bir e-posta adresiyle Firebase Authentication üzerinden giriş yapan tüm kullanıcılar sorgu veya mutasyon gerçekleştirmeye yetkilidir. |
NO_ACCESS |
Bu işlem, Admin SDK bağlamı dışında yürütülemez. |
Bu önceden ayarlanmış erişim düzeylerini başlangıç noktası olarak kullanarak, @auth yönergesinde where filtreleri ve sunucuda değerlendirilen Common Expression Language (CEL) ifadelerini kullanarak karmaşık ve güçlü yetkilendirme kontrolleri tanımlayabilirsiniz.
@auth
Yaygın yetkilendirme senaryolarını uygulamak için @auth yönergesini kullanın
Önceden ayarlanmış erişim düzeyleri, yetkilendirme için başlangıç noktasıdır.
USER erişim düzeyi, başlangıç için en yaygın olarak kullanılan temel düzeydir.
Tamamen güvenli erişim, USER düzeyinin yanı sıra kullanıcı özelliklerini, kaynak özelliklerini, rolleri ve diğer kontrolleri inceleyen filtreler ve ifadeler üzerine kurulur. USER_ANON ve USER_EMAIL_VERIFIED seviyeleri, USER durumunun varyasyonlarıdır.
İfade söz dizimi, işlemlerde iletilen kimlik doğrulama verilerini temsil eden bir auth nesnesi kullanarak verileri değerlendirmenize olanak tanır. Bu veriler, hem kimlik doğrulama jetonlarındaki standart verileri hem de jetonlardaki özel verileri içerir. auth
nesnesinde kullanılabilen alanların listesi için referans bölümüne bakın.
Elbette, PUBLIC ile başlamanın doğru erişim düzeyi olduğu kullanım alanları da vardır. Erişim düzeyi her zaman başlangıç noktasıdır ve sağlam bir güvenlik için ek filtreler ve ifadeler gerekir.
Bu kılavuzda artık USER ve PUBLIC üzerinde nasıl geliştirme yapılacağına dair örnekler verilmektedir.
İlham verici bir örnek
Aşağıdaki en iyi uygulama örnekleri, belirli içeriklerin ödeme planı arkasında kilitlendiği bir blog platformunun aşağıdaki şemasına atıfta bulunmaktadır.
Bu tür bir platform büyük olasılıkla Users ve Posts modelini kullanır.
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")
}
Kullanıcıya ait kaynaklar
Firebase, aşağıdaki durumlarda kullanıcının bir kaynağın sahipliğini (Posts sahipliği) test eden filtreler ve ifadeler yazmanızı önerir.
Aşağıdaki örneklerde, kimlik doğrulama jetonlarındaki veriler ifadeler kullanılarak okunur ve karşılaştırılır. Tipik olarak, depolanmış bir authorUid değerini kimlik doğrulama jetonunda iletilen auth.uid (kullanıcı kimliği) ile karşılaştırmak için where: {authorUid:
{eq_expr: "auth.uid"}} gibi ifadeler kullanılır.
Oluştur
Bu yetkilendirme uygulaması, sonraki yetkilendirme testlerinde karşılaştırmaya olanak tanımak için yetkilendirme jetonundaki auth.uid değerini her yeni Post öğesine authorUid alanı olarak ekleyerek başlar.
# 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
})
}
Güncelle
Bir istemci Post güncellemeye çalıştığında, iletilen auth.uid değerini depolanan authorUid değerine göre test edebilirsiniz.
# 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"
}
)
}
Sil
Silme işlemlerini yetkilendirmek için de aynı teknik kullanılır.
# 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
}
}
Verileri Filtreleme
Data Connect'nın yetkilendirme sistemi, PUBLIC gibi önceden ayarlanmış erişim düzeyleriyle birlikte karmaşık filtreler yazmanıza ve kimlik doğrulama jetonlarından gelen verileri kullanmanıza olanak tanır.
Yetkilendirme sistemi, aşağıdaki örneklerin bazılarında gösterildiği gibi, temel erişim düzeyi olmadan yalnızca ifadeler kullanmanıza da olanak tanır.
Kaynak özelliklerine göre filtreleme
Burada, temel güvenlik düzeyi PUBLIC olarak ayarlandığından yetkilendirme, kimlik doğrulama jetonlarına dayalı değildir. Ancak veritabanımızdaki kayıtları açıkça herkese açık erişime uygun olarak ayarlayabiliriz. Veritabanımızda Post kaydın herkese açık olarak ayarlandığını varsayalım.visibility
# 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
}
}
Kullanıcı hak taleplerine göre filtreleme
Burada, uygulamanızın "pro" planındaki kullanıcıları tanımlamak için kimlik doğrulama jetonlarına iletilen özel kullanıcı talepleri ayarladığınızı varsayalım. Bu kullanıcılar, kimlik doğrulama jetonunda auth.token.plan alanı ile işaretlenir. İfadeleriniz bu alana göre test edilebilir.
# 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
}
}
Sıraya ve sınıra göre filtreleme
Alternatif olarak, Post kayıtlarında visibility değerini ayarlayarak bu kayıtların "pro" kullanıcılar için kullanılabilen içerikler olduğunu belirtebilirsiniz. Ancak verilerin önizleme veya teaser listelenmesi için döndürülen kayıt sayısını daha da sınırlayabilirsiniz.
# 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
}
}
Role göre filtreleme
Özel talebiniz bir admin rolü tanımlıyorsa işlemleri buna göre test edip yetkilendirebilirsiniz.
# List all posts unconditionally iff the current user has an admin claim
query AdminListPosts @auth(expr: "auth.token.admin == true") {
posts { ...DisplayPost }
}
Yetkilendirme verilerini aramak için @check ve @redact yönergelerini ekleyin.
Yaygın bir yetkilendirme kullanım alanında, özel yetkilendirme rolleri veritabanınızda (ör. özel bir izin tablosunda) depolanır ve bu roller, veri oluşturma, güncelleme veya silme işlemlerini yetkilendirmek için kullanılır.
Yetkilendirme verisi aramalarını kullanarak bir kullanıcı kimliğine göre rolleri sorgulayabilir ve değişikliğin yetkilendirilip yetkilendirilmediğine karar vermek için CEL ifadelerini kullanabilirsiniz. Örneğin, yetkili bir istemcinin film başlıklarını güncellemesine olanak tanıyan bir UpdateMovieTitle mutasyonu yazmak isteyebilirsiniz.
Bu tartışmanın geri kalanında, film inceleme uygulaması veritabanının MoviePermission tablosunda bir yetkilendirme rolü depoladığını varsayalım.
# MoviePermission
# Suppose a user has an authorization role with respect to records in the Movie table
type MoviePermission @table(key: ["movie", "user"]) {
movie: Movie! # implies another field: movieId: UUID!
user: User!
role: String!
}
Mutasyonlarda kullanma
Aşağıdaki örnek uygulamada, UpdateMovieTitle mutasyonu, MoviePermission'den veri almak için bir query alanı ve işlemin güvenli ve sağlam olmasını sağlamak için aşağıdaki yönergeleri içerir:
- Tüm yetkilendirme sorgularının ve kontrollerinin
@transactiontamamlanmasını veya atomik olarak başarısız olmasını sağlayan bir yönerge. - Sorgu sonuçlarını yanıttan çıkarmak için
@redactyönergesi. Bu, yetkilendirme kontrolümüzün Data Connect sunucusunda yapıldığı ancak hassas verilerin istemciye gösterilmediği anlamına gelir. Sorgu sonuçlarındaki yetkilendirme mantığını değerlendirmek için kullanılan bir çift
@checkyönerge (ör. belirli bir kullanıcı kimliğinin değişiklik yapmak için uygun role sahip olup olmadığını test etme).
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
})
}
this
Sorgularda kullanma
Yetkilendirme verisi aramaları, sorguları rollere veya diğer kısıtlamalara göre kısıtlamak için de kullanışlıdır.
Aşağıdaki örnekte, MoviePermission şeması da kullanılarak bir isteği gönderenin, bir filmi düzenleyebilecek kullanıcıları görüntülemek için uygun bir "yönetici" rolüne sahip olup olmadığı kontrol edilir.
query GetMovieEditors($movieId: UUID!) @auth(level: PUBLIC) {
moviePermission(key: { movieId: $movieId, userId_expr: "auth.uid" }) @redact {
role @check(expr: "this == 'admin'", message: "You must be an admin to view all editors of a movie.")
}
moviePermissions(where: { movieId: { eq: $movieId }, role: { eq: "editor" } }) {
user {
id
username
}
}
}
this
Yetkilendirmede kaçınılması gereken anti-kalıplar
Önceki bölümde, @auth yönergesini kullanırken izlenecek kalıplar ele alınmıştır.
Ayrıca kaçınmanız gereken önemli antipattern'ler hakkında da bilgi sahibi olmalısınız.
Kullanıcı özelliği kimliklerini ve kimlik doğrulama jetonu parametrelerini sorgu ve mutasyon bağımsız değişkenlerinde iletmekten kaçının
Firebase Authentication, kimlik doğrulama akışlarını sunmak ve kayıtlı kullanıcı kimlikleri ile kimlik doğrulama jetonlarında depolanan çok sayıda alan gibi kimlik doğrulama verilerini güvenli bir şekilde yakalamak için kullanılan güçlü bir araçtır.
Kullanıcı kimliklerinin ve kimlik doğrulama jetonu verilerinin sorgu ve mutasyon bağımsız değişkenlerinde iletilmesi önerilen bir uygulama değildir.
# 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
}
}
USER erişim düzeyini filtre olmadan kullanmaktan kaçının
Kılavuzda birkaç kez belirtildiği gibi, USER, USER_ANON, USER_EMAIL_VERIFIED gibi temel erişim düzeyleri, filtreler ve ifadelerle geliştirilecek yetkilendirme kontrolleri için temel ve başlangıç noktalarıdır. Bu düzeyleri, isteği hangi kullanıcının gerçekleştirdiğini kontrol eden ilgili bir filtre veya ifade olmadan kullanmak, esasen PUBLIC düzeyini kullanmaya eşdeğerdir.
# Antipattern!
# This incorrectly allows any user to view all documents
query ListDocuments @auth(level: USER) {
documents {
id
title
text
}
}
Prototip oluşturma için PUBLIC veya USER erişim düzeyini kullanmaktan kaçının
Geliştirme sürecini hızlandırmak için tüm işlemleri PUBLIC erişim düzeyine veya USER erişim düzeyine ayarlamak cazip gelebilir. Bu sayede tüm işlemler yetkilendirilir ve kodunuzu hızlıca test edebilirsiniz.
Bu şekilde ilk prototipleme işlemini tamamladığınızda NO_ACCESS'dan PUBLIC ve USER seviyeleriyle üretime hazır yetkilendirmeye geçmeye başlayın.
Ancak bu kılavuzda gösterildiği gibi ek mantık eklemeden bunları PUBLIC veya USER olarak dağıtmayın.
# Antipattern!
# This incorrectly allows anyone to delete any post
mutation DeletePost($id: UUID!) @auth(level: PUBLIC) {
post: post_delete(
id: $id,
)
}
Yetkilendirmeyi doğrulanmamış e-posta adreslerine dayandırmaktan kaçının
Belirli bir alan adındaki kullanıcılara erişim izni vermek, erişimi sınırlamanın harika bir yoludur. Ancak, oturum açma sırasında herkes bir e-postanın sahibi olduğunu iddia edebilir. Yalnızca Firebase Authentication ile doğrulanmış e-posta adreslerine erişim izni verdiğinizden emin olun.
# Antipattern!
# Anyone can claim an email address during sign-in
mutation CreatePost($text: String!, $visibility: String) @auth(expr: "auth.token.email.endsWith('@example.com')") {
post_insert(data: {
# set the author's uid to the current user uid
authorUid_expr: "auth.uid"
text: $text
visibility: $visibility
})
}
Ayrıca auth.token.email_verified
mutation CreatePost($text: String!, $visibility: String) @auth(expr: "auth.token.email_verified && auth.token.email.endsWith('@example.com')") {
post_insert(data: {
# set the author's uid to the current user uid
authorUid_expr: "auth.uid"
text: $text
visibility: $visibility
})
}
Firebase CLI ile yetkilendirmeyi denetleme
Daha önce belirtildiği gibi, PUBLIC ve USER gibi önceden ayarlanmış erişim düzeyleri, güçlü yetkilendirme için başlangıç noktasıdır ve ek filtre ile ifade tabanlı yetkilendirme kontrolleriyle birlikte kullanılmalıdır.
Kullanım alanı dikkatlice değerlendirilmeden tek başına kullanılmamalıdır.
Data Connect, Firebase CLI'dan firebase deploy kullanarak sunucuya dağıtım yaptığınızda bağlayıcı kodunuzu analiz ederek yetkilendirme stratejinizi denetlemenize yardımcı olur. Kod tabanınızı incelemek için bu denetimden yararlanabilirsiniz.
Bağlayıcılarınızı dağıttığınızda KSA, bağlayıcınızdaki mevcut, değiştirilmiş ve yeni işlem kodu için değerlendirmeler oluşturur.
Değiştirilen ve yeni işlemler için CLI, yeni işlemlerinizde belirli erişim düzeylerini kullandığınızda veya mevcut işlemleri bu erişim düzeylerini kullanacak şekilde değiştirdiğinizde uyarılar verir ve onayınızı ister.
Uyarılar ve istemler her zaman şu durumlarda gösterilir:
PUBLIC
Ayrıca, auth.uid kullanarak filtrelerle artırmadığınızda aşağıdaki erişim düzeylerinde uyarılar ve istemler gösterilir:
USERUSER_ANONUSER_EMAIL_VERIFIED
@auth(insecureReason:) bağımsız değişkeniyle güvenli olmayan işlem uyarılarını engelleme
Çoğu durumda, PUBLIC ve USER* erişim düzeylerini kullanmanın tamamen uygun olduğu sonucuna varırsınız.
Bağlayıcınız çok sayıda işlem içerdiğinde, normalde uyarıyı tetikleyecek ancak doğru erişim düzeyine sahip olduğunuzu bildiğiniz işlemleri atlayan daha net ve daha alakalı bir güvenlik denetimi çıktısı isteyebilirsiniz.
@auth(insecureReason:) ile bu tür işlemler için uyarıları devre dışı bırakabilirsiniz.
Örneğin:
query listItem @auth(level: PUBLIC, insecureReason: "This operation is safe to expose to the public.")
{
items {
id name
}
}
Uygulama onayı için Firebase App Check kullanma
Kimlik doğrulama ve yetkilendirme, Data Connectgüvenliğin kritik bileşenleridir. Kimlik doğrulama ve yetkilendirme, uygulama onayıyla birlikte çok güçlü bir güvenlik çözümü sunar.
Firebase App Check aracılığıyla onaylama sayesinde, uygulamanızı çalıştıran cihazlar, Data Connect işlemlerinin gerçek uygulamanızdan, isteklerin ise gerçek ve kurcalanmamış bir cihazdan geldiğini onaylayan bir uygulama veya cihaz onaylama sağlayıcısı kullanır. Bu onay, uygulamanızın Data Connect'ya yaptığı her isteğe eklenir.
App Check için Data Connect özelliğini nasıl etkinleştireceğinizi ve istemci SDK'sını uygulamanıza nasıl ekleyeceğinizi öğrenmek için App Check genel bakışına göz atın.
@auth(level) yönergesi için kimlik doğrulama düzeyleri
Aşağıdaki tabloda tüm standart erişim düzeyleri ve bunların CEL karşılıkları listelenmiştir. Kimlik doğrulama düzeyleri genişten dara doğru sıralanır. Her düzey, aşağıdaki düzeylerle eşleşen tüm kullanıcıları kapsar.
| Seviye | Tanım |
|---|---|
PUBLIC |
İşlem, kimlik doğrulama yapılarak veya yapılmadan herkes tarafından yürütülebilir.
Dikkat edilmesi gerekenler: Veriler herhangi bir kullanıcı tarafından okunabilir veya değiştirilebilir. Firebase, ürün veya medya listelemeleri gibi herkese açık olarak göz atılabilen veriler için bu yetkilendirme düzeyini önerir. En iyi uygulama örneklerine ve alternatiflere göz atın. @auth(expr: "true")
@auth filtreleri ve ifadeleri bu erişim düzeyiyle birlikte kullanılamaz. Bu tür ifadeler 400 hatalı istek hatasıyla başarısız olur.
|
USER_ANON |
Firebase Authentication ile anonim olarak giriş yapanlar da dahil olmak üzere tanımlanan tüm kullanıcılar sorgu veya mutasyon gerçekleştirmeye yetkilidir.
Not: USER_ANON, USER öğesinin üst kümesidir.
Dikkat edilmesi gerekenler: Bu yetkilendirme düzeyi için sorgularınızı ve mutasyonlarınızı dikkatli bir şekilde tasarlamanız gerektiğini unutmayın. Bu düzey, kullanıcının Authentication ile anonim olarak oturum açmasına (otomatik oturum açma yalnızca kullanıcı cihazına bağlıdır) olanak tanır ve verilerin kullanıcıya ait olup olmadığı gibi diğer kontrolleri kendi başına gerçekleştirmez. En iyi uygulama örneklerini ve alternatiflerini inceleyin. Authentication anonim giriş akışları uid yayınladığından, USER_ANON düzeyi @auth(expr: "auth.uid != nil") ile eşdeğerdir.
|
USER |
Firebase Authentication ile giriş yapan tüm kullanıcılar, anonim giriş yapan kullanıcılar hariç sorgu veya mutasyon gerçekleştirmek için yetkilidir.
Dikkat edilmesi gerekenler: Bu yetkilendirme düzeyi için sorgularınızı ve mutasyonlarınızı dikkatli bir şekilde tasarlamanız gerektiğini unutmayın. Bu düzeyde yalnızca kullanıcının Authentication ile oturum açtığı kontrol edilir. Verilerin kullanıcıya ait olup olmadığı gibi başka kontroller yapılmaz. En iyi uygulama örneklerine ve alternatiflere bakın. @auth(expr: "auth.uid != nil &&
auth.token.firebase.sign_in_provider != 'anonymous'")" etiketine eş değer
|
USER_EMAIL_VERIFIED |
Doğrulanmış bir e-posta adresiyle Firebase Authentication üzerinden giriş yapan tüm kullanıcılar sorgu veya mutasyon gerçekleştirmeye yetkilidir.
Dikkat edilmesi gerekenler: E-posta doğrulaması Authentication kullanılarak yapıldığından daha sağlam bir Authentication yöntemine dayanır. Bu nedenle, bu seviye USER veya USER_ANON'ya kıyasla ek güvenlik sağlar. Bu düzey yalnızca kullanıcının doğrulanmış bir e-posta adresiyle Authentication ile oturum açtığını kontrol eder ve verilerin kullanıcıya ait olup olmadığı gibi diğer kontrolleri kendi başına gerçekleştirmez. En iyi uygulama örneklerine ve alternatiflere göz atın.
@auth(expr: "auth.uid != nil &&
auth.token.email_verified")" etiketine eş değer |
NO_ACCESS |
Bu işlem, Admin SDK bağlamı dışında yürütülemez.
@auth(expr: "false") etiketine eş değer |
@auth(expr) için CEL Referansı
Bu kılavuzun başka yerlerindeki örneklerde gösterildiği gibi, Data Connect için yetkilendirmeyi kontrol etmek üzere @auth(expr:) ve @check yönergelerini kullanarak Common Expression Language (CEL) içinde tanımlanan ifadeleri kullanabilirsiniz ve kullanmanız gerekir.
Bu bölümde, bu yönergeler için ifadeler oluşturmayla ilgili CEL söz dizimi ele alınmaktadır.
CEL ile ilgili tüm referans bilgileri CEL spesifikasyonunda verilmiştir.
Sorgularda ve mutasyonlarda iletilen test değişkenleri
@auth(expr) söz dizimi, sorgulardaki ve mutasyonlardaki değişkenlere erişip bunları test etmenize olanak tanır.
Örneğin, vars.status kullanarak $status gibi bir işlem değişkeni ekleyebilirsiniz.
mutation Update($id: UUID!, $status: Any) @auth(expr: "has(vars.status)")
İfadelerde kullanılabilen veriler: request, response, this
Verileri şu amaçlarla kullanırsınız:
@auth(expr:)ve@check(expr:)yönergelerinde CEL ifadeleriyle değerlendirme- Sunucu ifadeleri kullanılarak atama,
<field>_expr.
Hem @auth(expr:) hem de @check(expr:) CEL ifadeleri aşağıdakileri değerlendirebilir:
request.operationNamevars(request.variablesiçin diğer ad)auth(request.authiçin diğer ad)
Değişimlerde aşağıdakilerin içeriklerine erişebilir ve bunları atayabilirsiniz:
response(çok adımlı mantıktaki kısmi sonuçları kontrol etmek için)
Ayrıca, @check(expr:) ifadeleri şunları değerlendirebilir:
this(geçerli alanın değeri)response(çok adımlı mantıktaki kısmi sonuçları kontrol etmek için)
The request.operationName bağlaması
request.operarationName bağlaması, işlem türünü (sorgu veya mutasyon) depolar.
vars bağlaması (request.vars)
vars bağlaması, ifadelerinizin sorgunuzda veya mutasyonunuzda iletilen tüm değişkenlere erişmesine olanak tanır.
vars.<variablename> ifadesini, tam nitelikli request.variables.<variablename> için takma ad olarak kullanabilirsiniz:
# The following are equivalent
mutation StringType($v: String!) @auth(expr: "vars.v == 'hello'")
mutation StringType($v: String!) @auth(expr: "request.variables.v == 'hello'")
auth bağlama (request.auth)
Authentication, verilerinize erişim isteğinde bulunan kullanıcıları tanımlar ve bu bilgileri, ifadelerinizde kullanabileceğiniz bir bağlama olarak sağlar.
Filtrelerinizde ve ifadelerinizde auth yerine request.auth takma adını kullanabilirsiniz.
Yetkilendirme bağlaması aşağıdaki bilgileri içerir:
uid: İstekte bulunan kullanıcıya atanan benzersiz kullanıcı kimliği.token: Authentication tarafından toplanan değerlerin haritası.
auth.token içeriği hakkında daha fazla bilgi için Kimlik doğrulama jetonlarındaki veriler başlıklı makaleyi inceleyin.
response bağlaması
response bağlaması, bir sorguya veya mutasyona yanıt olarak sunucu tarafından veriler oluşturulurken oluşturulan verileri içerir.
İşlem devam ederken her adım başarıyla tamamlandıkça response, başarıyla tamamlanan adımlardan gelen yanıt verilerini içerir.
response bağlama, ilişkili işlemin şekline göre yapılandırılır. Bu şekil, iç içe yerleştirilmiş (birden fazla) alan ve (varsa) yerleştirilmiş sorgular içerir.
Yerleştirilmiş sorgu yanıtı verilerine eriştiğinizde alanların, yerleştirilmiş sorguda istenen verilere bağlı olarak herhangi bir veri türünü içerebileceğini unutmayın. _insert ve _delete gibi mutasyon alanları tarafından döndürülen verilere eriştiğinizde bu veriler UUID anahtarları, silme sayısı ve boş değerler içerebilir (bkz. mutasyon referansı).
Örneğin:
- Yerleştirilmiş bir sorgu içeren bir mutasyonda,
responsebağlama,response.query.<fieldName>.<fieldName>....konumunda arama verileri içerir. Bu durumda,response.query.todoListveresponse.query.todoList.priority.
mutation CheckTodoPriority(
$uniqueListName: String!
) {
# This query is identified as `response.query`
query @check(expr: "response.query.todoList.priority == 'high'", message: "This list is not for high priority items!") {
# This field is identified as `response.query.todoList`
todoList(where: { name: $uniqueListName }) {
# This field is identified as `response.query.todoList.priority`
priority
}
}
}
- Çok adımlı bir mutasyonda (ör. birden fazla
_insertalanı içeren)responsebağlaması,response.<fieldName>.<fieldName>....konumunda kısmi veriler içerir. Bu örnekteresponse.todoList_insert.id.
mutation CreateTodoListWithFirstItem(
$listName: String!,
$itemContent: String!
) @transaction {
# Step 1
todoList_insert(data: {
id_expr: "uuidV4()",
name: $listName,
})
# Step 2:
todo_insert(data: {
listId_expr: "response.todoList_insert.id" # <-- Grab the newly generated ID from the partial response so far.
content: $itemContent,
})
}
this bağlaması
this bağlaması, @check yönergesinin eklendiği alan olarak değerlendirilir. Temel bir durumda, tek değerli sorgu sonuçlarını değerlendirebilirsiniz.
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
})
}
Döndürülen alan, herhangi bir üst öğe liste olduğu için birden çok kez gerçekleşirse her oluşum, her değere bağlı this ile test edilir.
Belirli bir yolda, bir üst öğe null veya [] ise alana ulaşılamaz ve bu yol için CEL değerlendirmesi atlanır. Başka bir deyişle, değerlendirme yalnızca this null veya null olmayan bir değer olduğunda yapılır ancak hiçbir zaman undefined olduğunda yapılmaz.
Alan kendisi bir liste veya nesne olduğunda this, aşağıdaki örnekte gösterildiği gibi aynı yapıyı (nesneler söz konusu olduğunda seçilen tüm alt öğeler dahil) izler.
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
})
}
Karmaşık ifade söz dizimi
&& ve || operatörleriyle birleştirerek daha karmaşık ifadeler yazabilirsiniz.
mutation UpsertUser($username: String!) @auth(expr: "(auth != null) && (vars.username == 'joe')")
Aşağıdaki bölümde, kullanılabilen tüm operatörler açıklanmaktadır.
Operatörler ve operatör önceliği
Operatörler ve öncelik sırası hakkında bilgi edinmek için aşağıdaki tabloyu kullanın.
Rastgele ifadeler a ve b, bir alan f ve bir dizin i verildiğinde.
| Operatör | Açıklama | Birleşme özelliği |
|---|---|---|
a[i] a() a.f |
Dizin, arama, alan erişimi | soldan sağa |
!a -a |
Tekli olumsuzlama | sağdan sola |
a/b a%b a*b |
Çarpma operatörleri | soldan sağa |
a+b a-b |
Toplama operatörleri | soldan sağa |
a>b a>=b a<b a<=b |
İlişkisel operatörler | soldan sağa |
a in b |
Listede veya haritada yer alma | soldan sağa |
type(a) == t |
Tür karşılaştırması. Burada t; bool, int, float, number, string, list, map, timestamp veya duration olabilir. |
soldan sağa |
a==b a!=b |
Karşılaştırma operatörleri | soldan sağa |
a && b |
Koşullu VE | soldan sağa |
a || b |
Koşullu VEYA | soldan sağa |
a ? true_value : false_value |
Üçlü ifade | soldan sağa |
Kimlik doğrulama jetonlarındaki veriler
auth.token nesnesi aşağıdaki değerleri içerebilir:
| Alan | Açıklama |
|---|---|
email |
Hesapla ilişkili e-posta adresi (varsa). |
email_verified |
Kullanıcı, email adresine erişimi olduğunu doğruladıysa true. Bazı sağlayıcılar, sahip oldukları e-posta adreslerini otomatik olarak doğrular. |
phone_number |
Hesapla ilişkili telefon numarası (varsa). |
name |
Ayarlanmışsa kullanıcının görünen adı. |
sub |
Kullanıcının Firebase UID'si. Bu, proje içinde benzersizdir. |
firebase.identities |
Bu kullanıcı hesabıyla ilişkili tüm kimliklerin sözlüğü. Sözlüğün anahtarları şunlardan biri olabilir: email, phone, google.com, facebook.com, github.com, twitter.com. Sözlüğün değerleri, hesapla ilişkili her kimlik sağlayıcı için benzersiz tanımlayıcı dizileridir. Örneğin, auth.token.firebase.identities["google.com"][0], hesapla ilişkili ilk Google kullanıcı kimliğini içerir. |
firebase.sign_in_provider |
Bu jetonu almak için kullanılan oturum açma hizmet sağlayıcısı. Şu dizelerden biri olabilir: custom, password, phone, anonymous, google.com, facebook.com, github.com, twitter.com. |
firebase.tenant |
Hesapla ilişkili tenantId (varsa). Örneğin, tenant2-m6tyz |
JWT kimlik jetonlarındaki ek alanlar
Ayrıca aşağıdaki auth.token alanlarına da erişebilirsiniz:
| Özel Jeton Talepleri | ||
|---|---|---|
alg |
Algoritma | "RS256" |
iss |
Düzenleyen | Projenizin hizmet hesabı e-posta adresi |
sub |
Konu | Projenizin hizmet hesabı e-posta adresi |
aud |
Kitle | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat |
Yayınlanma zamanı | UNIX sıfır zamanından itibaren saniye cinsinden geçerli saat |
exp |
Geçerlilik süresi |
Jetonun geçerliliğinin sona erdiği zaman (UNIX sıfır zamanından itibaren saniye cinsinden). iat tarihinden en fazla 3.600 saniye sonra olabilir.
Not: Bu ayar yalnızca özel jetonun kendisinin sona erme zamanını kontrol eder. Ancak signInWithCustomToken() kullanarak bir kullanıcının oturumunu açtığınızda, oturumu geçersiz kılınana veya kullanıcı oturumu kapatana kadar cihazda oturum açık kalır.
|
<claims> (isteğe bağlı) |
İfadelerde auth.token (veya request.auth.token) üzerinden erişilebilen, jetona dahil edilecek isteğe bağlı özel talepler. Örneğin, özel bir talep oluşturursanız adminClaim, bu talebe auth.token.adminClaim ile erişebilirsiniz.
|
|
Sırada ne var?
- Firebase Data Connect, ayrıcalıklı ortamlardan sorgu ve mutasyon işlemleri yapmanıza olanak tanıyan bir Yönetici SDK'sı sağlar.
- Hizmetleri ve veritabanlarını yönetme kılavuzundan IAM güvenliği hakkında bilgi edinin.