android - volley error No authentication challenges found
Asked Answered
T

5

11

I am trying to work with some legacy code and have come up against an issue when using volley.

I am trying to get to an api that our main site has and it works fine for one account, but not another. I'm trying to work out what the differences might be in the request URL/headers and also what is coming back in the response, but I can't seem to find a way in the volley code to print this to the log.

The error I'm getting is

com.android.volley.NoConnectionError: java.io.IOException: No authentication challenges found

I've read around that this might be due to a 401 response, but I don't really know what that means or at least how to prove/test that. I am really confused that it works for one account and not another.

The url is slightly different as one is for our UK site and the other our AM, but other than that there is no difference.

Thanks

Transceiver answered 16/12, 2013 at 17:12 Comment(7)
it's an Error indicating that no connection could be established when performing a Volley request.Gaudy
@Gaudy do you know if there is anyway of getting more info than that? Any response details etc?Transceiver
no connection could be established. if there no connection where is chance for getting responseGaudy
@bbalazs I don't think that helps, I've already read that. I don't think that's volley related.Transceiver
@Gaudy what makes you think that no connection could be established? I thought it was when authentication wasn't matchingTransceiver
@RussWheeler check the source @SuppressWarnings("serial") public class NoConnectionError extends NetworkError { public NoConnectionError() { super(); } public NoConnectionError(Throwable reason) { super(reason); } } and there is a comment saying /** * Error indicating that no connection could be established when performing a Volley request. */Gaudy
It has nothing to do with Network Connection, there was an error reading a header in the response when 401 was given. See here: #12932291Handley
H
8

This error happens because the server sends a 401 (Unauthorized) but does not give a "WWW-Authenticate" which is a hint for the client what to do next. The "WWW-Authenticate" Header tells the client which kind of authentication is needed (either Basic or Digest). This is usually not very useful in headless HTTP clients, but that's how the standard is defined. The error occurs because the lib tries to parse the "WWW-Authenticate" header but can't.

Possible solutions if you can change the server:

  • Add a fake "WWW-Authenticate" header like: WWW-Authenticate: Basic realm="fake". This is a mere workaround not a solution, but it should work and the HTTP client is satisfied.
  • Use HTTP status code 403 instead of 401. Its semantic is not the same and usually when working with login 401 is a correct response (see here for a detailed discussion) but its close enough.

Possible solutions if you can't change the server:

As @ErikZ wrote in his post you could use a try&catch

HttpURLConnection connection = ...;
try {
    // Will throw IOException if server responds with 401.
    connection.getResponseCode(); 
} catch (IOException e) {
    // Will return 401, because now connection has the correct internal state.
    int responsecode = connection.getResponseCode(); 
}

I also posted this here: java.io.IOException : No authentication challenges found

Handley answered 3/2, 2014 at 17:56 Comment(5)
I'm trying to send a header with Digest authentication, but can't figured out how to do it (still searching for an answer). Do you have any sample on how to do a Digest (or even basic) authentication in Android-Volley?Fibrilliform
Basic and Digest is just putting a header that looks like this "Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" in Basic and more complicated in digest - this is not special to volley, you just put set headers (google on how to do that in volley)Handley
I'm sorry I asked this question so long ago I don't even remember what it relates to, plus that legacy project has been shut down. I'll upvote your answer for effort you've put in, but have no way of checking it's right so won't select it as the answer I'm afraid.Transceiver
Fair enough. Ill leave it since it took me quite a while to understand the problem - learning REST/HTTP spec isn't sometimes as straight forward as you think :)Handley
how to add WWW-Authenticate header in the server responseBillon
M
8

Indeed, I have solved this problem by including the WWW-Authenticate header in the server response.

However, if you add the header WWW-Authenticate: Basic realm="" and your API is also consumed by web clients, some web browsers will trigger a pop up asking for basic credentials.

For me the right solution has been using a custom scheme. As explained in this blog post, I use xBasic instead of Basic in the header response.

WWW-Authenticate: xBasic realm=""

With this header, not only Volley parses the response correctly, but I also avoid web browsers showing the authentication pop up.

Militiaman answered 28/8, 2014 at 19:20 Comment(4)
I'm sorry I asked this question so long ago I don't even remember what it relates to, plus that legacy project has been shut down. I'll upvote your answer for effort you've put in, but have no way of checking it's right so won't select it as the answer I'm afraid.Transceiver
@Russ No problem! Just wanted to help other people looking for an answer :)Militiaman
Just a note to accompany this. You can use any string for the scheme (eg. xBasic as above), but the realm="" (including quotes) must also be included to avoid the exception being thrown.Figurant
how to add WWW-Authenticate header in the server responseBillon
J
0

I was able to catch this client-side when initializing the volley RequestQueue:

Volley.newRequestQueue(getApplicationContext(), new HurlStack() {
        @Override
        public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) {
            try {
                return super.performRequest(request, additionalHeaders);
            } catch (AuthFailureError authFailureError) {
                authFailureError.printStackTrace();
                // Log out / whatever you need to do here
            } catch (IOException e) {
                e.printStackTrace();
                if (e.getMessage().equals("No authentication challenges found")) {
                    // This is the error.  You probably will want to handle any IOException, not just those with the same message.
                }
            }
            return null;
        }
});
Janniejanos answered 10/2, 2015 at 21:51 Comment(0)
L
0

If Server crashed, you may face this problem. Steps:

  1. Stop the tomcat server

  2. goto Run -> Services -> restart your database (ex: postgres)

  3. Start the tomcat server.

Lepidopteran answered 23/3, 2016 at 11:36 Comment(0)
H
0

You can check e is instanceof AuthFailureError.

Log.e(TAG, "AuthFailureError: " + (e instanceof AuthFailureError));
Hilltop answered 17/10, 2016 at 16:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.