Introduction to OAuth Session Handling on Android

An overview of Android OAuth session handling using Okhttp Authenticator

Jason Low
4 min readOct 26, 2021

--

Preface

This is an overview of how to handle session refreshing in Android with the use of components found as part of the Okhttp library. We will discuss the technical challenges and implementation in a separate article.

Got a token?

In the OAuth world, depending on the use-cases and system architecture design, there are usually two key components consumed by the front-end mobile client; an Access Token (AT), and a Refresh Token (RT).

The former, sometimes called a session token, is what is typically used to call authenticated web APIs. Think of something like a GET /profile/me endpoint, how would the backend service know that it is your profile that has to be returned? Well, by the unique AT being passed in the request header of course.

So, how a typical Android app would cater for this, is that the token will be saved into some form of persistent storage, like sharedPreferences , to be accessed when needed.

Assuming we are using the defacto Repository pattern laid out by Google, coupled with a ViewModelor something similar, a typical flow of data for an authenticated request would look something like this:

  1. Load AT from something like a SessionRepositoryin the VM layer.
  2. Pass that AT to the calling method for the authenticated request, maybe a fetchUser method in UserRepository
  3. Profit $$$$

This seems fine for the most part, because in theory, every component involved in this transaction are abstracted from one another, and there is proper separation of concerns.

But, what if we wanted this implementation to be implemented between multiple view models? Basically, scale the implementation across the app? That’s where the problem starts to occur, because chances for one VM behaving the same as another is unlikely.

So, zooming out, maybe the VM isn’t the right place for this transaction to occur. Where else would be a good alternative to implement this then?

Inject it at the source

Thankfully for us, one of the most popular HTTP client for Android is Okhttp3, which is used by libraries such as Retrofit. It comes with a whole slew of features, but the ones we are interested in, are the interceptors, and specifically, the Authenticator.

Now, to make a long story short, an Authenticator automatically intercepts 401 errors (standard HTTP “Unauthorized” error code) returned from the web service we are consuming, and gives us the flexibility to handle that exception gracefully, particularly, refreshing the AT. If you’re familiar with Interceptors, think of Authenticators as a very specialized Interceptor.

Refreshing the token

In a typical scenario, say the app makes an authenticated API call, but, the AT is no longer valid, the next logical thing would be to refresh the token, yes? Taking our example from earlier, if this were all to be handled in the VM, it’d be an awful lot of orchestration in that VM, let alone if we were to scale this implementation to other VM (copy-pasta anyone?).

If we were to just do it in the Authenticator, we can implement it so that we make the call to refresh the token ONLY when we receive a 401 error. Now, should that refresh call fail, then we let the exception fall through normally, and we can even opt to throw a custom exception for our VM/Repository layer to further specify the cause.

An example implementation might look something like this:

Authenticators/Interceptors has to be run synchronously, hence the blocking coroutine.

In a happy path scenario, assuming our authRepository.refreshAccessToken() is able to cache the access token, we have an updated token to be injected into every subsequent requests via our Interceptor:

Wrap-up

This is just a taste of what there is to experiment with. There are more details to flesh out regarding the implementation, such as the role of the AuthRepository , the architecture to prevent cyclic dependencies, and how are we to setup the HTTP client(s) to make it all work. But this article provides a foundational knowledge for us to build upon, and exposes you to something you might not be familiar with.

If you’re interested to dive further into the implementation, keep an eye out for the the deep dive (or better yet, follow me!), where we address the inner working to get this show fully on the road!

Follow me on Twitter for more of my thoughts on Android, life, and everything in between.

I hope you stay safe, and have a wonderful day :)

https://twitter.com/jasonlowdh

--

--

Jason Low

https://twitter.com/jasonlowdh Full-time Android developer. I write about anything Android/software development, tech, and life’s musings.