У меня есть эти правила Firestore
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isValidUser(userId) {
return request.auth.uid == userId && request.auth.role == 'user';
}
function isLoggedIn() {
return request.auth.uid != null;
}
match /users/{id}/{document=**}{
allow create, read, update, delete: if isLoggedIn() && isValidUser(id)
}
}
}
И я создаю действительный токен Firebase через облачную функцию Google и отправляю его тому, кто успешно войдет в систему, вот так
const firebaseToken = await admin.auth().createCustomToken(uuid);
return res.status(200).json({status: true, token: firebaseToken, id: uuid});
Теперь переходим к Flutter, в main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Firebase.apps.isEmpty) {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
}
Instance.registerTypes(onRegister: (getIt) {
getIt.registerLazySingleton(() => BusinessDevice());
});
runApp(
Phoenix(
child: ProviderScope(
child: MyApp(),
),
),
);
}
И в login.dart
final headers = {'Content-Type': 'application/json'};
final request = http.Request(
'POST', Uri.parse(ENDPOINTS.FIREBASE_AUTH));
request.body = json.encode({
"email": userCtrl.text.trim(),
"password": passCtrl.text.trim(),
"role": "user"
});
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
final body = await response.stream.bytesToString();
final jsonResponse = json.decode(body);
if (response.statusCode == 200) {
// Authentication succeeded, store the token and navigate to the dashboard
final token = jsonResponse['token'];
final userid = jsonResponse['id'];
await FirebaseAuth.instance.signInWithCustomToken(token);
DocumentSnapshot<Map<String, dynamic>> snap = await FirebaseFirestore.instance
.collection('users').doc(userid).get();
}
Я получаю эту ошибку, когда приложение пытается прочитать из Firestore
FirebaseException ([cloud_firestore/permission-denied] The caller does not have permission to execute the specified operation.)
Мы используем signInWithCustomToken()
, потому что у нас есть система аутентификации по имени пользователя и паролю, которая изначально не поддерживается Firebase, поэтому мне пришлось написать облачную функцию Google, чтобы справиться с этим.
Я ищу решение, которое потребует наименьшего количества изменений в кодовой базе. Потому что мы сталкиваемся с одной и той же проблемой в 3 разных больших приложениях в производстве, а Firestore используется на всех страницах. Я хочу работать над защитой приложений, а не над их рефакторингом.
@anothermh Хороший вопрос, но мой вопрос о флаттере: если я уберу флаттер, то nodejs и эксперт по облачным вычислениям Google прочитают этот вопрос и потратят свое время. Эксперты Flutter могут даже не заметить этого, поскольку в названии есть nodejs — и потому что они могут не проверять теги. Я использую SO в течение очень долгого времени и пробовал много типов, добавление тегов в заголовок очень эффективно
Видимо, вы не читали мой комментарий или статью по ссылке. Не вставляйте теги в заголовок.
Это помогает сначала выяснить, какая именно часть вашего кода не работает. Например, если вы временно закомментируете эту часть чека request.auth.role == 'user'
, она тогда будет работать? Если это так, похоже, что роль отсутствует в токене.
Похоже, что ваше role
является пользовательским утверждением, и в этом случае оно существует в свойстве token
в ваших правилах. Так:
return request.auth.uid == userId && request.auth.token.role == 'user'
// 👆
Также см:
Чувак, ты легенда, я не могу вспомнить, сколько раз ты мне помогал, и такая интуиция супер впечатляюще, чувак, я люблю это, это просто легендарный, вечно благодарный человек.