Retrofit: Retrofit does not set Authorization in header

Created on 24 Jul 2015  Â·  14Comments  Â·  Source: square/retrofit

I'm working with

compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.okhttp:okhttp-urlconnection:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'

I'm setting RequestInterceptor like this:

RequestInterceptor requestInterceptor = new RequestInterceptor() {
    @Override
    public void intercept(RequestFacade request) {
        request.addHeader("Authorization", "Basic eHh4Onl5eXk=");
    }
};

RestAdapter restAdapter = new RestAdapter.Builder()
    .setLogLevel(RestAdapter.LogLevel.FULL)
    .setEndpoint("https://...")
    .setRequestInterceptor(requestInterceptor)
    .build();

AuthService authService = restAdapter.create(AuthService.class);

authService.authorize(new Callback<WhoAmI>() {
    @Override
    public void success(WhoAmI whoAmI, Response response) {
        Log.i(TAG, "AuthService success" + response);
    }

    @Override
    public void failure(RetrofitError error) {
        Log.i(TAG, "AuthService failure" + error);
    }
});

AuthService is:

public interface AuthService {

    @GET("/authorize")
    void authorize(Callback<WhoAmI> callback);
}

So when authorize is called then intercept(RequestFacade request) IS called, but I'm getting 401 from the server. I'm able to fix it with setting OkClient like this:

OkHttpClient client = new OkHttpClient();
client.setAuthenticator(new Authenticator() {
    @Override
    public Request authenticate(Proxy proxy, com.squareup.okhttp.Response response) throws IOException {
        return response.request().newBuilder().header("Authorization", "Basic eHh4Onl5eXk=").build();
    }

    @Override
    public Request authenticateProxy(Proxy proxy, com.squareup.okhttp.Response response) throws IOException {
        return null;
    }
});

RestAdapter.Builder authorizeServiceBuilder = new RestAdapter.Builder()
    .setClient(new OkClient(client)));

In this case when authorize is called then intercept(RequestFacade request) IS called and then authenticate(Proxy proxy, com.squareup.okhttp.Response response) IS called and I get valid response from the server (302 in my case).

In both cases when I look at logcat logs I see that Retrofit does set the authentication

07-23 09:12:10.736  12630-16274/com.my.super.app.debug D/Retrofit﹕ Authorization: Basic eHh4Onl5eXk=

or at least it logs it does.

I've also tried to use @Header("Authorization") in AuthService:

public interface AuthService {

    @GET("/authorize")
    void authorize(@Header("Authorization") String authorization, Callback<WhoAmI> callback);
}

and in call to authorize

authService.authorize("Basic eHh4Onl5eXk=", new Callback<WhoAmI>() {
    @Override
    public void success(WhoAmI whoAmI, Response response) {
        Log.i(TAG, "AuthService success" + response);
    }

    @Override
    public void failure(RetrofitError error) {
        Log.i(TAG, "AuthService failure" + error);
    }
});

but result fails as well.

Most helpful comment

I have the same issue. Have you found any workaround in Okhttp so far?

All 14 comments

What are you saying the problem here is? That the header is not being sent? Have you used something like Charles Proxy to inspect the HTTP request after it leaves the client? Retrofit's logs are a best guess of what the underlying HTTP client will send, but it's not guaranteed (the client is free to do whatever it wants). In this case, however, OkHttp should pass along everything logged.

I've checked with Charles proxy and here are the results. When I use @Header("Authorization") and don't add OKHttp's Authenticator the flow is:

  • GET with "Authorization" header properly set - I'm getting 302 (this is expected response from the server)
  • redirection is done but this time "Authorization" header is not added to the request and this is the reason of 401

So it seems that "Authorization" header is set only for the very first GET and not for further redirections. And this is why adding OKHttp's Authenticator solves the problem.

"It seems that "Authorization" header is set only for the very first GET and not for further redirections."
Any news on this problem?

I was having the same problem and this seemed to fix the issue.

Set the authToken as a string.format of the required format i.e

String basic = "Basic %s";
String authToken = "eHh4Onl5eXk=";

request.addHeader("Authorization", String.format(basic, authToken);

Its to do with the whitespace between 'Basic' and the authToken not being understood correctly. Or at least to me thats what it looks like is the cause.

@otormaigh The clue is that in my case I have redirections, see https://github.com/square/retrofit/issues/977#issuecomment-127175210.

@farmazon3000 sorry, my bad.

You could use the OkHttp authenticator. It will get called if there is a 401 error returned. So you could use it to re-authenticate the request.

@otormaigh If you see my 1st post you'll note that this is exactly what I do but I treat is as a workaroud.

@farmazon3000 I feel like an ass now. Sorry.

I see that this is intentional in OkHttp:
https://github.com/square/okhttp/blob/7cf6363662c7793c7694c8da0641be0508e04241/okhttp/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java

        // When redirecting across hosts, drop all authentication headers. This
        // is potentially annoying to the application layer since they have no
        // way to retain them.
        if (!sameConnection(url)) {
          requestBuilder.removeHeader("Authorization");
        }

Redirections never make it to Retrofit's layer and the header is being included in the outgoing requests so I'm going to close the issue because there's nothing to do. If you have issue with the OkHttp behavior you can file an issue on its project or ask on StackOverflow with the 'okhttp' tag if you're looking for something like a workaround (maybe something with a network interceptor?).

I have the same issue. Have you found any workaround in Okhttp so far?

What is WhoAmI ?

@Khamphai I would guess it is the model class for response from API service call. The endpoint could do anything. But... https://en.wikipedia.org/wiki/Whoami

I had same issue too. maybe interception sometimes not invoked!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zheangrybear picture zheangrybear  Â·  3Comments

chriskessel picture chriskessel  Â·  3Comments

bhagyasri picture bhagyasri  Â·  3Comments

JerzyPuchalski picture JerzyPuchalski  Â·  3Comments

Ne1c picture Ne1c  Â·  3Comments