Firebase Storage Exception when fetching downloadUrl [Flutter] - firebase

When trying to use FireBase Cloud Storage to get a video downloadUrl
final storage = FirebaseStorage.instance;
downloadUrl() async {
final downloadUrl =
await storage.ref("User_uploadVideo/videoplayback.mp4").getDownloadURL();
return downloadUrl;
}
An exception is thrown saying Exception: [firebase_storage/unauthenticated] User is unauthenticated. Authenticate and try again.
Even tho I have opened the security rules to public for development.
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write;
}
}
}

Try this:
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if true;
}
}
}
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
...
Also, make sure to have AppCheck disabled.

Related

Unhandled Exception: PlatformException(Error performing get, PERMISSION_DENIED: Missing or insufficient permissions., null)

Whenever the app starts this error comes. i think the error mainly is in the saveUserInfoFirestore function.. i saw that many other people have this same problem cause of their firestore security rules but i tried differenct rules it still shows same error..
final GoogleSignIn gSignIn = GoogleSignIn();
final userReference = Firestore.instance.collection("Users");
void initState(){
super.initState();
pageController=PageController();
gSignIn.onCurrentUserChanged.listen((gSigninAccount) { ControlSingIn(gSigninAccount); },
onError: (gError){
print("Google signin error"+ gError);
});
gSignIn.signInSilently(suppressErrors: false).then((gSigninAccount) { ControlSingIn(gSigninAccount); }).
catchError((onError){
print("Signin silently error"+ onError);
});
}
ControlSingIn(GoogleSignInAccount signInAccount) async{
if(signInAccount != null){
await saveUserInfotoFirestore();
setState(() {
isSignin = true;
});
}else{
setState(() {
isSignin = false;
});
}
}
saveUserInfotoFirestore() async{
final GoogleSignInAccount gCurrentuser = gSignIn.currentUser;
DocumentSnapshot documentSnapshot = await userReference.document(gCurrentuser.id).get();
if(!documentSnapshot.exists){
final username = await Navigator.push(context, MaterialPageRoute(builder: (context)=>CreateAccountPage()));
userReference.document(gCurrentuser.id).setData({
"id": gCurrentuser.id,
"profileName": gCurrentuser.displayName,
"username": username,
"url": gCurrentuser.photoUrl,
"email": gCurrentuser.email,
"bio": "",
"timestamp":timestamp
});
documentSnapshot = await userReference.document(gCurrentuser.id).get();
}
currentUser = User.fromDocument(documentSnapshot);
}
heres the firestore security rule that i am using:
rules_version = '2';
// Allow read/write access on all documents to any user signed in to the application
service cloud.firestore {
match /databases/{database}/documents {
match /messages/{document=**} {
allow read, write: if true;
}
}
}
Your security rules only allow access to a single collection called "messages" using this match:
match /messages/{document=**} {
allow read, write: if true;
}
However, your code is trying to write a different collection called "Users". You are seeing a permission error because your rules don't allow any access at all to that collection. You will have to write another rule to allow enough access to that collection as well.
I strongly suggest fully reviewing the documentation for security rules to understand how best to protect your app.
check with your googleservices.json file if it is in the right location. It should be in your project>android folder> app folder>

PlatformException(Error performing setData, PERMISSION_DENIED: Missing or insufficient permissions., null)

No error in my Dart Code, but I cannot write data to firestore,
i cannot write data to cloud firestore,
no error in my code: but error message comes again and again
Error is as Below::
W/Firestore( 9874): (21.3.0) [Firestore]: Write failed at user/6nattT06v0dfeeb6Rm9ablZuijU2/reports/reports_1: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
E/flutter ( 9874): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: PlatformException(Error performing setData, PERMISSION_DENIED: Missing or insufficient permissions., null)
Code Snippet:
```
abstract class Database {
Future createReport(Map<String, dynamic> reportData);
}
class FirestoreDatabase implements Database{
FirestoreDatabase({#required this.uid}) : assert (uid!=null);
final String uid;
//TODO: to create a report hard coded:
Future createReport(Map<String, dynamic> reportData) async {
final path = 'user/$uid/reports/reports_1';
final documentReference = Firestore.instance.document(path);
await documentReference.setData(reportData);
}
}
void _createReport(BuildContext context) { final database = Provider.of<Database>(context); database.createReport({ 'crime Type' : 'Blogging', 'Description' : 'description needs to be provided', }); }```
```class Report{
Report({#required this.crimeType, #required this.description});
final String crimeType;
final String description;
//TODO: to map data to Firestore
Map<String, dynamic> toMap(){
return{
'CrimeType' : crimeType,
'Description': description,
};
}
}```
Firebase Rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/Reports/{document=**} {
allow read, write; }}}
EDITED!!!:
OLD:
Try changing your Firestore rule to:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{uid}/Reports/{document=**} {
allow read, write: if true;
}
}
}
The only thing that was really changed here is this line:
allow read, write: if true;
If that does not work, try:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
NEW:
My first answer was actually insecure, because using the
if true
allowed anyone with access to your firebase project to have admin rights. Rather use this instead, which only works if the request from the app is authenticated:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Sorry for the late edit, have a great time coding everyone!

