Для моего веб-приложения Firebase требуется доступ администратора, т.е. Пользовательский интерфейс должен показывать несколько вещей только для администраторов (раздел "администратор"). Я придумал нижеследующее как средство авторизации пользовательского интерфейса для отображения раздела администратора только для допустимых администраторов. Мой вопрос, хороший или плохой? Является ли это звуковым средством авторизации?... так много способов сделать это. Этот конкретный способ требует, чтобы я настраивал админы в правилах безопасности (vs в узле/дереве в db/firestore)
Моя идея состоит в том, что если .get()
не удается выполнить из-за несанкционированного доступа, я скажу, что моя логика приложения не является администратором, если .get()
преуспевает в моей логике, показывает разделы "admin". Конечно, "разделы" - это просто скелеты HTML/пустые элементы, заполненные базой данных, поэтому даже если конечный пользователь взломает JS/логику, реальных данных не будет - только пустая структура "админ-раздела".
function isAdmin(){
return new Promise(function(resolve, reject){
var docRef = firebase.firestore().collection("authorize").doc("admin");
docRef.get().then(function(result) {
if (result) {
resolve (true);
}
}).catch(function(error) {
resolve (false);
});
});
}
Правило firestore указывает "админы" по UID.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid == "9mB3UxxxxxxxxxxxxxxxxxxCk1";
}
}
}
Вы сохраняете роль каждого пользователя в базе данных, а затем просматриваете его в клиенте для обновления своего пользовательского интерфейса. Раньше это был идиоматический способ в течение длительного времени в базе данных реального времени, и он все еще работает на Firestore.
Единственное, что я бы изменил, это заставить правила читать и /authorize/admin
, а не жестко кодировать UID в них. Таким образом, у вас есть только UID в одном месте, вместо того, чтобы иметь его как в правилах, так и в документе.
Но вы также можете рассмотреть альтернативу: установите индивидуальный запрос для своего администратора, после чего вы сможете читать как на уровне безопасности на стороне сервера (для обеспечения авторизации доступа), так и в интерфейсе (для оптимизации пользовательского интерфейса).
Чтобы настроить пользовательскую заявку, вы используете SDK Firebase Admin. Вы можете сделать это на настраиваемом сервере, в Облачных функциях, но в вашем сценарии может быть проще просто запустить его с вашей машины разработки.
Подробные инструкции: Firebase имеет то, что называется Custom Claims для этой функции, как описано в их контрольном доступе с пользовательскими требованиями и правилами безопасности. В принципе, вы встаете на отдельный сервер узлов, установите Firebase AdminSDK:
npm install firebase-admin --save
Создайте/загрузите закрытый ключ со вкладки "Учетные записи службы" в консоли Firebase и поместите его на свой сервер узла. Затем просто создайте приложение узла голой кости, чтобы назначить пользовательские претензии против каждого UID (пользователя), который вы хотите. Что-то вроде ниже работало для меня:
var admin = require('firebase-admin');
var serviceAccount = require("./the-key-you-generated-and-downloaded.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://xxxxxxxxxxxxxxxxxxxx.firebaseio.com"
});
admin.auth().setCustomUserClaims("whatever-uid-you-want-to-assign-claim-to", {admin: true}).then(() => {
console.log("Custom Claim Added to UID. You can stop this app now.");
});
Это. Теперь вы можете проверить, применяется ли пользовательское требование, выйдя из приложения (если вы ранее вошли в систему) и .onAuthStateChanged
в систему после обновления вашего веб-приложения. .onAuthStateChanged
:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
firebase.auth().currentUser.getIdToken()
.then((idToken) => {
// Parse the ID token.
const payload = JSON.parse(window.atob(idToken.split('.')[1]));
// Confirm the user is an Admin.
if (!!payload['admin']) {
//showAdminUI();
console.log("we ARE an admin");
}
else {
console.log("we ARE NOT an admin");
}
})
.catch((error) => {
console.log(error);
});
}
else {
//USER IS NOT SIGNED IN
}
});