javascript - Firebase apiKey'i halka açmak güvenli mi?
Firebase Web-Uygulama kılavuzu, Firebase'i başlatmak için verilen apiKey'i Html'ime koymam gerektiğini belirtiyor:
// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
firebase.initializeApp(config);
</script>
Böyle yaparak, apiKey her ziyaretçiye açık hale gelir.
O anahtarın amacı nedir ve gerçekten herkese açık olması mı amaçlanmış?
Cevap #1
API anahtarlarını kullanma ve yönetme hakkında Firebase belgelerinden:
Firebase ile ilgili API'ler, API anahtarlarını yalnızca Firebase projesini veya uygulamasını tanımlamak için kullanır, API'yi çağırmak için yetkilendirme amacıyla değil (diğer bazı API'lerde olduğu gibi).
Yani yapılandırma snippet'inizdeki apiKey sadece Firebase projenizi Google sunucularında tanımlar, ancak tek başına ona erişim sağlamaz. Birinin bunu bilmesi bir güvenlik riski oluşturmaz. Aslında, birinin Firebase projenizle etkileşimde bulunabilmesi için bunu bilmesi gereklidir. Aynı yapılandırma verileri, Firebase'i backend olarak kullanan her iOS ve Android uygulamasında da bulunmaktadır.
Bu anlamda, aynı kod parçasında projenizle ilişkili arka uç veritabanını tanımlayan veritabanı URL'sine çok benzer: https://<app-id>.firebaseio.com. Bunun neden bir güvenlik riski olmadığını açıklayan bu soruya bakın: Firebase veri değiştirmeyi nasıl kısıtlayabilirsiniz?, ayrıca yalnızca yetkili kullanıcıların arka uç hizmetlerine erişebilmesini sağlamak için Firebase’in sunucu tarafı güvenlik kurallarının kullanımı dahil.
Firebase arka uç hizmetlerinize tüm veri erişimini nasıl yetkilendirileceğini öğrenmek istiyorsanız, Firebase güvenlik kurallarıyla ilgili dökümantasyonu okuyun. Bu kurallar, dosya depolama ve veritabanı erişimini kontrol eder ve Firebase sunucularında uygulanır. Yani, sizin kodunuz olsun veya başkasının sizin yapılandırma verilerinizi kullanan kodu olsun, yalnızca güvenlik kurallarının izin verdiği şekilde hareket edebilir.
Firebase'in bu yapılandırma verilerini ne için kullandığı ve hangileri için kotayı ayarlayabileceğiniz hakkında daha uzun bir açıklama için, API anahtarlarının kullanımı ve yönetimi ile ilgili belgelere bakın.
Bu yapılandırma verilerini sürüm kontrolüne göndermeyi azaltmak isterseniz, Firebase Hosting'in SDK otomatik yapılandırmasını kullanmayı düşünebilirsiniz. Anahtarlar yine aynı formatta tarayıcıya ulaşacak olsa da, artık kodunuza sabitlenmiş olmayacaklar.
Güncelleme (Mayıs 2021): Firebase App Check adlı yeni özellik sayesinde, artık Firebase projenizdeki backend hizmetlerine erişimi yalnızca o özel projede kayıtlı iOS, Android ve Web uygulamalarından gelenlerle sınırlamak gerçekten mümkün.
Bunu, yukarıda açıklanan kullanıcı kimlik doğrulamasına dayalı güvenlikle birleştirmek isteyeceksiniz, böylece uygulamanızı gerçekten kullanan kötüye kullanan kullanıcılara karşı bir başka kalkanınız olur.
App Check'i güvenlik kurallarıyla birleştirerek, kötüye kullanıma karşı geniş kapsamlı korumaya sahip olurken, her kullanıcının hangi verilere erişebileceği üzerinde hassas bir kontrol elde edebilir ve yine de istemci tarafı uygulama kodunuzdan veritabanına doğrudan erişime izin verebilirsiniz.
Cevap #2
Burada prufrofro ve Frank van Puffelen’in cevaplarını temel alarak, kazımayı engellemeyen ama API anahtarınızı kullanmayı biraz daha zorlaştırabilecek bu kurulumu bir araya getirdim.
Uyarı: Bu yöntemle bile verilerinizi almak için, örneğin Chrome'da JS konsolunu açıp şunu yazabilirsiniz:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Verilerinizi yalnızca veritabanı güvenlik kuralları koruyabilir.
Yine de, üretim API anahtarımın kullanımını alan adımla sınırladım, şöyle:
- https://console.developers.google.com/apis
- Firebase projenizi seçin
- Kimlik Bilgileri
- API anahtarları altında, Tarayıcı anahtarınızı seçin. Şöyle görünmelidir: "Tarayıcı anahtarı (Google Servisi tarafından otomatik oluşturuldu)"
- "Bu HTTP referrer'larından (web sitelerden) gelen istekleri kabul et" bölümüne uygulamanızın URL'sini ekleyin (örnek:
projectname.firebaseapp.com/*)
Artık uygulama sadece bu belirli alan adı üzerinde çalışacak. Bu yüzden localhost geliştirmesi için özel olacak başka bir API Anahtarı oluşturdum.
- Oluştur kimlik bilgilerini tıklayın > API Anahtarı
Varsayılan olarak, Emmanuel Campos’un belirttiği gibi, Firebase yalnızca localhost ve Firebase barındırma alan adınızı beyaz listeye alır.
Yanlışlıkla yanlış API anahtarını yayınlamadığımı garanti etmek için, üretimde daha kısıtlı olanı otomatik olarak kullanmak için aşağıdaki yöntemlerden birini kullanıyorum.
Create-React-App için Kurulum
/env.development içinde:
REACT_APP_API_KEY=###dev-key###
/env.production içinde:
REACT_APP_API_KEY=###public-key###
/src/index.js içinde
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
// ...
};
Cevap #3
Güvenlik/konfigürasyon anahtarlarını istemciye açıklamaya ikna olmadım. Bunu güvenli olarak adlandırmazdım, bunu ilk günden biri tüm özel bilgileri çalabileceği için değil, birinin aşırı istek yapabileceği, kotanızı tüketebileceği ve Google'a çok fazla borçlanmanıza yol açabileceği için.
İnsanları olmamaları gereken yerlere erişmekten kısıtlamaktan, DOS saldırılarına kadar birçok kavramı düşünmeniz gerekiyor.
Müşterinin önce web sunucunuza gelmesini daha çok tercih ediyorum, oraya istediğiniz ilk el firewall, captcha, cloudflare, özel güvenlik önlemlerini koyabilirsiniz, müşteriye ve sunucuya ya da sunucu ile firebase arasında ve hazır olursunuz. En azından şüpheli aktivitelerin firebase'e ulaşmadan önce durmasını sağlayabilirsiniz. Çok daha fazla esnekliğe sahip olursunuz.
İç kullanımlar için istemci tabanlı yapılandırma kullanmanın yalnızca bir iyi kullanım senaryosunu görebiliyorum. Örneğin, dahili bir alan adınız var ve dışarıdan kimsenin oraya erişemeyeceğinden çok emin olduğunuzda, ortamı tarayıcı -> Firebase türü olarak kurabilirsiniz.
Cevap #4
API anahtarının açığa çıkması, kullanıcı/şifre ile kayıt etkinleştirildiğinde bir güvenlik açığı oluşturur. API anahtarını alan ve herkesin yeni bir kullanıcı hesabı oluşturmasına izin veren açık bir API uç noktası vardır. Daha sonra bu yeni hesabı kullanarak Firebase Auth ile korunan uygulamanıza giriş yapabilir veya SDK'yı kullanıcı/şifre ile kimlik doğrulamak ve sorgular çalıştırmak için kullanabilirler.
Bunu Google'a bildirdim ama onlar bunun kasıtlı olarak çalıştığını söylüyor.
Kullanıcı/parola hesaplarını devre dışı bırakamıyorsanız şunları yapmalısınız: Yeni kullanıcılar oluşturulduğunda otomatik olarak devre dışı bırakmak için bir bulut fonksiyonu oluşturun ve erişimlerini yönetmek için yeni bir veritabanı girişi oluşturun.
Örnek: MyUsers/{userId}/Access: 0
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Kurallarınızı, erişimi > 1 olan kullanıcılar için yalnızca okuma iznini verecek şekilde güncelleyin.
Dinleyici işlevi hesabı yeterince hızlı devre dışı bırakmazsa, okuma kuralları onların herhangi bir veriyi okumasını engelleyecektir.
Cevap #5
API ANAHTARLARININ AÇIK OLMASI BİR GÜVENLİK RİSKİ DEĞİLDİR AMA HERKES KİMLİK BİLGİLERİNİZİ KENDİ SİTELERİNE KOYABİLİR.
Açık API anahtarları, Firebase üzerinde çok fazla kaynak kullanabilecek saldırılara yol açar ve bu kesinlikle paranıza mal olur.
Firebase proje anahtarlarınızı her zaman alan adlarına/IP'lere kısıtlayabilirsiniz.
https://console.cloud.google.com/apis/credentials/key
Proje kimliğinizi ve anahtarınızı seçin ve bunu Android/iOS/web uygulamanıza sınırlayın.
Cevap #6
Veritabanı kuralları doğru bir şekilde yazıldığında, verilerinizi korumak için yeterli olacağını düşünüyorum. Ayrıca, veritabanınızı buna göre yapılandırmak için takip edilebilecek yönergeler vardır. Örneğin, kullanıcıların altına bir UID düğümü oluşturmak ve tüm bilgileri bunun altına yerleştirmek. Bundan sonra, aşağıdaki gibi basit bir veritabanı kuralı uygulamanız gerekecek.
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
Hiçbir başka kullanıcı diğer kullanıcıların verilerini okuyamayacak, ayrıca alan politikası diğer alanlardan gelen istekleri kısıtlayacaktır. Bu konuda daha fazla bilgiyi Firebase Güvenlik kurallarında okuyabilirsiniz
Cevap #7
Orijinal soru yanıtlanmışken (API anahtarının açığa çıkabileceği - verilerin korunmasının DB kurallarından ayarlanması gerektiği), ben de DB'nin belirli bölümlerine erişimi sınırlamanın bir çözümünü arıyordum. Bu ve olanaklar hakkında yaptığım bazı kişisel araştırmalardan sonra, yetkisiz kullanıcılar için veri kullanımını sınırlamak üzere biraz farklı bir yaklaşım geliştirdim:
Kullanıcılarımı DB'me de kaydediyorum, aynı uid altında (ve profil verilerini de oraya kaydediyorum). Yani DB kurallarını şöyle ayarlıyorum:
".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"
Bu şekilde, veritabanına yalnızca daha önce kaydedilmiş bir kullanıcı yeni kullanıcı ekleyebilir, bu nedenle hesabı olmayan hiç kimse veritabanında işlem yapamaz.
Ayrıca yeni kullanıcı eklemek, sadece kullanıcının özel bir rolü varsa ve yalnızca yönetici tarafından veya o kullanıcı tarafından düzenlenebilir (şöyle bir şey):
"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...