Permission denied while configuring firestore in flutter

I am trying to add security rules to my app have firebase firestore feature so the rules are
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
function isSignedIn() {
return request.auth.uid != null;
}
allow read, write: if isSignedIn() && request.auth.uid == resource.data.uid
}
}
}
and this is the function for getting query snapshot
Stream<QuerySnapshot> diarySnapshot(String uid){
return _firestore
.collection(uid)
.where('uid', isEqualTo:uid)
.snapshots();
}
but I am getting an error
[Firestore]: Write failed at 2nVrS92SbOZocu2CJY3Tj68er1n2/rXZAWPxEqhtqwmOrtZfo: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}
One more thing each user would have their own collection named on their id.
EDIT
** DatabaseService.dart**
class DatabaseService{
Firestore _firestore=Firestore.instance;
/*Future<void> configure() async{
final FirebaseApp app=await FirebaseApp.configure(name:'notes',
options: FirebaseOptions(
googleAppID: '1:1051484666895:android:7e879575351f8463b2f77a',
projectID: 'notes-e2864',
gcmSenderID:'1051484666895',
apiKey: 'AIzaSyBrCie0qxxwn0KwSLJ1wwTxnVZ7nLz-QkY'
),
);
_firestore = Firestore(app: app);
}
*/
Future setNewData(String uid,String title,String diary,DateTime dateTime) async{
await _firestore.collection(uid).document().setData({
'title':title,
'diary':diary,
'dateTime':dateTime.toString()
});
}
Stream<QuerySnapshot> diarySnapshot(String uid){
return _firestore
.collection(uid)
.where('uid', isEqualTo:uid)
.snapshots();
}
}
I tried both commented and uncommented code, the commented was being first configured and and then program was run.
ServiceViewModel
class ServiceViewModel extends ChangeNotifier {
final AuthService _authService=AuthService();
final DatabaseService _databaseService=DatabaseService();
String _uid;
/*ServiceViewModel(){
_databaseService.configure();
}*/
void signInWithEmailAndPassword(String email,String password) async {
await _authService.signInWithEmailAndPassword(email, password);
}
void registerInWithEmailAndPassword(String email,String password) async {
await _authService.registerWithEmailAndPassword(email, password);
}
void signInWithGoogle()async {
await _authService.signInWithGoogle();
print('Sign In With Google');
}
void signOut(){
_authService.signOut();
_uid=null;
}
/* void setUid() async{
_uid=await _authService.getCurrentUser();
}*/
void setData(String title, String diary, DateTime dateTime) async{
await _authService.getCurrentUser().then((value) async {
return await _databaseService.setNewData(value.toString(), title, diary, dateTime);
});
}
Stream<QuerySnapshot> getSnapShot(String uid) {
return _databaseService.diarySnapshot(uid);
}
}
resource.data does not exist on create, hence you error.
Try this instead:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
function isSignedIn() {
return request.auth.uid != null;
}
allow create: if isSignedIn() && request.auth.uid == request.resource.data.uid;
allow update: if isSignedIn() && request.auth.uid == resource.data.uid
&& request.auth.uid == request.resource.data.uid;
allow read, delete: if isSignedIn() && request.auth.uid == resource.data.uid
}
}
}
EDIT: special case for update not to get stucked

Firestore Permission denied. Connecting firestore to react native

addPost = async ({ text, localUri }) => {
const remoteUri = await this.uploadPhotoAsync(localUri);
return new Promise((res, rej) => {
this.firestore
.collection("posts")
.add({
text,
uid: this.uid,
timestamp: this.timestamp,
image: remoteUri
})
.then(ref => {
res(ref);
})
.catch(error => {
rej(error);
});
});
};
And
rules_version = '2';
service firebase.storage {
match /posts/{doc} {
allow read, write: if true;
}
}
Above is my react-native code and below it is the firebase rules for my database so far. Still getting
FirebaseError:[code=permission-denied]: Missing or insufficient permissions.
Any help as to how to fix this code or to make my rules more secure? At this point in the code the user has been authenticated.
The rules in the question are for firebase storage, you need to change the rule for firestore to true:
// Allow read/write access to all users under any conditions
// Warning: **NEVER** use this rule set in production; it allows
// anyone to overwrite your entire database.
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
Check here for more information:
https://firebase.google.com/docs/firestore/security/insecure-rules

