Last active
June 22, 2016 15:59
-
-
Save gandharva/4f524988ab07a098e56093009db11bca to your computer and use it in GitHub Desktop.
This demo shows a scenario where a secured resource is being accessed and the token has expired. The authenticator of the rest client detects the scenario, gets the new access token using refresh token and continues with the call
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package io.leftshift.app.model; | |
| import com.activeandroid.Model; | |
| import com.activeandroid.annotation.Column; | |
| import com.activeandroid.annotation.Table; | |
| import com.activeandroid.query.Delete; | |
| import com.activeandroid.query.Select; | |
| @Table(name = "Authentication") | |
| public class Authentication extends Model { | |
| private static final String TOKEN_PREFIX = "Bearer "; | |
| //TODO check for data availability else go to login. | |
| @Column (name = "access_token") | |
| public String accessToken; | |
| @Column (name = "refresh_token") | |
| public String refreshToken; | |
| public static boolean detailExists() { | |
| return new Select() | |
| .from(Authentication.class) | |
| .exists(); | |
| } | |
| public static Authentication getDetails() { | |
| return new Select() | |
| .from(Authentication.class) | |
| .executeSingle(); | |
| } | |
| public String getTokenString() { | |
| return TOKEN_PREFIX + accessToken; | |
| } | |
| public static void saveDetails(String accessToken, String refreshToken) { | |
| clearTable(); | |
| Authentication authentication = new Authentication(); | |
| authentication.accessToken = accessToken; | |
| authentication.refreshToken = refreshToken; | |
| authentication.save(); | |
| } | |
| public static void clearTable() { | |
| new Delete().from(Authentication.class).execute(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package io.leftshift.app.network; | |
| import io.leftshift.app.BuildConfig; | |
| import io.leftshift.app.model.Authentication; | |
| import java.io.IOException; | |
| import okhttp3.Interceptor; | |
| import okhttp3.OkHttpClient; | |
| import okhttp3.Request; | |
| import okhttp3.Response; | |
| import okhttp3.logging.HttpLoggingInterceptor; | |
| import retrofit2.Retrofit; | |
| import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; | |
| import retrofit2.converter.gson.GsonConverterFactory; | |
| public class RestClient { | |
| private final Retrofit client; | |
| public RestClient() { | |
| OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); | |
| httpClientBuilder.authenticator(new TokenAuthenticator()); | |
| addAuthorizationInterceptor(httpClientBuilder); | |
| if (BuildConfig.DEBUG) { | |
| HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(); | |
| httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); | |
| httpClientBuilder.addInterceptor(httpLoggingInterceptor); | |
| } | |
| client = new Retrofit.Builder() | |
| .baseUrl(BuildConfig.HOST) | |
| .client(httpClientBuilder.build()) | |
| .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) | |
| .addConverterFactory(GsonConverterFactory.create()) | |
| .build(); | |
| } | |
| private void addAuthorizationInterceptor(OkHttpClient.Builder httpClientBuilder) { | |
| httpClientBuilder.addInterceptor(new Interceptor() { | |
| @Override | |
| public Response intercept(Chain chain) throws IOException { | |
| Request original = chain.request(); | |
| Request.Builder requestBuilder = original.newBuilder() | |
| .headers(original.headers()) | |
| .method(original.method(), original.body()); | |
| if (Authentication.detailExists()) { | |
| Authentication authentication = Authentication.getDetails(); | |
| requestBuilder.addHeader("Authorization", authentication.getTokenString()); | |
| } | |
| Request request = requestBuilder.build(); | |
| return chain.proceed(request); | |
| } | |
| }); | |
| } | |
| public <T> T create(Class<T> apiInterfaceClass) { | |
| return client.create(apiInterfaceClass); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package io.leftshift.app.network; | |
| import io.leftshift.app.parser.RequestToken; | |
| import io.leftshift.app.parser.ResponseToken; | |
| import java.io.IOException; | |
| import okhttp3.Authenticator; | |
| import okhttp3.Request; | |
| import okhttp3.Response; | |
| import okhttp3.Route; | |
| import retrofit2.Call; | |
| public class TokenAuthenticator implements Authenticator { | |
| @Override | |
| public Request authenticate(Route route, Response response) throws IOException { | |
| RetrofitService service = new RestClient().create(RetrofitService.class); | |
| Authentication authentication = Authentication.getDetails(); | |
| RequestToken requestToken = new RequestToken(); | |
| requestToken.setGrantType(RequestToken.GRANT_TYPE_REFRESH_TOKEN); | |
| requestToken.setRefreshToken(authentication.refreshToken); | |
| Call<ResponseToken> call = service.refreshAccessToken(requestToken); | |
| retrofit2.Response<ResponseToken> refreshTokenResponse = call.execute(); | |
| if (refreshTokenResponse.isSuccessful()) { | |
| String accessToken = refreshTokenResponse.body().getAccessToken(); | |
| String refreshToken = refreshTokenResponse.body().getRefreshToken(); | |
| Authentication.saveDetails(accessToken, refreshToken); | |
| authentication = Authentication.getDetails(); | |
| return response.request().newBuilder() | |
| .header("Authorization", authentication.getTokenString()) | |
| .build(); | |
| } else { | |
| return null; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment