How to handle cookies with retrofit in android

Dileep
3 min readJan 12, 2020

--

We used cookies to keep track of users. cookies are the main way to store information about users who were visiting your site.

User-agent(browser) handles cookies automatically but there is no user-agent in android. So android unable to store cookies. So we have to do it manually using interceptors.

I am using

  1. Retrofit to hit api request (Async)
  2. Two Interceptor to send and receive cookies
  3. We used shared preference as local storage to store cookies.

Fundayou have to store all the cookies in shared preference from an incoming response and add that again in outgoing requests.

First create two classes which implements Interceptor interface(implement intercept method). One class intercept incoming traffic and other intercepts outgoing traffic.

CookieReceiver

public class ReceivedCookiesInterceptor implements Interceptor {

private Context context;
public ReceivedCookiesInterceptor(Context context) {
this.context = context;
}

@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());

if (!originalResponse.headers("Set-Cookie").isEmpty()) {
HashSet<String> cookies = (HashSet<String>) PreferenceManager.getDefaultSharedPreferences(context).getStringSet("PREF_COOKIES", new HashSet<String>());

for (String header : originalResponse.headers("Set-Cookie")) {
cookies.add(header);
}

SharedPreferences.Editor memes = PreferenceManager.getDefaultSharedPreferences(context).edit();
memes.putStringSet("PREF_COOKIES", cookies).apply();
memes.commit();
}

return originalResponse;
}
}

We just create a ReceivedCookiesInterceptor implement with the Interceptor interface and override its intercept method. Get the response from request and fetch Set-Cookie header value from it.

We used HashSet to store all then key-value pairs in the set-cookies header. and store it in shared preferences and return response after store cookies in shared preference.

CookieSender

Cookies handler in outgoing request
public class AddCookiesInterceptor implements Interceptor {

public static final String PREF_COOKIES = "PREF_COOKIES";
private Context context;

public AddCookiesInterceptor(Context context) {
this.context = context;
}

@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();

HashSet<String> preferences = (HashSet<String>) PreferenceManager.getDefaultSharedPreferences(context).getStringSet(PREF_COOKIES, new HashSet<String>());

Request original = chain.request();
if(original.url().toString().contains("distributor")){
for (String cookie : preferences) {
builder.addHeader("Cookie", cookie);
}
}

return chain.proceed(builder.build());
}
}

In the same way, we create an AddCookiesInterceptor implement with the Interceptor interface and override its intercept method and create a new request builder.

Now get the all key-values from shared preference in which we store cookies in earlier requests and add as header in request builder.

I want to send cookies only apis whose url contains distributor so i add a if else condition.

You can set what you want as header here. like if you want special auth for specific api in header. put it here

after that proceed this builder with chain interceptor and we are good to go.

One more thing you have to attach these interceptors with retrofit during generate retrofit instance (given below).

public class RetrofitAdapter {

public static Retrofit retrofit = null;


public static Retrofit getinstance(String baseUrl, Context context)
{
OkHttpClient client = new OkHttpClient();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.addInterceptor(new AddCookiesInterceptor(context)); // VERY VERY IMPORTANT
builder.addInterceptor(new ReceivedCookiesInterceptor(context)); // VERY VERY IMPORTANT
builder.addInterceptor(logging);
client = builder.build();

if(retrofit==null)
{
retrofit = new Retrofit.Builder().
baseUrl(baseUrl).
addCallAdapterFactory(RxJava2CallAdapterFactory.create()).
addConverterFactory(GsonConverterFactory.create()).
client(client).
build();
}
return retrofit;
}

}

Cookie expire

In this case, TTL (time to live) for cookie is handled by server. so for cookie expire flow we have to check is this cookie expired or not on the server. ( we can store cookies in our database and also store when it will expire). if it expired then don’t send it with api.

Hope this will help.

--

--

Dileep
Dileep

Written by Dileep

Passionate about coding, cyber security | Software Engineer | IIT Roorkee.

Responses (3)