Can't get past Django Rest Framework Token Authorization because I can't set withCredentials=true using OkHttp RequestBuilder. (I'm referring to this https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
In javascript using axios.post this works fine. I'm having trouble converting this post request to android using OkHttp request builder.
Request builder only seems to give setter methods for Header and Body of post Request?
Tried reading through OkHttp documentation and I've also tried to send withCredentials=True as a header
Django Rest Framework backend not recognizing the token and not resolving the bearer token to a user.
If no class authenticates, request.user will be set to an instance > of django.contrib.auth.models.AnonymousUser, and request.auth > will be set to None.
I'm going to assume here that withCredentials is a query parameter.
Appending ?withCredentials=true. to the end of the URL will probably get things going for you.
An example in full might look like https://www.example.com?withCredentials=true.
With multiple parameters, it may look like https://www.example.com?withCredentials=true&otherParam=Stuff.
Related
I've been busting my head for about two days now but neither I nor my colleagues seem to be able to disable URL encoding for a client_secret field in a #POST request when using Retrofit. We need to fetch an access token from an API endpoint that requires the following parameters in application/x-www-form-urlencoded format:
grant_type: "client_credentials"
scope: "CustomerService.WebApi"
client_id: "somerandomid"
client_secret: "XX#XXXXXXXXXXXXX"
The issue occurs when the '#' char in the client_secret field gets URL-encoded into %40 and our client's backend can't handle it. Using Postman, this encoding doesn't seem to happen and we successfully get a hit.
Here's what we have tried so far:
Specifying encoded=true inside the #Field/#FieldMap annotation
Removing the #FormUrlEncoded annotation and specifying it manually in the header while using a RequestBody as an In parameter and building the request body using a FormBuilder
Using both #FieldMap and #Field annotations but none of them worked
Setting disableHtmlEscaping() to the Gson instance used by the retrofit client
I've been looking at tons of stack posts and git issues but there doesn't seem to be a fix for POST requests. Some people blame the OkHTTP client, some Gson, and some Retrofit 2. JakeWharton advocates that Retrofit's test regarding the encoded=true flag does indeed work. Does anybody have a clue on how to resolve this?
P.S. Please do not mark this as a duplicate if the associated post doesn't have a valid answer (like most of the posts I've looked at).
OkHttp (and therefore Retrofit) follows this spec that requires # to be percent-escaped when encoded. I expect the same behavior is true of web browsers: they will also encode the # character.
You should direct your server’s maintainers to conform to the corresponding parsing spec. If they cannot, you may need to manually replace %40 with # on your outbound request body, perhaps with an OkHttp interceptor.
When making a request with Retrofit using an OKHttp Client with interceptors to add headers:
(Authorization: Bearer + access_token)
(User-Agent: "user_agetn_as_described_by_reddit")
Using the oauth.reddit.com/.json URL as recommended by Reddit, I get a 403. Now, when I do this same thing on Postman or something similar, I get a 200 and the expected JSON.
Is anyone aware of something related to Android or Retrofit or OKHttp that could be causing me this pain?
I was using the auth code instead of the access_token to make my requests. A mistake from my side. You should use the auth code to make a token request.
I am trying to examine the headers of a response from an API call made via Retrofit 2.0.2 before actually downloading the content.
My API interface looks like the following:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#HEAD("profiles")
Call<Void> getProfileHeaders(#Field("puids") String puid);
Please note that the API call requires me to specify in the body a field called puids=%{UUID} list of UUIDs in order to return a response.
If I would like to download the data without examining the headers first, I would just call an interface like this:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#FormUrlEncoded
#POST("profiles")
Call<String> getProfile(#Field("puids") String puid);
Now the issue is that when I try to use the getProfileHeader() endpoint, I get the following RuntimeException:
java.lang.IllegalArgumentException: #Field parameters can only be used with form encoding. (parameter #1)
In order to use the #Field parameters (as I suppose a POST method would normally would do if required), I would have to explicitly specify that I use #FormUrlEncoded, but I can't make a #HEAD call with that.
I am a bit puzzled how could I achieve what I want and what am I missing?
Basically I would like to know how can I examine a retrofit call's response headers before downloading the actual body, of an API endpoint that requires field parameters?
Cheers!
Ok, I just realized that my confusion originates from a couple of misunderstandings:
#HEAD is an HTTP method to usually verify the hyperlinks validity and the server's response to a GET call. It does not work with POST request and it is theoretically incorrect.
Taken from RFC2616 of the HTTP/1.1 definitions:
The HEAD method is identical to GET except that the server MUST NOT
return a message-body in the response. The metainformation contained
in the HTTP headers in response to a HEAD request SHOULD be identical
to the information sent in response to a GET request. This method can
be used for obtaining metainformation about the entity implied by the
request without transferring the entity-body itself. This method is
often used for testing hypertext links for validity, accessibility,
and recent modification.
The response to a HEAD request MAY be cacheable in the sense that the
information contained in the response MAY be used to update a
previously cached entity from that resource. If the new field values
indicate that the cached entity differs from the current entity (as
would be indicated by a change in Content-Length, Content-MD5, ETag or
Last-Modified), then the cache MUST treat the cache entry as stale.
When making a POST request by definition we already calculated the response server-side and taken the time to download the body in consideration.
One of the function's of the POST method, as defined in RFC2616 is:
Providing a block of data, such as the result of submitting a form, to a data-handling process;
Hence verifying the header in order not do download the body beats the purpose of this.
As mentioned by #Radek above, using interceptors on GET request to modify and/or examine requests on the fly would do the work, but at that point we could also initiate a HEAD method request.
The solution to this problem would be to better align to the standard definitions defined in RFC2616 by making changes on the server-side to instead of returning block of raw data as a POST response, make it to return a resource that would be than called in a GET/HEAD request then. All just refactor the service call to use GET instead of POST.
Okhttp which is used by retrofit has Interceptors which let you modify or examine requests on the fly. Check out the github documentation
someone may asked my question already but I cannot find any suggestions.
I writing an Android app which needs to access my Django server by using HttpsURLConnection then Django server will return a JSON array to Android.
The view function in Django will receive the parameters from request.POST and generate the JSON array then return using HTTPResponse Django method. It does not need any Templates and Forms.
When I call the Django view function from Android, it returns 403 error. I know that it is because the POST data does not contains "csrf_token".
My problem is: How can I get the "csrf_token" and put it into my POST data before I send it to Django? I try disable the CSRF checking by "#csrf_exempt" it can return the correct result to Android app but I would not disable the CSRF checking.
Thanks,
Wilson
You have to send the cookies and also have to send a header 'X-CSRFToken' with csrftoken.
This is what I do (may not be the best way):
Get csrf token via a get request.But first try to see if you get a csrftoken cookie by doing same request on your browser with developer tools. If not, you should use ensure_csrf_cookie decorator
from django.views.decorators.csrf import ensure_csrf_cookie
#ensure_csrf_cookie
def your_view(request):
pass
Now using the same HttpUrlConnection object do this :
String cookieString="";
String csrftoken="";
// The below code can be shortened using for-each loop
List<HttpCookie> cookies=cookieManager.getCookieStore().getCookies();
Iterator<HttpCookie> cookieIterator=cookies.iterator();
while(cookieIterator.hasNext()){
HttpCookie cookie=cookieIterator.next();
cookieString+=cookie.getName()+"="+cookie.getValue()+";";
if(cookie.getName().equals("csrftoken")){
csrftoken=cookie.getValue();
}
}
Add the following to your post request:
urlConnection.setRequestProperty("X-CSRFToken", csrftoken);
urlConnection.setRequestProperty("Cookie", cookieString);
How can I get an authentication for a URL, to which we have to send a request using Retrofit?
This depends on the the authentication method used by the service server.
For example, Twitch.tv provides "Authorization Code Flow" as one of the methods for authentication. In this method you provide the auth parameters in the request URL:
https://api.twitch.tv/kraken/oauth2/authorize
?response_type=code
&client_id=[your client ID]
&redirect_uri=[your registered redirect URI]
&scope=[space separated list of scopes]
Other methods requires specifying the auth parameters in the request header.
If you provide me with more information, regarding the authentication method used by the service you want to talk to, I may be able to provide you with a specific answer, or even with working code (If I have the time).