Cross Origin calls from curl working without needed headers - rest

I am invoking one of my APIs using curl as follows(cross origin).
curl -H "Origin: foo.com" -H "Content-Type: application/json" -H "Authorization: Basic YWRtaW46YWRtaW4=" -v https://localhost:9443/api/v10/configs -k
I have not set the necessary cross origin headers in the server side. But the API call works. Why is that?
on server side API class, in the options call I am only setting the Allow header.
#OPTIONS
public Response options() {
return Response.ok().header(HttpHeaders.ALLOW, "GET").build();
}
The following headers are not set.
Access-Control-Allow-Methods:
Access-Control-Allow-Origin:
Access-Control-Allow-Headers:

CORS is a mechanism to enable cross domain requests but in the browser using AJAX. If you use curl you can do what you want ;-)
So in your case (using curl), you try to execute the request outside a browser. So you are free to do what you want! With curl, the request will be always executed and you will see the exchanged headers for example. This can be something helpful to see if you have the expected headers for CORS...
Hope it helps you,
Thierry

You may want to read HTTP access control (CORS) to get a better understanding of how it works, and the main purpose it serves.
Just some into snippet
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest follows the same-origin policy. So, a web application using XMLHttpRequest could only make HTTP requests to its own domain. To improve web applications, developers asked browser vendors to allow XMLHttpRequest to make cross-domain requests.
The W3C Web Applications Working Group recommends the new Cross-Origin Resource Sharing (CORS) mechanism. CORS gives web servers cross-domain access controls, which enable secure cross-domain data transfers. Modern browsers use CORS in an API container - such as XMLHttpRequest - to mitigate risks of cross-origin HTTP requests.
So CORS was introduced to allow for cross-domain access (from scripts) in browsers. How it works is that when a a request is made that requires cross-domain authorization, the browser first makes an OPTIONS ("preflight") request to look for the access response headers. If they are there, then it make the initial request. Otherwise there is a request error.
As an aside, I would avoid implementing CORS support in resource methods. I would instead use a filter mechanism so all requests are handled in the filter, instead of having to implement an #OPTIONS method for all endpoints.

Related

Is it bad to have access token in OAuth redirect URL

I am building an oauth login flow and I am not sure if I have done it wrong because I will need to send the bearer token back via redirect URL, like /oauth2/redirect?token=[TOKEN]. But isn't it not recommended to have token passed along through URL? As it is pointed out in this thread:
Don't pass bearer tokens in page URLs: Bearer tokens SHOULD NOT be passed in page URLs (for example, as query string parameters).Instead, bearer tokens SHOULD be passed in HTTP message headers or message bodies for which confidentiality measures are taken. Browsers, web servers, and other software may not adequately secure URLs in the browser history, web server logs, and other data structures. If bearer tokens are passed in page URLs, attackers might be able to steal them from the history data, logs, or other unsecured locations.
I must have missed something in the whole flow and would like to understand more about this matter. Any input is appreciated!
UPDATE
Might not be correct but this is my understanding after some digging. The three means to pass token:
URL (not preferable)
Auth header
Request body
But under the oauth redirect use case, option 2 and 3 not feasible. So option 1 is the only option available. If really needed, token can be encrypted to ensure security.
I think this only means, that you should not use a GET request when the server requires the token, instead you should use POST or whatever is appropriate. In a GET request the parameters are included in the URL and those can end up in logs or other histories, other request types will send the paramters separat from the request URL.
P.S. BTW if you are not implementing the OAuth server yourself, you won't have to send a redirect url containing the token.
The basic auth header which provides a little extra security as it's required to be through TLS:
In the case of a "Basic" authentication like shown in the figure, the exchange must happen over an HTTPS (TLS) connection to be secure.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
Also, the headers aren't logged in easy places like browser history.
From the spec,
it SHOULD NOT be used
unless it is impossible to transport the access token in the
"Authorization" request header field or the HTTP request entity-body.
https://www.rfc-editor.org/rfc/rfc6750#section-2.3

OAuth2 security in REST GET API

I understand that OAuth2 is a good way to secure access to a REST API. I also understand that unlike in a simple website or in a SOAP API, in a REST API you want to use the right HTTP method for the right task. That is GET to read data, POST to write, etc.
My question is, when doing a GET call to a REST API secured via OAuth2, how do you protect your access token ? I don't see any other way to pass it to the server than in clear view in the URL, so isn't it that anybody that can see my call on the network could hijack my authorization ?
A HTTP request has a couple of major components:
The method
The url
Headers
Body
The OAuth2 Bearer token is usually sent in the headers, as such:
GET /thingy HTTP/1.1
Host: api.example.org
Authorization: Bearer [secret]
As an aside, this assumption is not really correct either:
so isn't it that anybody that can see my call on the network could hijack my authorization ?
If you don't use HTTPS, anyone can still see this token even if it's in a header. If you do use HTTPS, putting a token in the url shouldn't allow anyone else to snoop. However, putting secrets in urls is considered a bad practice for different reasons. Specifically, people don't like it because the tokens can end up in a browsers history and in logs. This increases the chances of it accidentally falling in the wrong hands.

What WWW-Authenticate header should a http server return in a 401 response when using form-based authentication?

