< Back to articles

RxOAuth2: reactive OAuth approach for Android, pt. 2

TL;DR: with colleagues from Ackee we developed RxOauth2, an open source library to handle OAuth with RxJava streams. You may take a look at it directly or read this blog post (part 1 is here) to find out why and how we implemented it.

In Part 1, we were talking about the implementation of the core part of RxOauth2 library. In this part, we’d like to share our way to integrate the core logic into project REST API layer.

In almost every Ackee project we have so called ApiInteractor, it is a layer between Retrofit API description (endpoints declaration layer) and repositories working with API requests. When using the first versions of RxOauth library, we had to separately wrap each of our requests with refresh token logic. We wanted to create a solution, which will integrate this logic to our API calls automatically by default.

It was Java time and annotation processors were on the peak of popularity. So we came up with a solution to generate a wrapper on top of ApiDescription(Retrofit interface with endpoints declaration) during build time. We decided to take more general approach and created RxWrapper, a library that allows to generate a wrapper class around interface methods that return ObservableSingle or Completable. That wrapper then applies the custom Transformer to each of those methods via compose() operator. To exclude a method from applying the Transformer, the NoCompose annotation is used.

You may still explore and use RxWrapper library, but we stepped back from using it due to a couple of reasons:

  • The wrapper is generated during build time, so the library user has to run the build at least once to be able to use the wrapper
  • The wrapper is generated in Java, after Kotlin adoption we weren’t able to use its main features: optional values, default values or nullability

Rewriting the wrapper to Kotlin seemed more complex and we decided to look into another way to achieve required functionality. That’s how RxOauthCallAdapter came into life.

To convert API Call into arbitrary type Retrofit uses an interface called CallAdapter. Retrofit itself has a couple of adapter implementations, for example RxJava2CallAdapter allows us to work with API requests as RxJava2 streams. Initializing the CallAdapter is done by setting the CallAdapter.Factory to the Retrofit.Builder when building the Retrofitinstance.

The cool thing about this decoupled architecture that it is possible to write your own CallAdapter.Factory implementation and do whatever you wand with requests handling. For example convert them to RxJava2 streams andwrap with OAuth logic. Unfortunately RxJava2CallAdapter as well as its factory are final, that’s why we almost copied its functionality to create [RxOauthCallAdapter](https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2FAckeeCZ%2Frxoauth%2Fblob%2Fmaster%2Fretrofitadapter%2Fsrc%2Fmain%2Fjava%2Fcz%2Fackee%2Frxoauth%2Fadapter%2FRxOauthCallAdapter.kt) with [RxOauthCallAdapterFactory](https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2FAckeeCZ%2Frxoauth%2Fblob%2Fmaster%2Fretrofitadapter%2Fsrc%2Fmain%2Fjava%2Fcz%2Fackee%2Frxoauth%2Fadapter%2FRxOauthCallAdapterFactory.kt) and added our wrapping. Now there is no need to work with each request manually or generate redundant classes, all the library user has to do is to add our custom factory to Retrofit client. Together with setting the OAuthInterceptor it will look like this:

val apiDescription: ApiDescription = retrofitBuilder  

Now all our requests inside ApiDescription will be wrapped with OAuth logic.

To exclude some requests from OAuth wrapping (registration, login etc.) you ma use IgnoreAuth annotation, which should be added to ApiDescriptionfunctions:

    fun signUp(): Single

Basically, that’s all about it. If you want to read about RxOAuth2 library usage or see its insides, it is available on Github.

Georgiy Shur
Georgiy Shur
Android DeveloperBefore Georgiy used to live off Android, he used to live off poker. His interest lies in Kotlin, UX and preparation of delicious meals.

Are you interested in working together? Let’s discuss it in person!

Get in touch >