Advanced Retrofit2 (Part 2): Authorization Handling
Retrofit, most popular networking library in the recent times. The convenient thing I found in retrofit is the…medium.com
This article is second part of the previous article. I’m writing this article on handling authorization using Retrofit2+OkHttp3. So, get started!
I will follow up the same coding fashion used in the previous article. It’s better to have a glance into my previous article to proceed on this one.
Apps connected with backend APIs needs it’s user to authenticate to get access to it’s services. When a user get logged in to an app, a token get generated using user’s credentials (i.e: email, password). Backend APIs uses several authentication method (i.e: JWT, OAuth2) to generate token. Credentials are exchanged against a token which is then attached to every subsequent request.
Token are temporary and get expired/refreshed after a certain period of time. Apps might need to get the updated token in some way so that access won’t be revoked. If expired, app need to take necessary actions. There are several use cases as following:
Use Case 1: Some API returns the updated token in response header for once.
Use Case 2: App should be instantly logged out when token get expired and promote user to login again (For example: when user change facebook password using website and want to continue using the mobile app. Let’s have a try 😉).
Use Case 3: When token get expired, it might be required to automatically login in background to get the new token without notifying anything to user and let them do what he/she intended.
Token might get expired any time. This can be encountered with any of the consecutive Http requests. That’s why we need to have a mechanism of handling token expiration that works centrally at the module level and doesn’t require any change in the top level implementation.
So let’s dive to the solution step by step. Let’s setup necessary classes first.
Now let’s consider our first use case. When the token get expired, new token supposed to be available into the response header for the very first request with older token. We need to save the new token replacing the older one. We will create an interceptor called
TokenRenewInterceptor that will check for new token into the response header for the consecutive requests. If token is available it will be saved to session. We just need to add the interceptor into
Let’s move to the second use case. Have a look into the following code
Here, we’ve added another interceptor
AuthorizationInterceptor . That checks for response code 401 and 403 which conventionally denotes an authentication issue. When this error is encountered we just call
invalidate() to delete token and user’s data. An event is passed to it’s listener (i.e: view/service) to take the necessary actions (i.e: Switch to Login Activity).
We can add multiple Interceptor if required (like here).
Now come to our third use case. If we don’t want to promote the user to login again and want to manage this authentication error dynamically without notify anything to the user, we have the following solution. Though, this might not be a good practice to login the user automatically because app will need to keep save user’s credentials. Preserve those credentials securely if you need to implement this mechanism. I’m just trying to show up the use cases. You might relate this implementation with your own requirement in a different way. So, let’s go ahead.
Now we will update our existing
AuthorizationInterceptor class as following
Here, we are manipulating the request chain if 401/403 error occurred. When occurred, we generate the auth key (an encoded combination of email and password) and pass it to login API as a request header. As login API get called it returns an
Authorization object if the request is successful.
Authorization includes the new token which we have to save into session. Thus the token get updated. Now we can retry for the
mainRequest for which the unauthorized error occurred. We add the new token to the
mainRequest header and let the request to make again. It should now get result successfully.
getAccountInfo() → Unauthorized Error →
loginAccount() → Success (token updated) → retry
getAccountInfo() → Success!
That’s it! We can do lots of exciting stuff with Retrofit+OkHttp like this.
Hopefully, I will come up with debug and unit testing using Retrofit+OkHttp+GSON in next article.
Please feel free to put up your suggestion to improve my writings.
Thanks for reading!