28

I'm looking through examples and code but I don't see anything implemented. Is this possible at this stage?

Robert Karl
  • 7,598
  • 6
  • 38
  • 61
LocoMike
  • 5,626
  • 5
  • 30
  • 43
  • I have tested both solutions but still an error 401 https://stackoverflow.com/questions/53839122/volley-basicnetwork-performrequest-unexpected-response-code-401-on-normal-authe – andrea ciuffoli Dec 18 '18 at 18:41

3 Answers3

93

For those who don't want to use Spring for Android just for that, here's how to do it.

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    HashMap<String, String> params = new HashMap<String, String>();
    String creds = String.format("%s:%s","USERNAME","PASSWORD");
    String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT);
    params.put("Authorization", auth);
    return params;
}

Note that you may have to use Base64.NO_WRAP instead of Base64.DEFAULT for this to work. As pointed in the comments.

API 8+

Androiderson
  • 16,865
  • 6
  • 62
  • 72
  • 3
    This is really good as the final size of the APK is very important for small projects. – slott Dec 19 '13 at 09:56
  • 9
    It's worth noting that I needed to use Base64.NO_WRAP instead of Base64.DEFAULT in order for this to work for me. – Logiraptor Apr 04 '14 at 16:36
  • @Logiraptor Your comment helped me to fix 400 error on Andrpiod 2.3 devices. What can be a reason of the issue? – dimetil Sep 03 '14 at 19:07
  • Even i had to use use `Base64.NO_WRAP` instead of `Base64.DEFAULT` for it to work. I am using Play and it gave exception `p.nettyException - Exception caught in Netty java.lang.IllegalArgumentException: Header name cannot contain the following prohibited characters: =,;: \t\r\n\v\f ` when i used `Base64.DEFAULT`. Any idea why? Also please edit your post with this change. – lovesh Dec 09 '14 at 21:01
  • 6
    Yes, you must use NO_WRAP as otherwise it a line break might split the encoded string into two lines which is not allowed for HTTP headers. A line break always indicates a new header line. The second line of the base64 string is not a valid header line causing this exception. – Denis Loh Aug 04 '15 at 06:47
  • This worked for me but I had to use NO_WRAP for it to work – X09 Aug 21 '16 at 20:07
  • So where does this fit into Volley? Do I have to extend StringRequest and override it there? – G_V Aug 25 '16 at 19:54
10

Yes it's possible. You need to override Request.getHeaders(). I'm lazy and I used HttpHeaders and HttpAuthentication from Spring for Android but you can just build the auth header and return it from the method. From getHeaders() you can return the auth header for basic auth. This is a sample request with basic auth.

public class GetUser extends Request<User> {

    private static final String TAG = GetUser.class.getName();

    private Response.Listener<User> mListener;
    private ObjectMapper mMapper = new ObjectMapper();

    public GetUser(Response.ErrorListener errorListener, Response.Listener<User> listener){
        super(Method.GET, PoisUtils.BASE_URL + "/users", errorListener);

        mListener = listener;
    }

    @Override
    protected Response<User> parseNetworkResponse(NetworkResponse response) {
        String jsonString = new String(response.data);
        try {
            User result = mMapper.readValue(jsonString, User.class);
            return Response.success(result, getCacheEntry());
        } catch (IOException e) {
            Log.d(TAG, e.getMessage());
        }
        return null;
    }

    @Override
    protected void deliverResponse(User response) {
        mListener.onResponse(response);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        return AuthUtils.buildAuthHeaders().toSingleValueMap();
    }
}

And here is how I build the auth headers

public static HttpHeaders buildAuthHeaders(){

    if(UserUtils.isUserLogged()){
        HttpHeaders requestHeaders = new HttpHeaders();
        User user = PoisApplication.get().getUser();

        HttpAuthentication auth = new HttpBasicAuthentication(
                user.getUsername(), user.getPassword());
        requestHeaders.setAuthorization(auth);

        return requestHeaders;
    }
    return null;
}
colin
  • 52
  • 9
alex
  • 3,412
  • 2
  • 28
  • 36
  • Thank you for the reply. However, this looks like a very common/basic feature, and I think a library like volley should implement this somehow in an easier way. I'm trying out this library, and it looks promising (really excited about a good caching HTTP library), but I'm finding certain parts that don't make much sense: like I would like the parsing part (json, xml...) be part of the Listener and not the Request, that way I could create my own base Request that will add these headers all the time. Maybe it should be the RequestQueue the one having some default options (headers)... Some ideas. – LocoMike May 29 '13 at 17:10
  • I'm not sure it's what you want to do, but you could create something like this https://gist.github.com/alexmazza/5659606 with the getHeaders() method implemented. I'm using jackson there but you could use Gson or anything else, and then always use that class as a base class for your authenticated requests – alex May 29 '13 at 17:16
  • Yeah, but it if I want to get some JSON data, and later some xml data, I would have to replicate the logic, or create a base class, that has the headers code, and then I would have to create 2 subclasses, and I wouldn't be able to use the default JsonRequest, etc... To me, it looks like response and requests should be in different classes (parsing should belong to the Listener) so that you could mixed them up. Inheritance issues! ;) Thanks for the reply anyway. – LocoMike May 29 '13 at 18:12
  • Hi again, I'm trying to do this manually, so when curling my url, authorization works with something like -H "Authorization: Basic " ( being Base 64 encoded versino of user:passw). However, if I return a map containing a key "Authorization" and a value for that key "Basic ", volley still returns an error. Is there a specific format I need to follow? Thank you! – LocoMike Jun 04 '13 at 21:24
  • 2
    I found this https://github.com/njzk2/VolleyTwitter/blob/master/src/com/njzk2/twitterbrowser/TokenRequest.java – alex Jun 04 '13 at 22:01
  • Awesome, I found the same link a while ago and it is working like a charm! Thanks! – LocoMike Jun 05 '13 at 01:37
  • Why bother responding if you're lazy? :) – kishu27 Feb 21 '15 at 02:29
0

For a proxy authorization (like squid) use this header :

String credentials = proxyUsername + ":" + proxyPassword;
String auth = "Basic "  + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);                
headers.put("Proxy-Authorization", auth);
earlypearl
  • 596
  • 6
  • 10