I'm trying to figure out if it is and how possible to initiate a connection with Authorization that avoids getting a 401 back from the server on the initial call.
According to the RFC (https://www.ietf.org/rfc/rfc4559.txt, end of section 4.2), the client should be able to send, with the initial request, an Authorization header containing a token, but for me that doesn't work. I've tried sending the same token (seems to be always the same) that is usually sent as a response to the first 401, but no luck.
Is there something in the configuration that needs to be changed to allow such behavior or do I need a different token?
Related
The title sums it all up nicely. I'm asking for the conditions that should be met so Spring decides to send back a Set-Cookie:XSRF-TOKEN=... response header.
I can see that lots of my requests are getting back responses with such header while it is not needed. For instance, when I send a GET request it gets a response with that header set even though I had set the X-XSRF-TOKEN for the request. But for the POST request having the mentioned request header will stop Spring from sending back the set-cookie header. So I wonder what are the conditions that should be met so Spring decides to send back one.
I spent some time tracing Spring Security's source code and I managed to find out the answer myself.
First of all, I didn't know how CSRF works and tracing the code helped me understand it completely. And I think this is something worth knowing. Here's the scenario of requests and responses sent and received from CSRF point of view:
The first request is sent to the server. Since it's the first one, it has no cookie or header set.
Regardless of the request's method, the server (in here Spring Security) looks into the incoming request. If there's no cookie sent to the server under the name XSRF-TOKEN, it will generate a SET COOKIE header on the response's way back.
The client receives the cookie and for the second request, it will add a header to the request under the name X-XSRF-TOKEN set to the same value as the cookie received. Of course, the cookie will be sent to the server with the second request automatically.
When the server receives the second request, this time it has a XSRF-TOKEN cookie, so it will look for a X-XSRF-TOKEN header and the request is considered valid only if these two strings match.
And as for the answer to my question, as I mentioned in step two, the cookie is generated if there's no cookie sent (with XSRF-TOKEN name) to the server. And it does not rely on any other factor - what so ever!
I want to customise OAuth Endpoint URI's.
I want to sent parameters in post body instead of query params.
now my request is like -
example.com/oauth/token?grant_type=password&client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&username={USERNAME}&password={PASSWORD}
But I want it like this.
example.com/oauth/token
Request body -
{
grant_type=password,
client_id={CLIENT_ID},
client_secret={CLIENT_SECRET},
username={USERNAME},
password={PASSWORD}
}
How should I do it?
The token endpoint of a properly-implemented authorization server does NOT accept GET requests because RFC 6749, "3.2. Token Endpoint" says as follows:
The client MUST use the HTTP "POST" method when making access token requests.
So, your authorization server's token endpoint should reject GET requests.
RFC 6749, "4.3. Resource Owner Password Credentials Grant" says that request parameters of a token request using Resource Owner Password Credentials flow should be embedded in the request body in the format of "application/x-www-form-urlencoded". The following is an excerpt from "4.3.2. Access Token Request".
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
Therefore, you don't have to customize your authorization server. If the server is implemented correctly, its token endpoint accepts POST requests.
The token endpoint created by spring-oauth2 already deals with POST as well.
It would be hard to customize it to accept a JSON request body, because the TokenEndpoint class expects all the params as #RequestParam params.
However, if your concern is about security (as HTTPs does not secure query parameters) you indeed can send the request parameters through post. It is just a matter of sending the request in the form "form-data" or "x-www-form-urlencoded". These are 2 ways of sending arbitrary key-value parameters in the request body, in a way that appears to the server as they are regular request parameters. So it is a matter of making your client using this.
Also, note that in spring-oauth2 it is possible to disable the GET endpoint, this way forcing your clients to use POST with one of the ways above.
I have a web crawler on Heroku and I'm trying to call the script from a POST request on Parse Cloud Code httpRequest but I receive a 403 forbidden response basically telling me the Referer Header didn't pass. How can I get past this?
Django's CSRF protection tests the Referer header: see https://docs.djangoproject.com/es/1.9/ref/csrf/#how-it-works. Browsers typically send that header to indicate the page that originated a request, but programmatic user agents don't (cURL, Python requests, and presumably Parse.Cloud.httpRequest) without being told to do so.
To add custom headers to a Parse request, see: Parse.Cloud.httpRequest call with HTTP request header (note the headers object).
That said, you also need to make sure you have a way to get the CSRF token to begin with, and include it either in a XCSRF-Token header or a form field (unclear from your question whether you are doing that).
I am using polymer to send ajax requests to my Drupal services api.
I send a POST to login and then a POST to create a node. When I login I am given a token which I store and pass to the next request.
I am monitoring the the requests and responses with Charles, the token is being sent, the cookie is being set and passed on the 2nd POST but I get an "Unauthorized : CSRF validation failed" response.
When I send the request with Postman It works like a dream but for some reason it doesn't validate when sent with my app.
I have checked the token being set matches the one being sent and the only difference I've noticed is that when it's being sent again there is a prefix of ga_; something to do with google analytics?
The expiry of the token is a month away the token matches what is returned at login and is being sent correctly. The header accepts X-CSRF-Token in the Access-Control-Allow-Headers.
My CORS module code is:
api/*|<mirror>|GET, POST, PUT, OPTIONS|Authorization, Origin, Content-Type, X-CSRF-Token|true
If any body has a similar issue, mine was caused by a couple of things, running Drupal and my app in the same browser causing all kinds or cookie conflicts and when passing parameters to my function that computes my request, if there were any parameters that were not used it breaks.
Hope this helps someone.
A similar question is posted here: What's an appropriate HTTP status code to return by a REST API service for a validation failure?
The answer in the thread above states that "For instance if the URI is supposed to have an ISO-8601 date and you find that it's in the wrong format or refers to February 31st, then you would return an HTTP 400. Ditto if you expect well-formed XML in an entity body and it fails to parse."
However, what happens if the user submitted correctly formatted data? By this I mean, the user submitted a plain alphabetical string / text for the username and password (which is perfectly valid for my application). The only issue is that the password did not match with the username. In this case, 400 will be incorrect because it is perfectly valid syntax and well-formed.
A 401 would be incorrect (as suggested here: Which HTTP status code to say username or password were incorrect?) because the user is not trying to access any page, he is simply trying to login and entered data which does not match.
If you look back at the first post I linked to, the second answer states that 422 is the correct response (and it looks correct to me), however, I am using Django Rest Framework and 422 is not part of the status codes (a list of the status codes which are part of DRF can be found here: http://www.django-rest-framework.org/api-guide/status-codes/#client-error-4xx)
404 also doesn't look right because the data is successfully accepted and not refused.
With that said, what is the real correct response which should be used?
If you are strictly using the HTTP authentication framework provided by RFC 7235 for your REST API, the correct HTTP code would actually be 401. From the RFC:
The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 4.1) containing at least one challenge applicable to the target resource.
If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The user agent MAY repeat the request with a new or replaced Authorization header field (Section 4.2).
Your REST API should employ an authentication scheme of some sort in order to return a valid 401 response to your client.
Another pertinent section from RFC 7235, page 4:
Upon receipt of a request for a protected resource that omits
credentials, contains invalid credentials (e.g., a bad password) or
partial credentials (e.g., when the authentication scheme requires
more than one round trip), an origin server SHOULD send a 401
(Unauthorized) response that contains a WWW-Authenticate header field
with at least one (possibly new) challenge applicable to the
requested resource.
A higher-level response, such as a rendered login page for a visual user (redirected from a protected resource via 302), would be better served with the 200 status code (per #KernelDeimos' answer, for example). Since login pages are typically their own resource (e.g. /login?redirect=original-resource), the unauthenticated user is still authorized to see this page, even if they provide an incorrect username/password. Then, you redirect the authenticated user back to the resource, at which point would show 200 if allowed, or 403 if the user is forbidden to view the resource.
The area where 401 could come into play with a visual login page is a front-end library that leverages the REST API using XHR requests, then relay the 401 response from the REST API back into a meaningful format on the login page.
If login is handled at a higher-level (ex: sending a POST to the server with a username and password), use the appropriate status code in 2xx for a successfully handled login request with the wrong password. If using the HTTP authentication framework provided by RFC 7235, send 401 (see answer by #sjagr for further detail).
Below the line is the rest of my original answer, which explains my train of thought. Also note the thread on sjagr's answer which includes a debate which improved both our answers and a comment from Julian Reschke (one of the RFC's authors).
Before asking "what is the correct HTTP status code", it's important to consider this question: "Should success or failure of login be reflected in the HTTP status code of the response?"
In #sjagr's answer the first part of this section is highlighted. I'm going to highlight the second part and explain why:
If the request included authentication credentials, then the 401 response indicates that authorization has been refused for those credentials. The user agent MAY repeat the request with a new or replaced Authorization header field (Section 4.2).
This refers to an Authorization header, rather than a request body containing login credentials. The phrasing of the first part, unfortunately, could be misinterpreted to refer to a request body containing login information. This ambiguity can be resolved by considering separation of concerns; (https://en.wikipedia.org/wiki/Separation_of_concerns) the server's response header should not depend on the differences of two valid request bodies, with the exception of when it causes an internal server error, otherwise the concerns of data transfer and appliction login begin to creep into each other.
I would use HTTP response 2xx for a valid login request, where the client has permission to attempt a login, that is handled successfully with a response indicating success or failure.
I also like the way #spectras expressed this in the comments:
Attempting to express an application-level error in a transport-level status code is a design mistake.
401 - Unauthorized
403 - Forbidden
http://www.buggybread.com/2012/11/http-error-codes-401-access-denied-403.html
If you try to log into a Google account with the wrong password, it will return a 200 response containing data that indicates the password was incorrect. For that reason, I just use a 200.
At the end of the day, which status code you use is purely a semantic issue and isn't going to change the functionality of your application. What really matters is that your application displays the correct information to the user.
I think what causes all the confusion is that there are two entities that need to be authenticated. One is the client (front-end app) needs to authenticate itself, that its authorized to make a login request for the user, and then the user needs to authenticate itself with his username/password.
The status code should only be related to the client making the request, not the user.
From https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
HTTP response status codes indicate whether a specific HTTP request has been successfully completed.
200 is correct:
Given that you have a front-end application that talks to the backend, the appropriate respond code should be 200 and the response body should contain the information if password matches or not, but that result has no impact on the status code, because the request itself was authorized and successfully parsed.
401 is wrong:
Assume your front-end authenticates with a token for example, then the response code 401 would mean the front-end token is invalid, not the password of the user inside that request.
403 is wrong: Assume your front-end authenticates with a token for example, then the response code 403 would mean the token is vaild, but that token does not have the access right to ask if password/username match.