2

I have an android studio application that connects to a nodejs backend server with user authentication. I can log in and register from my app but it does not store a session. So I can not get session based functionality yet.

I need to add functionality to store a session. For this how do I do this with the retrofit interface. I want to log in start a session so I can have user logged in access to other routes on the server.

Or is there another interface for android studio that will allow for cookies and sessions? Retrofit interface


public interface RetrofitInterface {

            
    @POST("/login")
    Call<Login_result> executeLogin(@Body HashMap<String, String> map);
            
    @POST("/signup")
    Call<Void> executeSignup(@Body HashMap<String, String>map);
            
    @POST("/add_data")
    Call<Void> executeAdd_data(@Body HashMap<String, String>map);
            
    @POST("/logout")
    Call<Void> executeLogout(@Body HashMap<String, String>map);
            
    @GET("/test")
    Call<Void> executeTest();

}
**Main code**

```java


/*Updated this*/
    Context context = this;

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(new OkhttpClient.builder()
                        .addInterceptor(new ReceivedCookiesInterceptor(context)
                                .addInterceptor(new AddCookiesInterceptor(context)
                                ).build())
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
        retrofitInterface = retrofit.create(RetrofitInterface.class);

Log in code


    HashMap<String,String> map = new HashMap<>();
                //map.put("email",emailEdit.getText().toString());//
                map.put("username", usernameEdit.getText().toString());
                map.put("password", passwordEdit.getText().toString());

                Call<Login_result> call = 
                retrofitInterface.executeLogin(map);//Run the post
                call.enqueue(new Callback<Login_result>()
                {

                    @Override
                    public void onResponse(Call<Login_result> call, Response<Login_result> response) {
                        if(response.code() == 200)
                        {
                            /*Login_result result = response.body();
                            AlertDialog.Builder builder1 = new AlertDialog.Builder(MainActivity.this);
                            builder1.setTitle(result.getUsernname());
                            builder1.setMessage(result.getEmail());

                            builder1.show();*/
                            Toast.makeText(MainActivity.this, "Logged in", Toast.LENGTH_SHORT).show();


                        }else if(response.code() == 404)
                        {
                            Toast.makeText(MainActivity.this, "Incorrect usernanme or password", Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(Call<Login_result> call, Throwable t) {
                        Toast.makeText(MainActivity.this, t.getMessage(),Toast.LENGTH_LONG).show();
                    }
                });
Thomas Morris
  • 739
  • 3
  • 24
  • does this questions ans is switable for you? https://stackoverflow.com/questions/38418809/add-cookies-to-retrofit-2-request – Jyotish Biswas Jul 28 '20 at 09:29

1 Answers1

4

You would need to create an two interceptors and store the cookie information in Shared Preferences

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;
    }
}

And then reverse to add cookies to the 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());
    }
}

Which then you would need to change your Retrofit instance to the below

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(new OkhttpClient.builder()
                        .addInterceptor(new ReceivedCookiesInterceptor(context)
                        .addInterceptor(new AddCookiesInterceptor(context) 
                ).build())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        retrofitInterface = retrofit.create(RetrofitInterface.class);
Scott Johnson
  • 705
  • 5
  • 12