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?
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.
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.
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).
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
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With