Removing basic authorization header in Nginx or Apache - apache

The Nginx/Apache serves as a reverse proxy to the backend server. I'd like to write a rule to remove the Authorization header if the value starts with "Basic". That is the Nginx/Apache server won't pass the Basic auth header, but it will pass all other Authorization headers.

You will need to forge the 401 response. One way is to do than is by:
{
error_page 401 = #error401
location #error401 {
...
proxy_set_header WWW-Authenticate ...
}

Related

Nginx -> Apache 2 authentication -> return to Nginix

We have a nginx and an apache2 server.
Apache2 is configured to manage Kerberos (Active Directory) authentication.
We have a website managed by nginx with a reserved area.
I would know if this is possible:
the user goes to main site managed by nginx
from main site, there is a link to "/login" mapped to apache2:
location /login/ {
proxy_pass http://apache2server/testlogin;
}
when the login is successful, apache2 is configured to go to another nginx webpage, using proxypass too:
ProxyPass /testlogin http://nginxserver/logindone.php
ProxyPassReverse /testlogin http://nginxserver/logindone.php
I wonder if this is the right solution to the problem.
The best way you can implement an external authentication to your NGiNX website is using auth_request directive.
Basically, you can protect any request doing a subrequest to any external web server. The subrequest must return HTTP code 2XX to allow proceeding to the content, and any other HTTP code returned will deny access.
To accomplish that, be sure you've NGiNX with auth_request enabled (compiled with --with-http_auth_request_module). To check that, use the following command at shell:
nginx -V 2>&1 | grep "http_auth_request_module"
Add the auth_request directive to the location you want to protect, specifying an internal location where the authorization subrequest will be forwarded to, using:
location /system/ {
auth_request /auth;
#...
}
So, when a request is made to /system/ location, the system will create a subrequest to /auth location. Now we need to create the internal /auth location. We can use the following example below:
location = /auth {
internal;
proxy_pass http://my.app.webserver/auth_endpoint;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
#...
}
Here, we created the /auth internal location. We used the internal directive to disable external NGiNX access (any external request to /auth will not be processed by this location). Also, we removed the request body content and set the request length to zero, removing any original request variable. We do a subrequest to http://my.app.webserver/auth_endpoint passing all requested cookies, so your backend application could determine if user has access or not.
If you need to know the original requested URI, you can add it on an extra HTTP header at subrequest adding:
proxy_set_header X-Original-URI $request_uri;
You can learn more about NGiNX auth_request directive here.

Bearer token for upstream server with NGINX reverse proxy. Is the header being stripped?

I have a Tomcat server that is behind an NGINX reverse proxy applying SSL. There is a bearer token in place for API calls on the Tomcat server, but I am getting a 401 error when I send this token to an endpoint in Postman. The proxy otherwise works flawlessly.
I've spent way too long troubleshooting this, but I've only looked at my proxy settings. I discovered last night that the proxy should be forwarding Authentication headers to the upstream Tomcat server, so now I'm lost as to how to troubleshoot this. Has anyone encountered this before or can point me in the right direction? This is outside of my normal scope so I'm a little out of my element.
EDIT - Even when I force the header with the Bearer token using "proxy_set_header Authorization "Bearer $ID_TOKEN";" it still returns the 401 error. Is it maybe adding something it shouldn't like a second Authorization header, or appending the Authorization header?
EDIT2 - Tomcat error logs show:
[{"time":"2021-05-14 19:01:10.069","description":"Request header did not include a token."}]
If you are not using the auth_request module for NGINX then it should be fairly easy to simply pass the Authorization headers as followed:
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
If this doesn't work i will really need to see more of your NGINX configuration and I would strongly suggest to use the NGINX auth_request module to handle all oAuth on the NGINX server itself.

Cache results of auth_request module, keyed by username

