CSRF and CORS: Why allow the request to happen if we know there will be a cors error? - express

I am confused by why the cors package allows the request to be processed even if the origin in the request header isn't white-listed. For example, res.status(202).send(await User.find()) returns a response with status code 202, but the data can't be loaded in the Chrome console.
Also, doesn't the browser send preflight OPTIONS requests to know what's allowed; why would it send cookies/credentials along a request with a disallowed origin?
Edit: Tried a post request on jsfiddle and the post request doesn't happen server side. When I said "why the cors package allows" it would be better to say why the browser allows.

CORS is enforced in the browser, not in your server. The server participates in setting headers that the browser can then use to determine whether the request should be allowed or not. But, it is the browser that ultimately decides whether the CORS request satisfies the requirements or not and the result should be passed through to the Javascript in the browser.
Thus, the request is sent to the server, response is received and THEN the browser decides whether the Javascript in the page is allowed to see the result or not.
In some cases where the request is likely to have side effects on the server (based on a set of criteria in the request), the browser will send a pre-flight request to get just the CORS info first.

Related

Is Basic Authorization always using the same "success condition"?

I have some code that looks at "Basic Authorization" requests from many different sites.
I want to know if I can make the following assumptions:
A successful response (credentials are correct) will always have response code 200 OK
A failed response (incorrect credentials) will always have response code 401 Unauthorized
Are the above fair assumptions, or is the success/fail conditions configurable per site?
No, there are other possible response codes.
According to the official spec, there can also be the error code 407.
Also, on MDN:
If a (proxy) server receives invalid credentials, it should respond with a 401 Unauthorized or with a 407 Proxy Authentication Required, and the user may send a new request or replace the Authorization header field.
If a (proxy) server receives valid credentials that are inadequate to access a given resource, the server should respond with the 403 Forbidden status code. Unlike 401 Unauthorized or 407 Proxy Authentication Required, authentication is impossible for this user and browsers will not propose a new attempt.
In all cases, the server may prefer returning a 404 Not Found status code, to hide the existence of the page to a user without adequate privileges or not correctly authenticated.
Besides that, I'm quite sure that an actual successful attempt will result in status code 200.

Continue when HTTP authentication fails

I have created an app (backend and frontend) that is mainly used on a Windows intranet. I'm using Kerberos authentication to do SSO so that anyone logged in to Windows domain is automatically authenticated to the server. To do this I set up Kerberos SPN for server and configured browsers etc and is all working fine in the normal scenario. My problem is that I need to continue if the user is not authenticated (ie connects from outside the Windows domain or does not have their browser configured correctly).
In summary there are two scenarios:
if authenticated OK continue with authorization granted for their ID [currently works]
if not authenticated continue with no (public) authorization [does not work]
In the first case the HTTP requests/responses are:
a. frontend: initial HTTP request
b. backend: no auth found so return 401 unauthorized with WWW-Authenticate:Negotiate header
c. frontend: re-sends request with Authorization header -> decoded to get the login ID
In the 2nd case:
a. frontend: initial HTTP request
b. backend: no auth found so return 401 with WWW-Authenticate:Negotiate (and error text in the body)
c. frontend: browser stops (displaying the body of the response as text to the user)
This is the crux of the problem I need to somehow avoid the browser just completely bombing (as at step c above).
Solutions I have tried:
display a message to the user about how to adjust browser settings to allow SSO to work in the body of the 401 response message. This is pretty ugly looking and does not work for connections from outisde the domain
Tried a 301 redirect in stead of 401 unauthorized response, but the browser does not like this.
Tried a redirect using javascript in the 401 response body, but it is not executed.
Have the backend send 401 but with WWW-Authenticate:Negotiate,Basic. But this display an unneeded login/password dialog and still fails if they don't login.
What I really need is an None option, ie: WWW-Authenticate:Negotiate,None then continue with no auth if the subsequent frontend request indicate "None" was used.
Of course, there isn't a "None" option. :(
It seems that this should be a fairly typical scenario but I have been researching this to no avail for 3 days now. Any advice would be greatly appreciated.
If the browser is connecting from outside the intranet then just continue. That is do not send the 401 response at all (no auth). You should be able to tell from the IP address where they connect from.
Another option is to redirect using JS in a page in the 401 body. As mentioned above I think you need to include Content-type: text/html or Content-type: text/javascript.

How to check HTTP status code in Apache configuration

Is it possible to check Http status code in Apache configuration as %{REQUEST_STATUS} for instance?
There is no such thing as a "request status", and no way for a server to interact with a browser in the middle of serving an error message.
HTTP is not an interactive protocol; the browser sends a request, the server sends a response, and that's it. So if the browser sends a request, and the application crashes, the server can send a response with 500 and the error details, or a response with 401 requesting the user to log in. Either way, that's the end of the conversation.
When it receives a 401 response, the browser can't say "here's the login details, carry on with the current request", it has to make a new request. It can make an identical request, which might reproduce the error message; but the original error message is gone.
If the requirement is to show a different amount of detail to different users, you need some notion of optional authentication, so that the server can decide immediately whether to include the error details or not, without an extra round-trip to the browser. I would suggest either:
Have a list of IP addresses which the application can check against; if the IP address of the request is in the list, include the error details.
Have a custom login system where you can authenticate and set a "session cookie" in the browser. If the user has an active session cookie, include the error details.

What is the difference between a postman request and a request from heroku or localhost

I can make a request from postman but when I make the same exact request (I'm talking about even copying the code from postman) I get an error.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://glacial-stream-35306.herokuapp.com' is therefore not allowed access.
Even with the cors-eveywhere chrome extension and attempting to use jsonp I cannot get it to work. Even though the request goes through every time on postman.
What makes a postman req different from a request from a Heroku app?

What is the correct HTTP response for requests without percent encoded URI?

Talking about HTTP API/HTTP Web server, what is the HTTP response code that the server should returns in case the client did not apply a URL encoding to requests params. I tried to look into HTTP RFCs but nothing specific or useful regarding that.
If the request is invalid, you can return a 400 Bad Request status.
400 Bad Request
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
(Source)
If you want to send a more informative or specific response, you can provide additional details in the response body.