Simple reactive extension, that adds support to Retrofit2 based projects which uses OAuth2 authentication.
This library is based on RxJava2.
-
RxOAuthManager
provides wrapping for RxJava2 streams, which automatically handles access token expiration and performs token refresh. In case of success, new credentials are stored inSharedPreferences
. When refresh token is invalid, the optional logic provided inonRefreshTokenFailed
is performed. With customErrorChecker
, the user may customize access and refresh tokens errors validation -
OAuthInterceptor
, which is provided byRxOAuthManager
addsAuthorization
header with access token to OkHttp requests -
DefaultOAuthCredentials
is the default implementation ofOAuthCredentials
compile 'cz.ackee.rxoauth2:core:x.x.x'
Working sample is provided in app
module.
Create RxOAuthManager
typically in API access layer (in our case, ApiInteractorImpl):
class ApiInteractorImpl @Inject constructor(private val apiDescription: ApiDescription,
context: Context) : ApiInteractor {
private val rxOAuthManager: RxOAuthManager = RxOAuthManager(
context = context,
refreshTokenAction = { refreshToken ->
apiDescription.refreshToken(refreshToken) // API call for token refresh
},
onRefreshTokenFailed = { err ->
// Fallback, e.g. log out
})
}
You can save OAuth credentials with saveCredentials(credentials: OAuthCredentials)
method. You may want to do this after receiving credentials from server, e.g. after login or sign in.
apiDescription.login(name, password)
.doOnNext { credentials -> rxOAuthManager.saveCredentials(credentials) }
After logging out, you may want to remove credentials from the store.
apiDescription.logout()
.doOnNext { response -> rxOAuthManager.clearCredentials() }
To wrap your requests with OAuth handling, just call wrapWithOAuthHandlingObservable()
, wrapWithOAuthHandlingSingle()
or wrapWithOAuthHandlingCompletable()
on the stream you want. RxOAuthManager
supports Observable
, Single
and Completable
.
apiDescription.getData().wrapWithOAuthHandlingSingle(rxOAuthManager)
To avoid boilerplate for each request, you may use another library we developed - RxWrapper, which wraps the whole interface functions that use RxJava2 with custom Transformer
s using compose
operator. Now you need to apply wrapWithOAuthHandling...()
only once and work with generated wrapper insteado of original apiDescription
. If you want to exclude some function from wrapping, just mark it with @NoCompose
annotation.
Initialization in constructor of Api Interactor:
private var apiWrapper = ApiDescriptionWrapped(apiDescription, object : IComposeWrapper {
override fun <T : Any?> wrapSingle(): SingleTransformer<T, T> {
return rxOAuthManager.transformSingle()
}
override fun wrapCompletable(): CompletableTransformer {
return rxOAuthManager.transformCompletable()
}
override fun <T : Any?> wrapObservable(): ObservableTransformer<T, T> {
return rxOAuthManager.transformObservable()
}
})
From version 2.0.0, new module is available. Now RxOAuth2 wrapping may be provided as Retrofit2 CallAdapter
.
compile 'cz.ackee.rxoauth2:retrofit-adapter:x.x.x'
When creating your API service, just provide RxOAuthCallAdapterFactory
to Retrofit builder. If you want to exclude some function from wrapping, just mark it with @IgnoreAuth
annotation.
val apiDescription: ApiDescription = retrofitBuilder
.client(OkHttpClient.Builder()
.addNetworkInterceptor(rxOAuthManager.provideAuthInterceptor())
.build())
.addCallAdapterFactory(RxOAuthCallAdapterFactory(rxOAuthManager))
.build()
.create(ApiDescription::class.java)
- Release of lib with RxJava2 support
- Abstract checker for errors to give user ability to change behavior when to refresh token
- Artifact naming change:
cz.ackee.rxoauth2:rxOAuth
->cz.ackee.rxoauth2:core
- New module
Retrofit adapter
is created with artifactcz.ackee.rxoauth2:retrofit-adapter
, more on this in section Retrofit2 adapter -
RxOAuthManager
now acceptsContext
or customSharedPreferences
in the constructor instead ofOAuthStore
-
RxOAuthManager
now uses lambda actionrefreshTokenAction: (String) -> Single<OAuthCredentials>
instead ofRefreshTokenService
class -
RxOAuthManager
now uses lambda actiononRefreshTokenFailed: (Throwable) -> Unit
instead ofRefreshTokenFailedListener
class. - New property
expiresIn
is added toOAuthCredentials
. NowOAuthStore
stores token expiration time andRxOAuthManager
controls it locally before each request to avoid redundant API calls if access token is expired -
OAuthStore
is now an internal class. The only way to store credentials issaveCredentials(credentials: OAuthCredentials)
onRxOAuthManager
. The same is withclearCredentials()
-
AuthInterceptor
is renamed toOAuthInterceptor
an has now only internal constructor. The only way to get an instance isprovideAuthInterceptor()
function onRxOAuthManager
-
DefaultOAuthCredentials
class is added as default implementation ofOAuthCredentials
-
DefaultErrorChecker
functions were renamed
- Rename
wrapWithOAuthHandlingObservable()
,wrapWithOAuthHandlingSingle()
andwrapWithOAuthHandlingCompletable()
functions, returning transformers totransformObservable()
,transformSingle()
andtransformCompletable()
respectively - Add Kotlin extensions for RxJava entities:
wrapWithOAuthHandlingObservable()
,wrapWithOAuthHandlingSingle()
andwrapWithOAuthHandlingCompletable()
- Fix
NullPointerException
onCompletable
handling due to null body