How to show error message in token authenticator and logout user

373 Views Asked by At

I would like to refresh-token and send the request again. I can make request if it is success there is no problem but if refresh-token response gets fail I would like to show error message and forward user to login screen. I also do not have context in TokenAuthenticator class and it's not possible because it provides in my Hilt NetworkModule.

I have tried create a MutableLiveData in Session and postvalue true in below class but while i observe it in BaseActivity, it goes infinite loop and trigger every time after one time postValue.

How can i solve this problem?

class TokenAuthenticator(
    val preferenceHelperImp: PreferenceHelperImp,
    private val tokenApi: RefreshTokenApi,
) : Authenticator{

    override fun authenticate(route: Route?, response: Response): Request? {
        GlobalScope.launch {
            getUpdatedRefreshToken(RefreshTokenRequest(preferenceHelperImp.getRefreshToken())
            ).collect {
                when (it) {
                    is State.Success -> {
                        preferenceHelperImp.setCurrentUserLoggedInMode(Constants.App.LoggedInMode.LOGGED_IN_MODE_SERVER)
                        preferenceHelperImp.setAccessToken(it.data.body()?.payload?.accessToken)
                        preferenceHelperImp.setRefreshToken(it.data.body()?.payload?.refreshToken)
                        preferenceHelperImp.setUserInfo(Gson().toJson(TokenInfo.initFromToken(
                            it.data.body()?.payload?.accessToken!!)))

                        Session.current.userInfo =
                            Gson().fromJson(preferenceHelperImp.getUserInfo(),
                                TokenInfo::class.java)

                        response.request.newBuilder()
                            .header("Authorization", it.data.body()?.payload?.accessToken!!)
                            .build()
                    }
                    is State.Fail -> {
                      Session.current.isRefreshTokenFail.postValue(true)
                    }
                    is State.Error -> {
                        Session.current.isRefreshTokenFail.postValue(true)
                    }
                }
            }
        }
        return null
    }

    private fun getUpdatedRefreshToken(refreshTokenRequest: RefreshTokenRequest): Flow<State<LoginResponse>> {
        return object :
            NetworkBoundRepository<LoginResponse>() {
            override suspend fun fetchFromRemote(): retrofit2.Response<LoginResponse> =
                tokenApi.getRefreshToken(refreshTokenRequest)
        }.asFlow()
    }
}
1

There are 1 best solutions below

0
On

Could you try with typealias?

typealias OnAuthSuccess = () -> Unit
typealias OnAuthFailure = () -> Unit
    class TokenAuthenticator (){...
        override fun authenticate(onAuthSuccess: OnAuthSuccess,onAuthFailure: OnAuthFailure, route: Route?, response: Response): Request? {
                   when (it) {
                            is State.Success -> {
                                onAuthSuccess.invoke()
                            }
                            is State.Fail -> {
                              onAuthFailure.invoke()
                            }
            }