Как заблокировать базу данных Firebase любому пользователю из определенного (электронной почты) домена?
У меня есть небольшой персональный Firebase webapp, который использует базу данных Firebase. Я хочу защитить (заблокировать) это приложение для любого пользователя из одного конкретного домена. Я хочу выполнить проверку подлинности с помощью Google. Я не понимаю, как настроить правила, чтобы сказать: "Только пользователи из одного конкретного домена (скажем @foobar.com
) могут читать и записывать в эту базу данных".
(Часть проблемы, которую я вижу: трудно загружать базу данных с достаточной информацией, чтобы сделать эту работу использования. Мне нужно знать адрес электронной почты пользователя во время проверки подлинности, но auth
объект не содержит электронная почта. Кажется, проблема с куриным яйцом, потому что мне нужно написать правила Firebase, которые относятся к данным в базе данных, но эти данные еще не существуют, потому что мой пользователь не может писать в базу данных.)
Если auth
имел электронную почту, я мог бы легко писать правила.
Спасибо заранее!
Ответы
Ответ 1
Если вы используете новую Firebase, теперь это возможно, так как email
доступен в правилах безопасности.
В правилах безопасности вы можете получить доступ как к адресу электронной почты, так и к проверке, что делает возможными некоторые возможные варианты использования. С этими правилами, например, только аутентифицированный, проверенный пользователь Gmail может написать свой профиль:
{
"rules": {
".read": "auth != null",
"gmailUsers": {
"$uid": {
".write": "auth.token.email_verified == true &&
auth.token.email.matches(/.*@gmail.com$/)"
}
}
}
}
Вы можете ввести эти правила в Firebase Database console вашего проекта.
Ответ 2
ПРЕДУПРЕЖДЕНИЕ: не доверяйте этому ответу. Только здесь для обсуждения.
TL;DR: Я не думаю, что это возможно, без запуска вашего собственного сервера.
Здесь моя попытка:
{
"rules": {
".read": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')",
".write": "auth.provider === 'google' && root.child('users').child(auth.uid).child('email').val().endsWith('@foobar.com')",
"users": {
"$user_id": {
".write": "auth.provider === 'google' && $user_id === auth.uid && newData.child('email').val().endsWith('@foobar.com')"
}
}
}
}
Я считаю, что выше сказанное говорит "только разрешить людям создавать нового пользователя, если они аутентифицированы Google, пытаются записать в базу данных node для themselve ($user_id === auth.uid
), а их адрес электронной почты заканчивается на foobar.com".
Однако была отмечена проблема: любой веб-клиент может легко изменить свою электронную почту (используя консоль dev) до отправки сообщения в Firebase. Поэтому мы не можем доверять данным пользовательской записи при их хранении в Firebase.
Я думаю, что единственное, на что мы можем доверять, - это объект auth
в правилах. Этот объект auth
заполняется бэкэндом Firebase. И, к сожалению, объект auth
не включает адрес электронной почты.
Для записи я вставляю своего пользователя таким образом:
function authDataCallback(authData) {
if (authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider + " and has displayName " + authData.google.displayName);
// save the user profile into the database so we can list users,
// use them in Security and Firebase Rules, and show profiles
ref.child("users").child(authData.uid).set({
provider: authData.provider,
name: getName(authData),
email: authData.google.email
});
Как вы могли бы себе представить, определенный пользователь мог бы перезаписать здесь значение email
(например, с помощью DevTools).
Ответ 3
Вот код, отлично работающий с моей базой данных, я установил правило, что только электронные письма моей компании могут читать и записывать данные моей базы данных firebase.
{
"rules": {
".read": "auth.token.email.matches(/.*@yourcompany.com$/)",
".write": "auth.token.email.matches(/.*@yourcompany.com$/)"
}
}
Ответ 4
Код, который работает для меня.
export class AuthenticationService {
user: Observable<firebase.User>;
constructor(public afAuth: AngularFireAuth) {
this.user = afAuth.authState;
}
login(){
var provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({'hd': '<your domain>'});
this.afAuth.auth.signInWithPopup(provider)
.then(response => {
let token = response.credential.accessToken;
//Your code. Token is now available.
})
}
}
Ответ 5
Для тех, кто действительно не хочет, чтобы в систему входили непроверенные учетные записи. Может быть, грязная, но очень эффективная.
Это мой обходной путь (приложение Angular):
this.userService.login(this.email.value, this.password.value).then(data => {
if (data.user.emailVerified === true) {
//user is allowed
} else {
//user not allowed, log them out immediatly
this.userService.logout();
}
}).catch(error => console.log(error));