Flutter and Firestore does not have user information in request

Using flutter, I have installed the firebase-auth and firestore packages and am able to both authenticate with firebase auth and make a call into firestore as long as I don't have any rules around the user.
I have a button that calls _handleEmailSignIn and I do get a valid user back (since they are in the Firebase Auth DB)
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
void _handleEmailSignIn(String email, String password) async {
try {
FirebaseUser user = await _auth.signInWithEmailAndPassword(
email: email, password: password);
print("Email Signed in " + user.uid); // THIS works
} catch (err) {
print("ERROR CAUGHT: " + err.toString());
}
}
I then have another button that calls this function to attempt to add a record into the testing123 collection.
Future<Null> _helloWorld() async {
try {
await Firestore.instance
.collection('testing123')
.document()
.setData(<String, String>{'message': 'Hello world!'});
print('_initRecord2 DONE');
} catch (err) {
print("ERROR CAUGHT: " + err.toString());
}
}
Now this works as long as I don't have any rules around checking the request user. This works...
service cloud.firestore {
match /databases/{database}/documents {
match /testing123auth/{doc} {
allow read, create
}
}
}
This does not which gives PERMISSION_DENIED: Missing or insufficient permissions. when I want to make sure I have the authenticated user I did with _handleEmailSignIn.
service cloud.firestore {
match /databases/{database}/documents {
match /testing123auth/{doc} {
allow read, create: if request.auth != null;
}
}
}
I suspect that the firestore request is not including the firebase user. Am I meant to configure firestore to include the user or is this supposed to be automatic as part of firebase?
One thing to note that's not well documented is that firebase_core is the "Glue" that connects all the services together and when you're using Firebase Authentication and other Firebase services, you need to make sure you're getting instances from the same firebase core app configuration.
final FirebaseAuth _auth = FirebaseAuth.instance;
This way above should not be used if you're using multiple firebase services.
Instead, you should always get FirebaseAuth from FirebaseAuth.fromApp(app) and use this same configuration to get all other Firebase services.
FirebaseApp app = await FirebaseApp.configure(
name: 'MyProject',
options: FirebaseOptions(
googleAppID: Platform.isAndroid ? 'x:xxxxxxxxxxxx:android:xxxxxxxxx' : 'x:xxxxxxxxxxxxxx:ios:xxxxxxxxxxx',
gcmSenderID: 'xxxxxxxxxxxxx',
apiKey: 'xxxxxxxxxxxxxxxxxxxxxxx',
projectID: 'project-id',
bundleID: 'project-bundle',
),
);
FirebaseAuth _auth = FirebaseAuth.fromApp(app);
Firestore _firestore = Firestore(app: app);
FirebaseStorage _storage = FirebaseStorage(app: app, storageBucket: 'gs://myproject.appspot.com');
This insures that all services are using the same app configuration and Firestore will receive authentication data.
There shouldn't be any special configuration needed for the firestore to do this.
This is all you should need.
Modified from Basic Security Rules:
service cloud.firestore {
match /databases/{database}/documents {
match /testing123/{document=**} {
allow read, write: if request.auth.uid != null;
}
}
}
It seems they check if the uid is null rather than the auth itself. Try this out and see if it works. Also, it seemed that your code was inconsistent as the firestore rule had testing123auth and flutter had testing123. I'm not sure if that was intentional.
to check if the user is signed in you should use
request.auth.uid != null
I would have suggested to make the rule like:
service cloud.firestore {
match /databases/{database}/documents {
match /testing123auth/{documents=**} {
allow read, create: if true;
}
}
}
Or, better yet, limit the scope of the user:
service cloud.firestore {
match /databases/{database}/documents {
match /testing123auth/{userId} {
allow read, create:
if (request.auth.uid != null &&
request.auth.uid == userId); // DOCUMENT ID == USERID
} // END RULES FOR USERID DOC
// IF YOU PLAN TO PUT SUBCOLLECTIONS INSIDE DOCUMENT:
match /{documents=**} {
// ALL DOCUMENTS/COLLECTIONS INSIDE THE DOCUMENT
allow read, write:
if (request.auth.uid != null &&
request.auth.uid == userId);
} // END DOCUMENTS=**
} // END USERID DOCUMENT
}
}

Resources