0

I'm familiar with how to use dynamic URLs with Retrofit2 but having issue sending username & password in the request. The webAPI works by entering a URL, a login prompt appears on the screen for a username & password, after authentication a JSON response is displayed. The interface is defined for a dynamic URL:

@GET
public Call<User> getJSON(@Url String string);

My request is as follows:

Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(API_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    LoginService service = retrofit.create(LoginService.class);

    Call<User> call = service.getJSON("https://username:password@api.url.com/");

    call.enqueue(new Callback<User>() {
        @Override
        public void onResponse(Call<User> call, retrofit2.Response<User> response) {
            System.out.println("Response status code: " + response.code());

I'm certain the URL is correct as it works in the browser & but I keep getting error the username & password aren't correct?

I/System.out: Response status code: 401

Also, as far as I can tell I can only use @GET rather than @POST because whenever I try @POST the response code is:

I/System.out: Response status code: 405

At first I tried to follow something similar to this post using an encoded flag because it's an example of how to use @PATH & @URL with Retrofit2 but didn't have any success. That's why I tried the username:password@ prepend to the URL. Most of the other examples all use the @POST method.

Any feedback or ideas on how I can authenticate? Thanks

Community
  • 1
  • 1
JC23
  • 1,248
  • 4
  • 18
  • 28

2 Answers2

2

Not sure how to do it in retrofit, but you can add it via an OkHttp interceptor --

OkHttpClient client = new OkHttpClient().newBuilder().addNetworkInterceptor(
    new Interceptor() {
      @Override
      public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request();
        HttpUrl url = request.url();
        url = url.newBuilder().username("username").password("password").build();
        Request newRequest = request.newBuilder().url(url).build();
        return chain.proceed(newRequest);
      }
    }
).build();

be sure to add this client to your retrofit instance --

Retrofit retrofit = new Retrofit.Builder()
        .client(client)
        .baseUrl(API_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
iagreen
  • 31,470
  • 8
  • 76
  • 90
0

Another way to use basic authentication with Retrofit2 would be to pass the authentication string as an argument to your interface method.

So you would change the method signature to:

@GET
public Call<User> getJSON(@Url String string, @Header("Authorization") String myAuthString);

And then call it like this:

Call<User> call = service.getJSON("https://api.url.com/", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");

Where you substitute QWxhZGRpbjpvcGVuIHNlc2FtZQ== for your Base64-encoded username:password string.

If you need to pass the username and password for every API call and want to keep the method signatures clean, it might be better to use the custom OkHttpInterceptor method instead.

Craig Brown
  • 1,891
  • 1
  • 24
  • 25