xamarin / GooglePlayServicesComponents

Other
316 stars 147 forks source link

Permissions denied when authenticating to Firebase in Xamarin.Android #178

Open sdiaz-qkt opened 5 years ago

sdiaz-qkt commented 5 years ago

Xamarin.Android Version (eg: 6.0):

Xamarin.Android = 9.1.0.38

Operating System & Version (eg: Mac OSX 10.11):

Windows 10 - Visual Studio Community 2017 15.9.2

Google Play Services Version (eg: 8.4.0):

Xamarin.Firebase.Firestore = 60.1142.1

Describe your Issue:

First, if I initialize my app to Firebase in Xamarin.Android in the same way is done in Xamarin.iOS by letting the application find what it needs in the json file, I get the error "projectID is null", which I found is an issue that is being handle (https://github.com/xamarin/GooglePlayServicesComponents/issues/104). So, to address this error, since I don't know how long until the release of the fix, I initialize the app by telling it where to find the projectId. However this is not enough, since I can't authenticate to the Cloud Firestore due to the following error:

com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions

My rules request that the user id is not null and it must be the same as the document's name, and I need this for security reasons. So just changing the permissions in my rules is not an option. In Xamarin.iOS this is not an issue! I had no problem with authenticating to firestore and accessing my documents.

Steps to Reproduce (with link to sample solution if possible):

  1. Initialize app to firestore :

    FirebaseFirestore db;
    var baseOptions = FirebaseOptions.FromResource(Application.Context);
    var options = new FirebaseOptions.Builder(baseOptions)
                       .SetProjectId(baseOptions.StorageBucket.Split('.')[0])
                       .Build();
    
            var app = FirebaseApp.InitializeApp(Application.Context, options, RandomString(8));
  2. Try to access some document in your database.

Include any relevant Exception Stack traces, build logs, adb logs:

The error I'm facing is:

com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions

as mentioned before.

UPDATE:

This problem appears when my rule is :

service cloud.firestore {
match /databases/{database}/documents {
    match /Users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;
    }
  }

(I failed to explained earlier when this became a serious issue for me, which is this! )

craigmart-in commented 5 years ago

So I was actually having this issue all day yesterday and figured I would try something new this morning and I got something to work!

In my test app, I have a simple security rule setup in Firestore that looks like this:

service cloud.firestore {
match /databases/{database}/documents {
    match /Users/{userId} {
      allow read, write: if request.auth != null;
    }
  }
}

Then in my code, I had to make sure that when I was creating my FirebaseAuth I used the same FirebaseApp object I used to create my database.

var baseOptions = Firebase.FirebaseOptions.FromResource(this);
// This HACK will be not needed, fixed in https://github.com/xamarin/GooglePlayServicesComponents/commit/723ebdc00867a4c70c51ad2d0dcbd36474ce8ff1
var options = new Firebase.FirebaseOptions.Builder(baseOptions)
            .SetProjectId(baseOptions.StorageBucket.Split('.')[0]).Build();
var app = Firebase.FirebaseApp.InitializeApp(this, options, "Firebase");
var auth = FirebaseAuth.GetInstance(app);
var database = FirebaseFirestore.GetInstance(app);

I suspect this workaround isn't needed with the latest version of the this library but I guess they are not updated for Windows on nuget and I wasn't able to figure out how to build them myself.

And for reference, here are the versions of everything:

sdiaz-qkt commented 5 years ago

@DirtyRasa Hello,

Sure, I tried that also and it works for that specific rule. However, my rules look something more like this:

service cloud.firestore {
match /databases/{database}/documents {
    match /Users/{userId} {
      allow read, update, delete: if request.auth.uid == userId;
      allow create: if request.auth.uid != null;
    }
  }

In this case, that workaround do not work.

sdiaz-qkt commented 5 years ago

This is a really big security issue, how long do you think until we get a new release ? @Redth

jehans commented 5 years ago

Hello! This is also a big issue for me. Works perfectly fine on IOS.

moljac commented 5 years ago

@jehans @sdiaz-qkt @craigmart-in

Could you try preview9 and if it is not working provide some minimal sample and if it is working close this issue, please?

sdiaz-qkt commented 5 years ago

@moljac Hello, I'm trying to try preview 9 but it is failing the authentication with email and password. This was never an issue for me, so I can only assume it has something to do with the new updates.

Here's my code, hopefully you can help me figure out what's going on here so I can test preview 9 soon enough :)

FirebaseApp fa = FirebaseApp.InitializeApp(Application.Context);
mAuth = FirebaseAuth.GetInstance(fa);

AuthCredential credential = EmailAuthProvider.GetCredential(emailField.Text, passField.Text);
var creds = mAuth.SignInWithEmailAndPassword(emailField.Text, passField.Text);

In the last line it throws the following error:

Unhandled Exception:

System.NullReferenceException: Object reference not set to an instance of an object.

My mAuth variable is null which means the instance didn't succeed, not sure why.

I also did it like this:

var baseOptions = FirebaseOptions.FromResource(Application.Context);
var options = new FirebaseOptions.Builder(baseOptions)
                .SetProjectId(baseOptions.StorageBucket.Split('.')[0])
                .Build();

var fa = FirebaseApp.InitializeApp(Application.Context, options, RandomString(8));

mAuth = FirebaseAuth.GetInstance(fa);

AuthCredential credential = EmailAuthProvider.GetCredential(emailField.Text, passField.Text);
var creds = mAuth.SignInWithEmailAndPassword(emailField.Text, passField.Text);

but the error remains the same.

moljac commented 5 years ago

@sdiaz-qkt There were few version bumps for few artifacts, that might have caused the problem. I need to investigate.

Can you provide some minimal repro sample? That would speed up investigation and fix.

sdiaz-qkt commented 5 years ago

@moljac Ok, so I'm not sure if this is what you asked me but hopefully it will help. I uploaded a sample project in this link.

nnovalbos commented 5 years ago

I have the same error. Has anyone found a solution?

sdiaz-qkt commented 5 years ago

@nnovalbos You should read all of the comments and see the dates before commenting. But I will answer you anyway. You can try preview 9 as the solution for the original problem as is supposed to be fixed in there. However, I could not try it since the email and password authentication failed for me. @moljac is currently working on it to find the problem and fix this issue. So you can try preview 9 yourself and see if it works for you or you can just patiently wait for a new release.

nnovalbos commented 5 years ago

@sdiaz-qkt Sorry, I did not notice. Thanks for the reply.

moljac commented 4 years ago

@sdiaz-qkt I see you are using more Firebase packages. Try ManifestMerger please

@nnovalbos @jehans @craigmart-in

Please add nuget Xamarin.Android.ManifestMerger. It will add MSbuild targets that fix Manifest merging.

And please provide info:

https://www.nuget.org/packages/Xamarin.Android.ManifestMerger/1.0.0-preview03

JPZV commented 4 years ago

@moljac I'm having the exactly same problem (PERMISSION_DENIED: Missing or insufficient permissions) using security rules in Firebase/Firestore. Which package I have to update to preview9? I tried updating Xamarin.Firebase.Auth to preview9 (which was launched before that the lastest stable version) but I have the same exception (although I can log in with my email). Just in case, here is the full stack from the exception:

Firebase.Firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions. ---> Xamarin.Grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions. --- End of inner exception stack trace --- --- End of managed Firebase.Firestore.FirebaseFirestoreException stack trace --- com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions. at com.google.firebase.firestore.g.zzt.zza(com.google.firebase:firebase-firestore@@17.0.5:100) at com.google.firebase.firestore.b.zzd.zza(com.google.firebase:firebase-firestore@@17.0.5:122) at com.google.firebase.firestore.b.zzac.zza(com.google.firebase:firebase-firestore@@17.0.5:374) at com.google.firebase.firestore.b.zzg.zza(com.google.firebase:firebase-firestore@@17.0.5:236) at com.google.firebase.firestore.f.zzo.zza(com.google.firebase:firebase-firestore@@17.0.5:6461) at com.google.firebase.firestore.f.zzv.zzb(com.google.firebase:firebase-firestore@@17.0.5:3089) at com.google.firebase.firestore.f.zza$zzb.zza(com.google.firebase:firebase-firestore@@17.0.5:73) at com.google.firebase.firestore.g.zzm$1.onMessage(com.google.firebase:firebase-firestore@@17.0.5:93) at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33) at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33) at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1MessagesAvailable.runInContext(ClientCallImpl.java:519) at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at com.google.firebase.firestore.g.zza$zza.run(com.google.firebase:firebase-firestore@@17.0.5:190) at java.lang.Thread.run(Thread.java:764) Caused by: io.grpc.StatusException: PERMISSION_DENIED: Missing or insufficient permissions. at io.grpc.Status.asException(Status.java:534) at com.google.firebase.firestore.g.zzt.zza(com.google.firebase:firebase-firestore@@17.0.5:98) ... 19 more

nnovalbos commented 4 years ago

Hi @moljac

I added nuget Xamarin.Android.ManifestMerger but i got the same error.

I'm using the following dependencies:

* Xamarin.Firebase.Auth
* Xamarin.Firebase.Core
* Xamarin.Firebase.Database
* Xamarin.Firebase.Firestore
* Xamarin.Firebase.Messaging
* Xamarin.GooglePlayServices.Base

All of them with version 60.1142.1

nnovalbos commented 4 years ago

Does anyone know any alternative to avoid this error?

Thanks

nnovalbos commented 4 years ago

When I use

app = Firebase.FirebaseApp.InitializeApp(context);

instance of

var baseOptions = Firebase.FirebaseOptions.FromResource(context);
var options = new Firebase.FirebaseOptions.Builder(baseOptions).SetProjectId("project_id").Build();
app = Firebase.FirebaseApp.InitializeApp(context, options, AppName);

it works...