I want to use Http Digest with Volley. So far I have used the following code:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s","admin","mypass");
String auth = "Digest " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
params.put("Authorization", "Digest " +auth);
return params;
}
So far I get a response from server as wrong credentials which means that authentication is working but only wrong credentials are getting passed. But my credentials are right.
You use Base64 encoding which is fine for Basic Auth but this is not how digest works.
Digest & Basic Auth specs can be found here: https://www.rfc-editor.org/rfc/rfc2617
the newer Digest Specs can be found here: https://www.rfc-editor.org/rfc/rfc7616
And nice extra explanation on wikipedia here: https://en.wikipedia.org/wiki/Digest_access_authentication
For Volley implementation of Digest Auth you can use:
http://www.java2s.com/Open-Source/Android_Free_Code/Framework/platform/com_gm_android_volleyHttpDigestStack_java.htm
You will just need to pass this http stack when you create your Network which you then use to create your RequestQueue:
RequestQueue requestQueue;
requestQueue = new RequestQueue(
new DiskBasedCache(rootDir),
new BasicNetwork(new HttpDigestStack())
);
requestQueue.start();
Related
So I'm running into a problem when calling rest-auth/user/.
I am able to login and obtain the key from said login, but from that I'm not sure how to use it in regards to rest-auth/user/. I've tried using it with GET in volley, as well as POSTing it in volley. But everytime I try to do so, I get a 403 back saying credentials were not provided. I've also tried saving the token to Android's SharedPreferences.
I'm not sure what could be wrong or how to fix this problem, so any help would be appreciated.
My code looks like this:
getUserQueue = Volley.newRequestQueue(this);
JSONObject jsObj = new JSONObject();
try {
jsObj.put("token", token);
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, "http://hurst.pythonanywhere.com/supportal/rest-auth/user/", jsObj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
result = response.getString("username");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
// add the request object to the queue to be executed
getUserQueue.add(jsObjRequest);
From comments it is clear that you are using different authentication schemes for rest, will explain these,
SessionAuthentication
For authenticating session authentication you need persistant cookie implementation in android volley, check here for this, where Set-Cookie header is parsed from server api response & send over next requests.
BasicAuthentication
In Basic authentication scheme, username & password are send over every request ( after login ?), with Authorization header value ( Base64 encoded).To check how to implement this check here
#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;
}
JSONWebTokenAuthentication
In JWT authentication scheme, after successful login you will get a JWT token, you need to send this token in every request that need user authorization, for this to work, set Authorization header value with JWT token_after_login;Only difference with Basic authentication is how header is send.
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String auth = "JWT " + token // token you will get after successful login
params.put("Authorization", auth);
return params;
}
So I am building an Android app which talks to an API.
Whenever a user logs in, I see the response in the log cat which contains the user details including the authentication token but the user gets unauthorized access although the login is successful.
My question is; how do I authorize the user? How do I save the token header in android using volley? This concept is new to me. Please help.
After you login, you need to save the session cookie, access token or whatever your api provides. I usually use SharedPreferences.
Later within your next api Request, you need to override the getHeaders();
JsonObjectRequest volleyRequest = new JsonObjectRequest(url, null, responseListener, errorListener){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<>();
// put your accesstoken if available
params.put("X-CSRF-Token", accessToken);
// put a session cookie if available
params.put("cookie", sessionName + "=" + sessionId);
return params;
}
};
I'm trying to make a GET request in an Android application using the Volley library. This GET request is to verify account credentials using Basic HTTP Authentication. I verified the URL with credentials works in my browser as it returns successful XML. The format is:
http://username:password#myanimelist.net/api/account/verify_credentials.xml
where username and password obviously represent real user credentials. Volley throws this error:
BasicNetwork.performRequest: Unexpected response code 401 for http://username:password#myanimelist.net/api/account/verify_credentials.xml
Here is my Android code that handles the request:
private static final String HTTP_PRE = "http://";
private static final String VERIFY_CREDENTIALS = "myanimelist.net/api/account/verify_credentials.xml";
public void verifyCredentials(String username, String password) {
RequestQueue queue = Volley.newRequestQueue(context);
String url = HTTP_PRE + username + ":" + password + "#" + VERIFY_CREDENTIALS;
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
processResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// handle error
Log.d(TAG, "error: " + error.getMessage());
}
});
queue.add(stringRequest);
}
This solution to override the getHeaders() method provided the same result:
How does one use Basic Authentication with Volley on Android?.
Here is my implementation of that solution:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = super.getHeaders();
if (params == null){
params = new HashMap<>();
}
String creds = String.format("%s:%s", username, password);
params.put("Authorization", creds);
return params;
}
Which returned this error without the credentials built directly into the URL:
BasicNetwork.performRequest: Unexpected response code 401 for http://myanimelist.net/api/account/verify_credentials.xml
If someone could provide advice, I'd really appreciate it. This is my first time using Basic HTTP Authentication so I could be missing something obvious.
I solved this problem following the first answer here: Http Authentication in android using volley library. I had tried something similar and many other solutions but this was the only one that worked.
Basic Authentication uses BASE64 encoding. You're missing
String creds = String.format("%s:%s", username, password);
creds = Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
The Authorization HTTP header requires to indicate the method used (Basic|Digest). At last you headers should look like this:
GET http://username:password#myanimelist.net/api/account/verify_credentials.xml
Accept: text/xml,text/plain
...
Authorization: Basic XXXXXXXXXXXXXX==
Any one can help me for implement digest authentication using Google Volley for web service calling (REST).
basically Volley is using SHA1 authentication(Basic Auth), But is there any way to modify with digest Auth (MD5).
Both HTTP-authentications use simple header entities. I have not tried this by myself, but i assume all you need to implement is to provide header with Digest-specific format in your custom request like this:
public class MyRequest<T> extends Request<T> {
...
#Override
public Map<String,String> getHeaders() throws AuthFailureError {
Map<String,String> headers = new HashMap<String,String>();
headers.put("Authorization", "Digest " + getAuthorizationData());
return headers;
}
...
}
I hope it'll help you
The best solution for you is, indeed, use the HttpDigestStack. You can find the docs right here: http://www.java2s.com/Open-Source/Android_Free_Code/Framework/platform/com_gm_android_volleyHttpDigestStack_java.htm
All you have to do is to provide a new instance of a HttpDigestStack as an additional parameter when creating a new RequestQueue using Volley. You can follow this example:
Volley.newRequestQueue(context, new HttpDigestStack());
I am trying to POST a JSON body using Volley in Android and after spending many hours with no success I am writing this question.
Following is mine code snippet
StringRequest residentSyncRequest = new StringRequest(Request.Method.POST, Commons.URL,this,this,ADD_REQ){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String,String> params = new HashMap<String, String>();
params.put("Content-Type","application/json");
return params;
}
#Override
public byte[] getBody() throws AuthFailureError {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
SharedPreferences sharedPreferences = getActivity().getSharedPreferences(Commons.PREF_NAME, Context.MODE_PRIVATE);
try {
jsonObject.put("RowID","0");
jsonObject.put("LocalID","100");
jsonObject.put("LoginUserID",sharedPreferences.getString(Commons.pref_loginUserId,""));
jsonObject.put("AppToken",sharedPreferences.getString(Commons.pref_appToken,""));
} catch (JSONException e) {
e.printStackTrace();
}
jsonArray.put(jsonObject);
return jsonArray.toString().getBytes();
}
};
VollyRequest.getRequestQueue(getActivity()).add(residentSyncRequest);
and I am getting following response
E/Volley﹕ [255] BasicNetwork.performRequest: Unexpected response code 400 for ...
I tried to call the same web service using postman chrome extension and the service is working just fine.
Not sure if I need to do any encoding before returning byte[].
Please help.
Thanks in advance.
Volley doesn't support JsonArray request directly like JsonObject request.Hope they can add this function in next version because there are a lot of api only provide JsonArray.
EDIT:
Actually there is a solution here.
Volley by default puts all post parameters as JSON Values, so you just need to use a Request and not StringRequest and just add all JSON Values you want to post as regular post values.