Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Firebase user token synchronously

I am trying to get a Firebase token to authenticate my calls to a Rest API. I can generate the tokens asynchronously with the following code.

    FirebaseUser mUser = App.getFirebaseAuth().getCurrentUser();
    if (mUser!=null) {
        mUser.getIdToken(false)
                .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
                    public void onComplete(@NonNull Task<GetTokenResult> task) {
                        if (task.isSuccessful()) {
                            ID_TOKEN = task.getResult().getToken();
                        } else {
                            Log.e(App.TAG, "Firebase Token task ended with error.");
                        }
                    }
                });
    } else {
        Log.i(App.TAG,"User is null, no Firebase Token available");
    }

The ID_TOKEN is a static string variable that holds the result. The issue is, I am constructing my request and adding the authentication headers.

        headers.put("Authentication",
                "Bearer  + ID_TOKEN);

The issue is, since the Firebase token is retrieved asynchronously, sometims the ID_TOKEN variable is empty. I tried forcing the thread to wait for the task using

Tasks.await(task)

But I get an exception saying await cannot be invoked in the main thread.

Is there any other way to get the token synchronously, or make the thread wait until the tasks finishes?

like image 717
OCDev Avatar asked Feb 15 '18 23:02

OCDev


People also ask

Does Firebase automatically refresh token?

Every time a user signs in, the user credentials are sent to the Firebase Authentication backend and exchanged for a Firebase ID token (a JWT) and refresh token. Firebase ID tokens are short lived and last for an hour; the refresh token can be used to retrieve new ID tokens.

How do I get my Firebase access token?

The access tokens can be generated using a service account with proper permissions to your Realtime Database. Clicking the Generate New Private Key button at the bottom of the Service Accounts section of the Firebase console allows you to easily generate a new service account key file if you do not have one already.

Is Firebase user UID unique?

Firebase users have a fixed set of basic properties—a unique ID, a primary email address, a name and a photo URL—stored in the project's user database, that can be updated by the user (iOS, Android, web).


2 Answers

I'm doing it like this now:

private suspend fun getTokenResult (firebaseUser: FirebaseUser) = suspendCoroutine<GetTokenResult?> { continuation ->
firebaseUser.getIdToken(true).addOnCompleteListener {
    if (it.isSuccessful) {
        continuation.resume(it.result)
    } else {
        continuation.resume(null)
    }
}

Using a suspended function and the continuation mechanism. So if you are using Coroutines, this might be the easiest way

like image 72
Boy Avatar answered Sep 19 '22 10:09

Boy


I had the same problem, I needed to update token in Retrofit Authenticator when I got 407. I use CountDownLatch

override fun authenticate(route: Route?, response: Response): Request? {
    val user = FirebaseAuth.getInstance().currentUser
    var token: String? = null
    val lock = CountDownLatch(1)

    user?.getIdToken(true)?.addOnCompleteListener { task ->
        if (task.isSuccessful) {
            token = task.result?.token
            if (token == null) {
                lock.countDown()            //<--unlock 
                return@addOnCompleteListener
            }
            //save token
        } else {
            lock.countDown()                //<--unlock 
            return@addOnCompleteListener
        }
    }
    lock.await()                            //<--wait unlock 

    return if (token != null)
        response.request().newBuilder().header(AUTHORIZATION_KEY, token).build()
    else null
}
like image 28
Владислав Прасков Avatar answered Sep 23 '22 10:09

Владислав Прасков