4
votes

i have set up firebase storage for my app, and added the code for anonymous auth on the app and on the firebase console.

it worked at first, but i dont know why it stopped working, saying that the user does not have permission to access the object

Anonymous auth is correctly set up and i did see it working, code is almost like Google Firebase docs

logcat:

D/FirebaseAuth: signInAnonymously:onComplete:true
D/FirebaseAuth: onAuthStateChanged:signed_in: (Random auth user id)

... When i request the item from firebase

E/StorageUtil: error getting token java.util.concurrent.ExecutionException: com.google.firebase.FirebaseException: An internal error has occured. [Internal error encountered.] I/DpmTcmClient: RegisterTcmMonitor from: com.android.okhttp.TcmIdleTimerMonitor W/NetworkRequest: no auth token for request E/StorageException: StorageException has occurred. User does not have permission to access this object. Code: -13021 HttpResult: 403

Can Someone help?

Declaring Variables

private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;

on the OnCreate method

mAuthListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                // User is signed in
                Log.d("FirebaseAuth", "onAuthStateChanged:signed_in:" + user.getUid());
            } else {
                // User is signed out
                Log.d("FirebaseAuth", "onAuthStateChanged:signed_out");
            }
            // ...
        }
    };
    mAuth.signInAnonymously()
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    Log.d("FirebaseAuth", "signInAnonymously:onComplete:" + task.isSuccessful());

                    // If sign in fails, display a message to the user. If sign in succeeds
                    // the auth state listener will be notified and logic to handle the
                    // signed in user can be handled in the listener.
                    if (!task.isSuccessful()) {
                        Log.w("FirebaseAuth", "signInAnonymously", task.getException());
                        Toast.makeText(SingleMemeEditor.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                    }

                    // ...
                }
            });

and the method that gets from storage:

    Bitmap bmp;
    final Context lContext = context; //getting the MainActivity Context
    final String lFileName = fileName; //filename to download
    final String lCatPath = catPath; //internal categorization folder

    FirebaseStorage storage = FirebaseStorage.getInstance();
    // Create a storage reference from our app
    StorageReference storageRef = storage.getReferenceFromUrl(context.getResources().getString(R.string.firebase_bucket));
    // Create a reference with an initial file path and name
    StorageReference filesRef = storageRef.child("files/" + fileName);
    try
    {
        final File localFile = File.createTempFile("images", "jpg");

        filesRef.getFile(localFile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>()
        {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot)
            {
                // Local temp file has been created
                File file = new File(getDirectory(lContext)
                        + File.separator + lCatPath + File.separator + lFileName);
                try
                {
                    Boolean b = file.createNewFile();
                    if(b)
                    {
                        FileInputStream in = new FileInputStream(localFile);
                        FileOutputStream out = new FileOutputStream(file);

                        // Transfer bytes from in to out
                        byte[] buf = new byte[(int)localFile.length()];
                        int len;
                        while ((len = in.read(buf)) > 0) {
                            out.write(buf, 0, len);
                        }
                        in.close();
                        out.close();
                    }
                            Drawable.createFromPath(file.getPath())).getBitmap());
                }
                catch (IOException ex)
                {
                    // Handle any errors
                    Log.e("CopyingFromTemp", ex.getMessage());
                }

            }
        }).addOnFailureListener(new OnFailureListener()
        {
            @Override
            public void onFailure(@NonNull Exception ex)
            {
                // Handle any errors
                Log.e("FirebaseDownloadError", ex.getMessage());
            }
        });
    }
    catch(Exception ex)
    {
        Log.e("FirebaseDownloadError", ex.getMessage());
    }

also i'm using standard security rules:

match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
4
Show the security rules for your Storage and the minimum code that reproduces the problem (the flow is rather important here).Frank van Puffelen
post edited to add what you requestedDaniel Andujar
The code does unfortunately not show how you ensure that the user is authenticated before uploading an image. You might want to add a simple check if (FirebaseAuth.getInstance().getCurrentUser !0 null) before starting the actual upload.Frank van Puffelen
as i'm using anonymous authentication, and i was seeing the Authentication "success" i thought that wouldn't actually be necesary, anyways thanks for the code to ensure the user is authenticated, but as i posted as answer earlier (haven't accepted it as correct because i have to wait a day) the solution was to sign out of the current authenticated "user"Daniel Andujar

4 Answers

5
votes

as Benjamin Wulfe hinted, i deleted the App's data on the phone and it worked, which means that some kind of Token data was stored on the phone and Anonymous Auth was getting an old session data.

so i added a sign out code before signInAnonymously

mAuth.signOut();

and done!

Thanks to you all for the help!

EDIT: I found another method which is better than signing out and in again (which lead to hundreds of unused anonymous users on the firebase console, and that because the app is not in production yet, would have been millions).

this is what i did:

if (mAuth.getCurrentUser() != null)
        {
            mAuth.getCurrentUser().reload();
        }
        else
        {
            mAuth.signInAnonymously()
                    .addOnCompleteListener(this, new OnCompleteListener<AuthResult>()
                    {
                        @Override
                        public void onComplete(@NonNull Task<AuthResult> task)
                        {
                            Log.d("FirebaseAuth", "signInAnonymously:onComplete:" + task.isSuccessful());

                            // If sign in fails, display a message to the user. If sign in succeeds
                            // the auth state listener will be notified and logic to handle the
                            // signed in user can be handled in the listener.
                            if (!task.isSuccessful())
                            {
                                Log.w("FirebaseAuth", "signInAnonymously", task.getException());
                                Toast.makeText(MainActivity.this, "Authentication failed.",
                                        Toast.LENGTH_SHORT).show();
                            }
                            // ...
                        }
                    });
        }

this just reloads current authenticated (anonymous) user.

4
votes

The message " W/NetworkRequest: no auth token for request " is key for debugging this issue.

This log message means that Firebase Storage did not see any login in the current context. This includes anonymous logins. It means that no authorization was passed to the backend and the only way this will be allowed is if you set your rules to be completely open (public access) which is not recommended (see below).

 //this sets completely open access to your data
 allow read, write;

I would review the code you have for logging in and ensure it successfully completes before any storage operation is done. If you are sure your auth code is correct, try resetting data on the device so that no saved state might be there to mess up the application's authorization information.

0
votes

You might have to check your RULES for storage in firebase console. By default it is set to only permit to authenticated user only like this

  allow read, write: if request.auth != null;
0
votes

Sometime its disconnect from firebase database,So Connect your app with firebase authentication in android studio through firebase assistance tool.