private class HttpInterceptor implements Interceptor { | |
@Override | |
public Response intercept(Chain chain) throws IOException { | |
Request request = chain.request(); | |
//Build new request | |
Request.Builder builder = request.newBuilder(); | |
builder.header("Accept", "application/json"); //if necessary, say to consume JSON | |
String token = settings.getAccessToken(); //save token of this request for future | |
setAuthHeader(builder, token); //write current token to request | |
request = builder.build(); //overwrite old request | |
Response response = chain.proceed(request); //perform request, here original request will be executed | |
if (response.code() == 401) { //if unauthorized | |
synchronized (httpClient) { //perform all 401 in sync blocks, to avoid multiply token updates | |
String currentToken = settings.getAccessToken(); //get currently stored token | |
if(currentToken != null && currentToken.equals(token)) { //compare current token with token that was stored before, if it was not updated - do update | |
int code = refreshToken() / 100; //refresh token | |
if(code != 2) { //if refresh token failed for some reason | |
if(code == 4) //only if response is 400, 500 might mean that token was not updated | |
logout(); //go to login screen | |
return response; //if token refresh failed - show error to user | |
} | |
} | |
if(settings.getAccessToken() != null) { //retry requires new auth token, | |
setAuthHeader(builder, settings.getAccessToken()); //set auth token to updated | |
request = builder.build(); | |
return chain.proceed(request); //repeat request with new token | |
} | |
} | |
} | |
return response; | |
} | |
private void setAuthHeader(Request.Builder builder, String token) { | |
if (token != null) //Add Auth token to each request if authorized | |
builder.header("Authorization", String.format("Bearer %s", token)); | |
} | |
private int refreshToken() { | |
//Refresh token, synchronously, save it, and return result code | |
//you might use retrofit here | |
} | |
private int logout() { | |
//logout your user | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
It's application level interceptor |
This comment has been minimized.
This comment has been minimized.
Where are you getting the httpClient instance to synchronize on? |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
Hello, you can give more details of how the implementation of its ServiceGenerator? I have serious problems making synchronous calls to RefreshToken. |
This comment has been minimized.
This comment has been minimized.
Hi. Gson gson = new GsonBuilder().create();
OkHttpClient httpClient = new OkHttpClient();
httpClient.interceptors().add(new HttpInterceptor());
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(BuildConfig.REST_SERVICE_URL)
.setClient(new OkClient(httpClient))
.setConverter(new GsonConverter(gson))
.setLogLevel(RestAdapter.LogLevel.BASIC)
.build();
remoteService = restAdapter.create(RemoteService.class); |
This comment has been minimized.
This comment has been minimized.
What is that settings variable? |
This comment has been minimized.
This comment has been minimized.
Hi. Sorry for late response. |
This comment has been minimized.
This comment has been minimized.
Are we talking here about Server Token(sent by backend) or say Facebook Oauth Token ? Thanks . |
This comment has been minimized.
This comment has been minimized.
How can we make refreshing access token block to execute only one time without using synchronized to okhttp instance. Can we make synchronized to other instance? |
This comment has been minimized.
This comment has been minimized.
About server token, I think facebook has their own means to update tokens. @rajeshkumarkhadka
I think you can use some generic object for locks, but I can't be sure that it will work correct |
This comment has been minimized.
This comment has been minimized.
I have implemented this without any fuss but there is a talk that Authenticator is a better of doing it. Thoughts anyone ? https://github.com/square/okhttp/wiki/Recipes#handling-authentication |
This comment has been minimized.
This comment has been minimized.
Authenticator is completely suitable tool for the token refresh action and retry the main request |
This comment has been minimized.
This comment has been minimized.
@alex-shpak Can you give a hint on how the settings object is accessed and updated? I am struggling to understand how to update the persistence layer once the new token is generated. |
This comment has been minimized.
This comment has been minimized.
@alex-shpak thanks for sharing your knowledge. Base on your model I've built mine own. I added few details, as synchronous refresh token and so on. This is it https://gist.github.com/CarlosJTorres/057dbf4d8de3095873b15956bdf47935 . Thank you very much. |
This comment has been minimized.
This comment has been minimized.
@alex_shpak i have a secured json link with https. Hiw to handle it? |
This comment has been minimized.
This comment has been minimized.
@jaswanthm that was quite long time ago, so I don't remember why @peterlazar1993 there are no specific requirements on persistence, the simplest I think is to use SharedPreferences settings = ...
String token = settings.getString("token")
settings.edit()
.putString("token", newToken)
.commit() @lalitsonawane can you please provide more details? From what I understood you want to update token via https. |
This comment has been minimized.
This comment has been minimized.
Thnks @alex-shpak, Helped me out alot. |
This comment has been minimized.
This comment has been minimized.
Hi, suppose i want to inject my SharedPreference (where my current token is stored) using dagger. How to do so ?? |
This comment has been minimized.
This comment has been minimized.
my case is token not pushed using header like above, but token is always include in every request as parameter. |
This comment has been minimized.
This comment has been minimized.
Is there a way to do it with observable (rx java)? |
This comment has been minimized.
This comment has been minimized.
I need to do it something like this
|
This comment has been minimized.
This comment has been minimized.
@jaswanthm how to implement refresh token with |
This comment has been minimized.
This comment has been minimized.
Hi.How do you implement the logout function within the interceptor? is The intercpetor standalone class or a part of an activity? |
This comment has been minimized.
This comment has been minimized.
@Kolyall @andrconstruction |
This comment has been minimized.
This comment has been minimized.
@paragones Did you find a way to refresh the token using rxjava? |
This comment has been minimized.
This comment has been minimized.
https://gist.github.com/mpetlyuk/77ac3221c1776d14654374faf2985d5a |
This comment has been minimized.
This comment has been minimized.
Very useful. Thanks! |
This comment has been minimized.
This comment has been minimized.
This is very good. Thanks for sharing this. |
This comment has been minimized.
Is this an application level interceptor or a network level interceptor?