I'm trying to determine what a client should do with headers on receiving a 303 (See Other) from the server. Specifically, what should be done with the Authorization header that was sent on the initial request?
Here's the problem: the client makes a request to myserver.com (HTTP request method is not relevant here) and the server at myserver.com responds with a 303 and the Location header contains otherserver.com/some_resource/. Tools like Postman and curl will follow the redirect by passing all the same headers in the subsequent request to otherserver.com. I haven't found a way to make these tools drop the headers.
In the case I've described, sending the Authorization header to otherserver.com seems like a security risk: otherserver.com now knows my token and possibly what host it can be used on so now the token is compromised. This can also cause errors, depending on how the destination host is configured. In the case where the redirect is to another resources on the same host (ie, myserver.com) then the Authorization header will (probably) need to be sent, and because it's the same host nothing is compromised.
Effectively, in different situations it seems that the correct behaviour is different. The relevant section in the RFC does not address this issue. In developing my own API, I've written documentation telling API clients to drop the Authorization header on redirect to otherserver.com. However, based on mucking around with curl and Postman, it's not clear to me either (a) what the default behaviour is for a typical HTTP client library or (b) whether HTTP client libraries permit easy modification of the HTTP headers before following a 303 redirect. As a result, it's possible my suggestion isn't practical. I also know of no way for the server to instruct the client as to what it should do with headers on following the 303 redirect.
What should a HTTP client do with the headers when it follows a 303 redirect? Who is responsible for deciding whether to use the same headers on the redirect, the HTTP client or server?
You can argue that when sending the 303 with otherserver.com's Location, myserver.com trusted otherserver.com to handle your token. It could have sent the token in the background as well. From the client's perspective, the client trusts myserver.com to handle the token, store and verify it securely, etc. If myserver.com decides to send it on to otherserver.com, should the client override? In this case it can of course, but in general I don't think it should.
As an attacker does not control the response headers from myserver.com which is a legit resource, I think in general it is secure to send the token by default to the other server it specifies, maybe unless you have some good reason not to (say an explicit policy on the client).
Related
Which of the http request headers are required for a client to get the correct response from server?
Does it depend on server back-end?
I've come up with situations in which setting all request headers(just like browser does) gave me improper responses and i had to cross some out.
If all request headers are required, does it mean http helper libraries in programming languages set some default values? If not, is there a better solution than error-and-trail?
I'm playing a bit with HTTP requests with fiddler.
Basically the site is my router interface which asks for a password.
The password is then encrypted (with a function i have, branded MD5 of some kind) and passed to the server in the body of the POST request.
Here what i've done:
With fiddler i sniffed the browser GET request (got a redirection 302)
With fiddler i sniffed the server response
With fiddler i sniffed the browser POST request (after typing the password)
Browser successfully logged in.
then:
With fiddler composer i performed a GET request equal to the one sniffed. (got a redirection 302)
With fiddler i sniffed the server response (each time the site provides to the client a different Set-Cookie value which is used in the brand MD5 function for antiXRSF attacks).
With fiddler composer i reproduced the sniffed POST request with a different body content due to the new Set-Cookie value.
The body of the post request is indeed correct because it is calculated by the very same function used by the browser.
What came to my mind now:
I'm using the wrong Set-Cookie value --> not possible since if i try to guess the body content of a browser request with the available parameters, the guess turns out to be correct.
The redirection performed by fiddler is done without the Set-Cookie or with a different one --> i saw i can decide not to follow a redirect, is there a way to decide what to pass in the header during a redirection? I'll test more directly on the redirected url.
Regards,
The redirection performed by fiddler is done without the Set-Cookie
Correct. Fiddler's Composer does not have a cookie jar. If a call returns a cookie via Set-Cookie on a redirect, that cookie is not added to a Cookie header when the redirected request is sent.
I'm trying to retrieve 3 response headers (Rails Devise Auth Headers: uid, client, access-token) in every request to a Rails Server.
Using Postman (http client) it's working.
With OkHttp (java http client) the headers just don't show up in the client (i've checked using Wireshark).
When i'm in debug mode it just work...
The additional headers with postman are due to postman sending an Origin header and the server is replying with CORS headers, i.e. Access-Control-.... These headers are send within the normal HTTP header, i.e. not after the response.
But these access control headers are only relevant when the access is done from a browser because they control the cross origin behavior of XHR. Since you are not inside a browser they should be irrelevant for what you are doing. What is relevant are the body of the response and some of the other headers and here you'll find no differences. Also irrelevant should be if multiple requests are send within the same TCP connection (HTTP keep-alive done by postman) or with multiple connections (OkHttp) because each request is independent from the other and using the same TCP connection is only a performance optimization.
If you really want to get these special headers you should add an Origin header within you OkHttp request. See the OkHttp examples on how to add your own headers. But like I said: these access control headers should be irrelevant for the real task and there should be no need to get to these headers.
There is a property "config.batch_request_buffer_throttle" in the file "config/initializers/devise_token_auth.rb" of the Rails Project. We changed it from 5 seconds to 0 seconds.
It is a property to keep the current token available for that amount of time to the following requests.
As the original documentation: "Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token."
So when we did the request using Postman or in Java Debug the 5 seconds was running allowing Devise to generate new tokens then retrieve them to the client.
I cannot find any RFC or Standard of HTTP client behavior in case it gets HTTP response with an error 4xx. I know the 401, 407 are the examples when the HTTP headers are parsed, but...
I have the concrete problem for OPTIONS method (HTTP1.1). The server responses 401 Unauthorized, so client tries to authenticate and re-sends the request with an authentication. After that the response has the error 404 Not Found and HTTP header is filled with Set-Cookie HTTP Header. The client use Apache Java HTTPClient/HTTPComponents, which ignores HTTP headers in case of an error in the response.
Should this HTTP Header be accepted by the client? I believe it should not be, but I cannot find the supportive quotation in the RFC.
RFC 2616 does not specify that any headers should be ignored, not for 404 responses and not for 4xx responses in general either.
RFC 6265 allows clients to ignore Set-Cookie headers, but does not specify situations where that might happen; a single example is given, that does not cover your case:
the user agent might wish to block responses to "third-party" requests
from setting cookies
In your case, since your server seems to use HTTP basic access authentication, it does not seem to concern the Set-Cookie header. In HTTP basic authentication, the Authorization header is sent by the client with every request, so there should be no need to keep state in a cookie.
It is not clear from your question if you have a very specific HTTP server that you're talking to, or if you are implementing a general HTTP client that is supposed to work with whatever server you throw it at. If you have such a specific case that the HTTP server you work with sends state with 404 responses, and you're required to honor that state in order to communicate with the server, and you have no control over the server, then it does not matter what the standard says; you will honor the state sent, or you will not be able to talk to the server.
If, on the other hand, you're implementing a general client and need it to work regardless of the remote server, then your best bet is to stick to RFC 1958:
Be strict when sending and tolerant when receiving.
Implementations must follow specifications precisely when sending to
the network, and tolerate faulty input from the network. When in
doubt, discard faulty input silently, without returning an error
message unless this is required by the specification.
Which, to me, would mean that you should honor the full response received, regardless of the status code, unless you have an objective reason making it impossible for you to do so. I don't see a reason to ignore the state, even if it violates the standard (or in this case, your personal perception of the standard, since it does not say anything about accepting or ignoring the state).
Update: RFC 2617 (HTTP Authentication) states:
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in
that space without receipt of another challenge from the server.
It is highly inconsistent if the server expects HTTP authentication for one URL, but does not honor it for URLs beneath it, requiring a separate cookie-based authentication for them. If anything should be changed in your server implementation, it should be to harmonize the authentication scheme for all resources.
I'm designing an RESTful API where some calls are public over HTTP, and some require an API key and encryption over HTTPS. I'm deliberating on what response code should be sent if an HTTP request is sent to one of the private resources. So far the only one that jumps out at me is 412 - Precondition Failed, but the standard indicates that the precondition is imposed by the requester not the server.
Is there an appropriate response code for this condition or do I just need to give in and do 400?
I cannot say if this is broadly accepted by HTTP clients, but speaking strictly RFC, the server should respond with:
HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.0, HTTP/1.1
Connection: Upgrade
Source:
https://www.rfc-editor.org/rfc/rfc2817#section-4.2
The most secure way to force HTTP client to use HTTPS is HTTP Strict Transport Security.
Previously a common suggestion was to drop the connection, but this practice has been removed in favor of HSTS (OWASP website).
The appropriate error code to return would be similar to 403.4 - SSL required.
Although not explicitly documented in the RFC for HTTP 1.1, this behavior does match the requirements outlined there:
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.
Adding your own subcode (as with the SSL example) might be helpful in some cases, but since this subcode would not be meaningful to third parties, I would recommend against it.
So, your final error message would be something like "403 - Private Resource". Note that, even in the case of a missing API key, "401 - Unauthorized" should not be used, unless your API key can actually be transmitted in a WWW-Authenticate header field.
Returning a 403 with reason phrase "HTTPS Required" seems like a practical option and what I use.
see https://en.wikipedia.org/wiki/HTTP_403
Redirecting a REST Api is not a good idea especially as you may have no idea as to how or what is consuming your service.
Just send a redirect to the corresponding https: URI.
UPDATE
The is a wrong answer - see comments below