Search code examples
androidiosretrofitpostmanokhttp

Webservice not working in Android Retrofit , but works in Postman and Swift / iOS, Getting 401 Unauthorized


BRIEFING BEFORE 'technical stuff'
Not new to working with Retrofit but came across this strange behaviour which I am having very hard time to understand and fix, I have two web service, both work fine as expected in Postman and iOS but only one works in Retrofit and not the other,
In my defence I can say I am getting (Unauthorized) response,which means I was able to hit the server and get a result
In API developer's defence he says it works in Postman and other devices so not a service issue

If any Retrofit expert out there tell me what retrofit may be doing behind my back in order to get this error?

TECHNICAL STUFF
Talking about the type of service , It contains Authorization Bearer token as header which expires every 6 hours and contains no params at all (so it should be easy, right ?) and a simple url http://hashchuna.nn-assets.com/api/locations
Unfortunately the header token cant be shared with valid key, cos it'l be expired before anyone can try it, but here it's anyway Authorization Bearer 3d44626a55dbb024725984e0d37868336fd7e48a

WHAT I'VE TRIED
I am using okhttp intercept to add Authorization Header to request using both addHeader/header method, no spaces in the url cos there r no params
Getting 401 unauthorized error in retrofit?
Java: Android: Retrofit - using Call but, Response{code = 401,message=unauthorized}
https://github.com/square/retrofit/issues/1290
But non of them helped

WARNING
Now the tricky part to keep in mind, the token when expired must give 401 error which is expected, but the problem is even for freshly created token I get 401 , which is my core problem

LOG

D/OkHttp: --> GET http://hashchuna.nn-assets.com/api/locations http/1.1
D/OkHttp: Authorization: Bearer 7c0d53de006b6de931f7d8747b22442354cecef9
D/OkHttp: --> END GET
D/OkHttp: <-- 401 Unauthorized http://hashchuna.nn-assets.com/api/locations (773ms)
D/OkHttp: Date: Mon, 20 Feb 2017 10:44:11 GMT
D/OkHttp: Server: Apache
D/OkHttp: X-Powered-By: PHP/7.0.15
D/OkHttp: Access-Control-Allow-Origin: *
D/OkHttp: Access-Control-Allow-Credentials: true
D/OkHttp: Access-Control-Max-Age: 1000
D/OkHttp: Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding
D/OkHttp: Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
D/OkHttp: Expires: Thu, 19 Nov 1981 08:52:00 GMT
D/OkHttp: Cache-Control: no-store, no-cache, must-revalidate
D/OkHttp: Pragma: no-cache
D/OkHttp: Set-Cookie: PHPSESSID=u477o8g0q387t92hms4nhc14n1; path=/
D/OkHttp: Vary: Authorization
D/OkHttp: X-Powered-By: PleskLin
D/OkHttp: Keep-Alive: timeout=5
D/OkHttp: Connection: Keep-Alive
D/OkHttp: Transfer-Encoding: chunked
D/OkHttp: Content-Type: application/json;charset=utf-8
D/OkHttp: <-- END HTTP

CODE
Intercept

Request request = chain
                        .request()
                        .newBuilder()
                        //.header("Authorization","Bearer "+ SharedPrefsUtils.getSPinstance().getAccessToken(context))
                        .addHeader("Authorization","Bearer 1ed6b7c1839e02bbf7a1b4a8dbca84d23127c68e")
                        //.addHeader("cache-control", "no-cache")
                        //.cacheControl(CacheControl.FORCE_NETWORK)
                        .build();

Retrofit Instance

private Api getApiInstance(Context context) {
        HttpLoggingInterceptor logInter = new HttpLoggingInterceptor();
        logInter.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient mIntercepter = new OkHttpClient.Builder()
                .addInterceptor(new RequestResponseInterseptor(context))
                .addInterceptor(logInter)
                .build();

        Retrofit retrofitInstance = new Retrofit.Builder()
                //.addConverterFactory(new NullOnEmptyConverterFactory())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(BASE_URL)
                .client(mIntercepter)
                .build();
        return retrofitInstance.create(Api.class);
    }

Solution

  • SOLUTION (its the COOKIE)
    Thanks to some of the tips, the actual reason for Incompatibility of service is , Supposedly POSTMAN and iOS client store and reuse COOKIE all by itself when requests are made without any need for explicit handling, Cookie in Postman can be tested using Postman Intercepter ,but cant be edited because chrome does not allow editing cookie by plugins

    However Retrofit/OkHttp unless specified will consider it disabled(for security reason maybe) ,
    Cookie is added either inside Interseptor as one of the header addHeader("Cookie","KEY-VALUE")
    or
    Use cookieJar to add into

    OkHttpClient mIntercepter = new OkHttpClient.Builder()
                    .cookieJar(mCookieJar)
                    .addInterceptor(new RequestResponseInterseptor(context))
                    .addInterceptor(logInter)
                    .build();
    

    based on your need and cookie type