Firebase Client Does Not Have Permission to Perform This Operation

Viewed 1834

I'm using Firebase Authentication in my app and I have the following code to allow the user to sign out:

FirebaseAuth.getInstance().signOut()
userInfo.removeEventListener(listener)
val intent = Intent(this@SettingsFragment.context, LoginActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)

The code successfully logs out the user, but I get this toast that says The client does not have permission to perform this operation. Why am I getting this toast? How do I prevent it from occurring?

UPDATE 1: Firebase Realtime Database Code and Removal of Event Listener

Below I have included my code for using Firebase Realtime Database:

userInfo = database.getReference("users").child(auth.currentUser!!.uid)
listener = userInfo.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        for (postSnapshot in dataSnapshot.children) {
            if (postSnapshot.key == "firstName") {
                firstNamePreference.text = postSnapshot.getValue(String::class.java)
            } else if (postSnapshot.key == "lastName") {
                lastNamePreference.text = postSnapshot.getValue(String::class.java)
            } else if (postSnapshot.key == "username") {
                userNamePreference.title =
                    "Username: ${postSnapshot.getValue(String::class.java)}"
            }
        }
    }

    override fun onCancelled(databaseError: DatabaseError) {
        Toast.makeText(
            context, databaseError.message,
            Toast.LENGTH_LONG
        ).show()
    }
})

I have also included userInfo.removeEventListener(listener) in my sign out code, but I am still getting the error message.

UPDATE 2: Logcat in debug mode for logging out the user

D/InputTransport: Input channel destroyed: fd=77
D/ViewRootImpl@b3aa7b8[SettingsActivity]: MSG_WINDOW_FOCUS_CHANGED 0 1
D/InputMethodManager: prepareNavigationBarInfo() DecorView@6d11dc3[SettingsActivity]
D/InputMethodManager: getNavigationBarColor() -855310
W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@f47f5fd
W/SyncTree: Listen at /users/ezTJRHVKZXhHyMGQGGljdQpfzGv1 failed: DatabaseError: This client does not have permission to perform this operation
I/DecorView: createDecorCaptionView >> DecorView@aa5b516[], isFloating: false, isApplication: true, hasWindowDecorCaption: false, hasWindowControllerCallback: true
D/InputTransport: Input channel constructed: fd=78
D/ViewRootImpl@46f9f6b[LoginActivity]: setView = DecorView@aa5b516[LoginActivity] TM=true MM=false
D/ViewRootImpl@46f9f6b[LoginActivity]: dispatchAttachedToWindow
D/ViewRootImpl@46f9f6b[LoginActivity]: Relayout returned: old=[0,0][1440,2960] new=[0,0][1440,2960] result=0x7 surface={valid=true 480479002624} changed=true
D/OpenGLRenderer: eglCreateWindowSurface = 0x6fdfef7280, 0x6fdec7c010
D/ViewRootImpl@46f9f6b[LoginActivity]: MSG_RESIZED: frame=Rect(0, 0 - 1440, 2960) ci=Rect(0, 96 - 0, 192) vi=Rect(0, 96 - 0, 192) or=1
D/ViewRootImpl@46f9f6b[LoginActivity]: MSG_WINDOW_FOCUS_CHANGED 1 1
D/InputMethodManager: prepareNavigationBarInfo() DecorView@aa5b516[LoginActivity]
D/InputMethodManager: getNavigationBarColor() -855310
D/InputMethodManager: prepareNavigationBarInfo() DecorView@aa5b516[LoginActivity]
D/InputMethodManager: getNavigationBarColor() -855310
D/InputMethodManager: startInputInner - Id : 0
I/InputMethodManager: startInputInner - mService.startInputOrWindowGainedFocus
D/InputTransport: Input channel constructed: fd=89
D/InputTransport: Input channel destroyed: fd=97
D/FA: Connected to remote service
D/InputTransport: Input channel constructed: fd=92
D/ViewRootImpl@346cbca[Toast]: setView = android.widget.LinearLayout{75c95b1 V.E...... ......I. 0,0-0,0} TM=true MM=false
D/ViewRootImpl@346cbca[Toast]: dispatchAttachedToWindow
D/ViewRootImpl@346cbca[Toast]: Relayout returned: old=[0,96][1440,2768] new=[115,2282][1324,2512] result=0x7 surface={valid=true 480480571392} changed=true
D/OpenGLRenderer: eglCreateWindowSurface = 0x6fdf199d80, 0x6fdedfb010
D/ViewRootImpl@346cbca[Toast]: MSG_RESIZED: frame=Rect(115, 2282 - 1324, 2512) ci=Rect(0, 0 - 0, 0) vi=Rect(0, 0 - 0, 0) or=1
D/OpenGLRenderer: eglDestroySurface = 0x6fdfff3d00, 0x6fdfd7c000
D/ViewRootImpl@b3aa7b8[SettingsActivity]: Relayout returned: old=[0,0][1440,2960] new=[0,0][1440,2960] result=0x5 surface={valid=false 0} changed=true
D/ViewRootImpl@b3aa7b8[SettingsActivity]: setWindowStopped(true) old=false
D/ViewRootImpl@b3aa7b8[SettingsActivity]: Surface release. android.view.WindowManagerGlobal.setStoppedState:669 android.app.Activity.performStop:7647 android.app.ActivityThread.callActivityOnStop:4379 android.app.ActivityThread.performStopActivityInner:4357 android.app.ActivityThread.handleStopActivity:4432 android.app.servertransaction.TransactionExecutor.performLifecycleSequence:192 android.app.servertransaction.TransactionExecutor.cycleToPath:165 android.app.servertransaction.TransactionExecutor.executeLifecycleState:142 
D/ViewRootImpl@b3aa7b8[SettingsActivity]: dispatchDetachedFromWindow
D/ViewRootImpl@b3aa7b8[SettingsActivity]: Surface release. android.view.ViewRootImpl.doDie:7967 android.view.ViewRootImpl.die:7935 android.view.WindowManagerGlobal.removeViewLocked:497 android.view.WindowManagerGlobal.removeView:435 android.view.WindowManagerImpl.removeViewImmediate:124 android.app.ActivityThread.handleDestroyActivity:4753 android.app.servertransaction.DestroyActivityItem.execute:39 android.app.servertransaction.TransactionExecutor.executeLifecycleState:145 
D/InputTransport: Input channel destroyed: fd=91
D/OpenGLRenderer: eglDestroySurface = 0x6fdf199d80, 0x6fdedfb000
D/ViewRootImpl@346cbca[Toast]: dispatchDetachedFromWindow
D/ViewRootImpl@346cbca[Toast]: Surface release. android.view.ViewRootImpl.doDie:7967 android.view.ViewRootImpl.die:7935 android.view.WindowManagerGlobal.removeViewLocked:497 android.view.WindowManagerGlobal.removeView:435 android.view.WindowManagerImpl.removeViewImmediate:124 android.widget.Toast$TN.handleHide:1110 android.widget.Toast$TN$1.handleMessage:898 android.os.Handler.dispatchMessage:106 
D/InputTransport: Input channel destroyed: fd=92
1 Answers

It sounds like you have a listener to one of the Firebase databases (either Realtime Database or Cloud Firestore), and this listener requires that the user is authenticated. When you sign the user out, the listener becomes invalid, and gets cancelled by Firebase with the error message you see.

The solution is to remove the listener before signing the user out.

Related