Retrofit and OkHttp basic authentication
Find the Solution
1.Write a Interceptor class
import java.io.IOException;import okhttp3.Credentials;import okhttp3.Interceptor;import okhttp3.Request;import okhttp3.Response;public class BasicAuthInterceptor implements Interceptor { private String credentials; public BasicAuthInterceptor(String user, String password) { this.credentials = Credentials.basic(user, password); } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request authenticatedRequest = request.newBuilder() .header("Authorization", credentials).build(); return chain.proceed(authenticatedRequest); }}
2.Finally, add the interceptor to an OkHttp client
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new BasicAuthInterceptor(username, password)) .build();
Retrofit 2
public class ServiceGenerator { public static final String API_BASE_URL = "https://your.api-base.url"; private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(API_BASE_URL) .addConverterFactory(GsonConverterFactory.create()); private static Retrofit retrofit = builder.build(); public static <S> S createService(Class<S> serviceClass) { return createService(serviceClass, null, null); } public static <S> S createService( Class<S> serviceClass, String username, String password) { if (!TextUtils.isEmpty(username) && !TextUtils.isEmpty(password)) { String authToken = Credentials.basic(username, password); return createService(serviceClass, authToken); } return createService(serviceClass, null); } public static <S> S createService( Class<S> serviceClass, final String authToken) { if (!TextUtils.isEmpty(authToken)) { AuthenticationInterceptor interceptor = new AuthenticationInterceptor(authToken); if (!httpClient.interceptors().contains(interceptor)) { httpClient.addInterceptor(interceptor); builder.client(httpClient.build()); retrofit = builder.build(); } } return retrofit.create(serviceClass); }}
Retrofit 1.9
public class ServiceGenerator { public static final String API_BASE_URL = "https://your.api-base.url"; private static RestAdapter.Builder builder = new RestAdapter.Builder() .setEndpoint(API_BASE_URL) .setClient(new OkClient(new OkHttpClient())); public static <S> S createService(Class<S> serviceClass) { return createService(serviceClass, null, null); } public static <S> S createService(Class<S> serviceClass, String username, String password) { if (username != null && password != null) { // concatenate username and password with colon for authentication String credentials = username + ":" + password; // create Base64 encodet string final String basic = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); builder.setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addHeader("Authorization", basic); request.addHeader("Accept", "application/json"); } }); } RestAdapter adapter = builder.build(); return adapter.create(serviceClass); }}
AuthenticationInterceptor.java
public class AuthenticationInterceptor implements Interceptor { private String authToken; public AuthenticationInterceptor(String token) { this.authToken = token; } @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); Request.Builder builder = original.newBuilder() .header("Authorization", authToken); Request request = builder.build(); return chain.proceed(request); }}
Usage
Retrofit 2
Interface
public interface LoginService { @POST("/login") Call<User> basicLogin();}
Requester
LoginService loginService = ServiceGenerator.createService(LoginService.class, "user", "secretpassword");Call<User> call = loginService.basicLogin(); call.enqueue(new Callback<User >() { @Override public void onResponse(Call<User> call, Response<User> response) { if (response.isSuccessful()) { // user object available } else { // error response, no access to resource? } } @Override public void onFailure(Call<User> call, Throwable t) { // something went completely south (like no internet connection) Log.d("Error", t.getMessage()); }}
Retrofit 1.9
Interface
public interface LoginService { @POST("/login") void basicLogin(Callback<User> cb);}
Requester
LoginService loginService = ServiceGenerator.createService(LoginService.class, "user", "secretpassword");loginService.basicLogin(new Callback<User>() { @Override public void success(User user, Response response) { // user object available } @Override public void failure(RetrofitError error) { // handle errors, too }});
add header interceptor
public class HeaderInterceptor implements Interceptor { private PreferencesRepository mPrefs; private String mAuth; public HeaderInterceptor(PreferencesRepository p) { mPrefs = p; } @Override public Response intercept(Chain chain) throws IOException { mAuth = (mPrefs.getAuthToken() != null)?mPrefs.getAuthToken():""; Request r = chain.request() .newBuilder() .addHeader("Accept", "application/json") // authorization token here .addHeader("Authorization", "Bearer" + mAuth) .build(); return chain.proceed(r); }}
add cacheinterceptor (optional)
public class CacheInterceptor implements Interceptor { Context mContext; public CacheInterceptor(Context context) { this.mContext = context; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (request.method().equals("GET")) { if (DeviceUtils.isConnected(mContext)) { request = request.newBuilder() .header(Constant.CACHE_CONTROL, "only-if-cached") .build(); } else { request = request.newBuilder() .header(Constant.CACHE_CONTROL, "public, max-stale=2419200") .build(); } } Response originalResponse = chain.proceed(request); return originalResponse.newBuilder() .header(Constant.CACHE_CONTROL, "max-age=600") .build(); }}
implement it
HttpLoggingInterceptor logger = new HttpLoggingInterceptor();logger.setLevel(HttpLoggingInterceptor.Level.BODY);long SIZE_OF_CACHE = 10 * 1024 * 1024; // 10 MiBCache cache = new Cache(new File(mContext.getCacheDir(), "http"), SIZE_OF_CACHE);new OkHttpClient.Builder() .addInterceptor(logger) .addInterceptor(new HeaderInterceptor(u)) .cache(cache) .addNetworkInterceptor(new CacheInterceptor(mContext)) .connectTimeout(Constant.CONNECTTIMEOUT, TimeUnit.SECONDS) .readTimeout(Constant.READTIMEOUT, TimeUnit.SECONDS) .writeTimeout(Constant.WRITETIMEOUT, TimeUnit.SECONDS) .build();