I am running the Kubernetes dashboard which, as one of its authentication methods, will allow you to pass the Authorization header with a bearer token in it. The token has to be a bearer token, i.e. Authorization: Bearer <token goes here>.
I am also running pam_hook as my authentication service. It uses HTTP basic auth to query PAM to get a user's groups, and it constructs a bearer token with that. I've modified it slightly to return the bearer token in the Authorization header after seeing this answer that tells me that you need to have it in the header for what I am trying to do: https://stackoverflow.com/a/31485557/691859
I have a fronting proxy (nginx) that uses the HTTP auth PAM module to secure the dashboard. Of course, I can have nginx forward the Authorization: Basic <basic auth goes here> header from this to pam_hook, and pam_hook can reply with the bearer token in an Authorization: Bearer <token goes here> header.
However, I'm having two problems:
I am struggling to get the bearer token from pam_hook forwarded to the kubernetes dashboard; nginx is only forwarding the basic auth.
Even if I was able to get it passed, I'm not sure how I can safely cache the responses. I need to cache each user's bearer token separately, otherwise, people will be able to act as each other. This answer alludes to that, but it doesn't tell you how to avoid the problem: https://stackoverflow.com/a/44232557/691859
So right now my config looks like this (I'm simplifying greatly here):
nginx.conf:
http {
proxy_cache_path /tmp/cache levels=1:2 keys_zone=authentication:10m inactive=15m;
proxy_cache_valid 200 15m;
include /etc/nginx/conf.d/pam.conf;
include /etc/nginx/conf.d/upstream.conf;
}
pam.conf:
auth_pam "Log in please";
auth_pam_service_name "nginx";
upstream.conf:
upstream backend {
server localhost:9090
}
server {
listen 443 default_server;
location #upstream {
proxy_pass https://backend;
proxy_redirect off;
}
include /etc/nginx/conf.d/basic_auth_proxy.conf;
location / {
root /dev/null;
try_files $uri #upstream;
auth_request /basicauthproxy;
auth_request_set $authorization_header $upstream_http_authorization;
proxy_set_header Authorization $authorization_header;
}
}
basic_auth_proxy.conf:
location /basicauthproxy {
internal;
proxy_pass https://pamhook/token;
proxy_cache authentication;
proxy_cache_key $cookie_authentication;
proxy_pass_request_body off;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_set_header Cookie "";
proxy_set_header Host $host;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
The behavior I get right now is that I get prompted for basic auth, pass my credentials, that succeeds, and then the dashboard gets the forwarded request... but the Authorization header contains the basic auth info from the proxy, not the bearer token. What am I missing to get this to work?
Edit: I upped the verbosity of pam_hook's logs. It's not getting any request from nginx. So that's probably the first problem to address, not that I understand why it's happening. I do know that I can curl pam_hook from the nginx container, so it's not a matter of a bad NetworkPolicy.

Caddy as reverse proxy to rewrite a http redirect url from an upstream response

I am having a backend that is not able when running behind a reverse proxy since I cannot configure a custom base URL.
For the login process the backend makes heavy use of HTTP redirects but due to the fact that is behind a reverse proxy it sends redirection URL that are not reachable by the client.
So I was wondering if there is a way to rewrite the upstream HTTP HEADER Location
If the backend responses
HTTP/1.1 301
Location: http://backend-hostname/auth/login
Caddy should rewrite the Location header to
HTTP/1.1 301
Location: http://www.my-super-site.com/service/a/auth/login
Is something like this possible?
I've that we can remove headers by declaring
header / {
- Location
}
but it possible to replace the header and rewrite the URL?
I was also looking for answer for this question and unfortunately I've found this responses:
https://caddy.community/t/v2-reverse-proxy-but-upstream-server-redirects-to-nonexistent-path/8566
https://caddy.community/t/proxy-url-not-loading-site/5393/7
TLDR:
You need to use sub-domains rather than sub-paths for services that are not design for being after proxy (or at least configure base URL). :(

nginx authentication from external service

My goal is to enable access on one (static) web page/folder only to authenticated users.
auth_basic is NOT option.
There are 2 servers: nginx (contains http,css and javascript) and REST server (doing authentication and provides secure content).
REST server provides access token.
On www.somesite.com/secret (hosted by nginx) should access only authenticated users.
I have tried something similar to this https://www.nginx.com/resources/admin-guide/restricting-access-auth-request/
this is my config example:
location /secret/ {
auth_request /restauth;
auth_request_set $auth_status $upstream_status;
}
location /restauth/ {
internal;
proxy_pass http://localhost:8080/api/auth/login;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
With this, only GET request is sent, REST service support only POST.
How can I send POST with access token, and with code 200 to allow access to content of /auth folder?
Another interesting thing I found is nginscript, but this simple example from this site doesn't work to me.