I have a web application with a Javascript part running on the browser. That frontend uses several HTTP endpoints (more or less REST). The frontend must be able to distinguish between 401 and 403 responses and must not receive the 3xx redirects usually used for human users.
Authorization is done with a plain form login (no Javascript involved there), then a session cookie is used (for both "REST" and normal requests).
What would be a correct value for the WWW-Authenticate header value?
From RFC 7235: "A server generating a 401 (Unauthorized) response MUST send a WWW-Authenticate header field containing at least one challenge."
The Hypertext Transfer Protocol (HTTP) Authentication Scheme Registry does not list any scheme for form-based authentication.
See also:
HTTP 401 Unauthorized when not using HTTP basic auth?
Authorization in RESTful HTTP API, 401 WWW-Authenticate
What would be a correct value for the WWW-Authenticate header value?
There's no point in returning 401 and WWW-Authenticate when you are not using HTTP Authentication as described in the RFC 7235. In HTTP Authentication, the client is expected to send the credentials in the Authorization header of the request with an authentication scheme token.
If you want to send the credentials in the request payload using POST, the 403 status code you be more suitable to indicate that the server has refused the request.
Since there is no standard challenge for this type of authentication, you are (as you predicted yourself) inventing your own.
I don't think there is a standard mechanism for specifying vendor tokens here, so I think the best thing you can do is use a token that's unlikely to clash with anything else.
Amazon has done this with AWS, and there's many others. My recommendation would be to use something like productname-schemename, for example acme-webauth.
In theory you should respond
HTTP/1.x 401 Unauthorized
WWW-Authenticate: cookie; cookie-name=my-session-cookie-name
However, real world internet browsers (user agents) do not really support this and in my experience the least bad option is to use HTTP status 403 for all of "Access Denied", "Unauthorized" or "Not allowed". If you have a REST service that's accessed with non-browser user-agents only, you could just follow the spec and return the above headers.
Also note that as described in RFC 7231 section 6.5.4 (https://www.rfc-editor.org/rfc/rfc7231#section-6.5.4) the server can respond with 404 for both "Access Denied" and "Not Found" so following should be okay for all user agents (browsers and standalone clients):
403 Unauthorized or Not allowed
404 Access Denied or Not Found
Or, you can just use 400 for any case because that should cause browser do fallback to generic error handling case. The HTTP status code 401 is especially problematic because it historically meant (at least in practice) that Basic Realm authentication is in use and the submitted HTTP header Authorization was not accepted. Because you cannot submit the session cookie via that header with commonly available browsers, those browsers have trouble handling 401 correctly when you use cookies for authentication. (According to the spec, HTTP 401 MUST include header WWW-Authenticate which should be used to figure out correct handling by the user agent but this doesn't seem to happen in reality with browsers.)
There is no HTTP authentication scheme for form based authentication.
Browsers implement basic, digest, etc. by showing a pop up where you can enter credentials.

REST API Authorization Header or custom Header like X-ABC-Token

Should I used custom HTTP Header to pass JSON web token or HTTP Authorization header in my RESTFul services.
I have already read Custom HTTP Authorization Header but could not understand clearly drawback, if I use header like - X-ABC-Token.
After reading REST Authorization: Username/Password in Authorization Header vs JSON body, I feel Authorization seems good choice.
If I use HTTP Authorization then I believe I can use scheme bearer to achieve this as mentioned in
rfc6750
Please suggest me what are the best ways to pass this token in each HTTP request.
You shouldn't expand the standard features of the protocol if the existent ones solve your problem. The correct approach is to define your own authorization scheme for the Authorization header.
You can do something like:
Authorization: MyCompanyLogin token="abcdefg...."
Browsers and proxies already know about the Authorization header. For example, responses to requests with an Authorization header are not cached or are cached just for one user.
In contrast, browsers and proxies don't know about your custom X-ABC-Token header. A proxy may return the same page to different users, even if that header is different. This makes it possible that one user sees the information of another user. This in turn can be disabled by using the header Cache-Control: private.

CSRF Prevention Without Modification to client

I need to integrate CSRF Prevention in our existing REST Service.
We have created many rest resources and published its detail for other developers to consume. Anyone in the organization can use it. I have no control how he uses it, the form he uses or the httpclient. I have no idea who has used it till date and I cannot change all the clients. Hence, I cannot add a hidden text fields/tokens to the form, since I do not have access to the clients. Also, I cannot use the double authentication or captcha, because it wont work with the httpclient implementations. Is there any other way that I can prevent the misuse of the REST service against CSRF.
You could do this by checking the X-Requested-With header.
If any web clients are already using JQuery, then this header will be passed automatically and ensures that the request is not a cross-domain request either by AJAX or by HTML forms. This header will not be sent at all for HTML forms, so this will work if no web clients use HTML forms.
If your web clients use plain JavaScript then you could check that the Origin header is set to a valid domain. Please note that some versions of some browsers do not set this when the request is not cross domain.
The only drawback is that non-web clients would have to set one of these headers, or that you have some way of identifying these non-web clients from your REST service so that you could bypass the checks in these cases.
If you non-web clients already send any headers other than the following:-
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type
then you could verify the value is passed (instead of X-Requested-With or Origin) to ensure that this is not a CSRF attack as custom headers cannot be sent in a CSRF attack. Even the User-Agent could be used - this can be spoofed only by a HTTP client but not by an attacker inside a browser which is the only relevant place that a CSRF attack can happen.