NGinx sends 307 instead of 401 - nginx

I've used several revers proxies over time, but NGinx blew me away with its behavior. I recently had to use NGinx after years of using HAProxy (as K8s Ingress) and I'm stuck with no solution in sight.
Right from the beginning, the behaviour was different when the session was lost. An HTTP 401 would tell the client (single page JavaScript application) to inform the user that the session was lost and he/she has to login again. Instead of sending 401 to the browser, it sends a 307 to the login page, with the wrong verb (POST) since the request that fails with 401 was a POST request.
The best way to troubleshoot would be in isolation so I installed the version from the repository (Linux Mint 20) and registered a simple reverse proxy entry in /etc/nginx/conf.d
server {
listen 80;
location / {
proxy_pass http://localhost:8080;
}
}
Unfortunately (or fortunately) the issue manifested itself right away: as soon as I removed the cookies and the server sends 401 "Please log in", the browser shows a 307 on the request that failed with 401.
Expected behavior:
Browser sends "POST /ping"
Browser receives "401 on /ping"
Current behavior:
Browser sends "POST /ping"
Browser receives "307 /auth" and then executes /auth with POST (not sure how it knows /auth is the login page)
Any idea how to disable this behavior?

Related

Axios redirect 308 not working (CORS error)

We are implementing short URLs to redirect on our project.
I do an API request to my server using axios, with the info on the short url.
The server responds with a redirect status 308 succesffuly.
I see in the response headers, the location parameter (to redirect to) is correct.
And we have also set Access-Control-Allow-Origin: *
But the redirect does not follow through...
After recieving the 308; the browser attempts a preflight OPTIONS request to the redirect URL, followed by a GET request to the redirect URL.
Both of these return an error.
The preflight request error: CORS Misssing Allow Origin. And the GET request gives error: NS_ERROR_DOM_BAD_URI
Not sure what the issue is. Is it on the front-end, or on the server-side?
Any advice would be greatly appreciated!

Firebase HTTP to HTTPS NGINX redirect for custom domains dropping POST method for GET

Firebase fails to redirect any HTTP POST requests to HTTPS POST. EX:
POST / HTTP/1.1
Host: apis.mydomain.com
is redirected by Firebase NGINX to
GET / HTTP/1.1
Host: apis.mydomain.com
if you are explicit about https, then NGINX works properly: POST -> POST
So, when the request hits Firebase hosting, and redirects your request to a firebase function that can be accessed by an https endpoint, the method has the possibility of collapsing into a GET from a POST method.
Looking closer at the headers, inside the Firebase Cloud Function, the protocol always expresses as http, instead of https.
I'm assuming this is an internal issue that I cannot modify, however, this is an issue for what I am doing, and this definitely is a problem given I cannot modify the NGINX that is handling my http(s) requests.
If you redirect with a 301 or 302 status code, the POST is downgraded to GET.
You need to use a 307 status to maintain POST across the redirect. See this document for details.
On Nginx, you will need to use a return statement. For example:
return 307 https://$host$request_uri;

Requests sequence in Nginx

I have a scenario when server needs to do authorization request before an actual request. so, one request are served by 2 different services.
Nginx's location has to be handled by Auth-Service, and if the response status is 200 OK, then the request should be forwarded to the Feature-Service. Otherwise, if the response status 401 then this status should be replied to front-end.
upstream auth_service {
server localhost:8180;
}
upstream feature_service {
server localhost:8080;
}
location /authAndDo {
# suggest here
}
Code snippet in nginscript will be also OK.
Specifically for this purpose, http://nginx.org/r/auth_request exists through http://nginx.org/docs/http/ngx_http_auth_request_module.html (not built by default).
It lets you put authentication, through a subrequest, into any location you want, effectively separating the authentication from the actual resource.
In general, such not possible from web server. 401 is a response at front end plus gives HTTP WWW-Authenticate response header. Develop web application according to need or edit 401 file. HTTP 401 has RFC specification. Users, browsers should understand the message. Nginx doc described how 401 will be handled.
Nginx community edition's auth_request will only process if the subrequest returns HTTP 200, else for 401 will not redirect more than to 401 by default, other headers will not be process the response to protect the application & the users. Nginx community edition not even support all features of HTTP/2. It can go worser.
Apache2 web server has full HTTP/2 support and custom 401 location in auth module and works only on few browsers. Few browsers allow Apache2 to do that perfectly. Others show fail to load page. On Stack Exchange networks's various subdomains peoples asked before for Apache2 to make it working for all the browsers.
Hardly you can redirect on Nginx :
error_page 401 /401.html;
location ~ (401.html)$ {
alias /usr/share/nginx/html/$1;
}
Another way may be using reverse proxy with another server like peoples talking here on Github. I can not give warranty of failure of loading page.

Fiddler requests vs browser requests, identical but different answer from the server

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.

Windows authentication multiple requests

I am using Windows Authentication to secure ASP.NET MVC5 application.
Everything works ok, I'm prompted to enter credentials via browser popup, and content it served properly.
However I do notice constantly that some requests are being sent 2 times, or more, with receiving 401 (Unauthorized) code, but shortly after requests are issued again and 200 (OK) is returned.
I assume that is part of negotiation with WWW-Authenticate and Authorize requests headers, but what is unclear to me is why this has to happen all the time even though credentials were supplied at the very start?
Is this normal behavior?
If not, how can it be fixed?
If yes, is it a big performance hit?
Attached is the combined screenshot of Fiddler and Firefox developer console.
What you are experiencing is the normal behavior. Here is a (very) short description of how the authentication works:
Request is sent to server (without credentials) => not authenticated (your first request)
Server responds with 401 (Access denied)
Browser gets error and sends credentials back => authenticated (your second request)
After the 3rd step, if the server has not received the requested credentials, it sends another 401 response and the browser displays the 401 error page. A more complete description can be found here.

Resources