#2013 closed defect (invalid)
auth_basic cannot be overwritten from other context
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.19.x |
Keywords: | Cc: | ||
uname -a: | Linux servername 4.4.0-119-generic #143-Ubuntu SMP Mon Apr 2 16:08:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.15.0
built with OpenSSL 1.0.2g 1 Mar 2016 TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-4QY95m/nginx-1.15.0/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-4QY95m/nginx-1.15.0/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-4QY95m/nginx-1.15.0/debian/modules/http-echo --add-dynamic-module=/build/nginx-4QY95m/nginx-1.15.0/debian/modules/http-upstream-fair --add-dynamic-module=/build/nginx-4QY95m/nginx-1.15.0/debian/modules/http-subs-filter |
Description (last modified by )
The documentation says: "The special value off allows cancelling the effect of the auth_basic directive inherited from the previous configuration level." Link: http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html#auth_basic
So this should work right?
http { auth_basic "Restricted Area"; auth_basic_user_file /htpasswd; server { location / { } location /api { auth_basic off; } } }
Or
http { server { auth_basic "Restricted Area"; auth_basic_user_file /htpasswd; location / { } location /api { auth_basic off; } } }
But at /api
I'm still getting the basic authentication. It only works like this:
http { server { location / { auth_basic "Restricted Area"; auth_basic_user_file /htpasswd; } location /api { auth_basic off; } } }
So auth_basic
can not be overwritten from another context. This also happens with allow
/deny
. Having this for example at http
/server
level:
allow 127.0.0.1; deny all;
Can not be overwritten with allow all;
for a specific location.
Change History (10)
comment:1 by , 4 years ago
Description: | modified (diff) |
---|
comment:2 by , 4 years ago
follow-up: 4 comment:3 by , 4 years ago
Just updated to 1.18.0:
nginx version: nginx/1.18.0 built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12) built with OpenSSL 1.0.2g 1 Mar 2016 TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
But I'm still having the same problem. All configuration (just for sure):
/etc/nginx/nginx.conf
:
user forge; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; server_names_hash_bucket_size 128; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
/etc/nginx/conf.d/password.conf
:
satisfy any; allow 127.0.0.1; allow 123.123.123.123; deny all; auth_basic "Restricted Area"; auth_basic_user_file /home/forge/global.htpasswd;
/etc/nginx/sites-enabled/website.com
:
# FORGE CONFIG (DO NOT REMOVE!) include forge-conf/website.com/before/*; server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name website.com; root /home/forge/website.com/public; # FORGE SSL (DO NOT REMOVE!) ssl_certificate /etc/nginx/ssl/website.com/1/server.crt; ssl_certificate_key /etc/nginx/ssl/website.com/1/server.key; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparams.pem; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.html index.htm index.php; charset utf-8; # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/website.com/server/*; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } access_log off; error_log /var/log/nginx/website.com-error.log error; error_page 404 /index.php; location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_index index.php; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; } } # FORGE CONFIG (DO NOT REMOVE!) include forge-conf/website.com/after/*;
/etc/nginx/forge-conf/website.com/before/ssl_redirect.conf
:
# Redirect every request to HTTPS... server { listen 80; listen [::]:80; server_name .website.com; return 301 https://$host$request_uri; } # Redirect SSL to primary domain SSL... server { listen 443 ssl http2; listen [::]:443 ssl http2; # FORGE SSL (DO NOT REMOVE!) ssl_certificate /etc/nginx/ssl/website.com/1/server.crt; ssl_certificate_key /etc/nginx/ssl/website.com/1/server.key; ssl_protocols TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparams.pem; server_name www.website.com; return 301 https://website.com$request_uri; }
/etc/nginx/forge-conf/website.com/server/letsencrypt_challenge.conf
:
location /.well-known/acme-challenge { auth_basic off; allow all; alias /home/forge/.letsencrypt; }
/etc/nginx/forge-conf/website.com/server/api.conf
:
location /api { auth_basic off; allow all; }
That last file isn't working. I've removed that file and I debugged it within /etc/nginx/modules-enabled/website.com
I'm having the behavior described in the ticket description.
comment:4 by , 4 years ago
Replying to royduineveld@…:
But I'm still having the same problem. All configuration (just for sure):
To be sure, please try the exact configuration you've written in the ticket description.
That last file isn't working.
Define "isn't working". How do you test?
Just in case, looking at your configuration suggests that the most likely reason is that the request you do for tests ends up being handled in location ~ \.php$
instead of location /api
, and this explains things since the former does require authentication. Consider using location ^~ /api
instead (note though that this will prevent *.php
processing).
comment:5 by , 4 years ago
I'm testing the same way as you did:
curl -IL https://website.com HTTP/1.1 401 Unauthorized Server: nginx/1.18.0 Date: Tue, 07 Jul 2020 14:37:27 GMT Content-Type: text/html; charset=utf-8 Content-Length: 179 Connection: keep-alive WWW-Authenticate: Basic realm="Restricted Area"
curl -IL https://website.com/api HTTP/1.1 401 Unauthorized Server: nginx/1.18.0 Date: Tue, 07 Jul 2020 14:38:20 GMT Content-Type: text/html; charset=utf-8 Content-Length: 179 Connection: keep-alive WWW-Authenticate: Basic realm="Restricted Area"
It doesn't even get to the location ~ \.php$
, I've removed that part to test. Even with all "locations" removed I'm still getting the basic auth prompt. But when I do this it's working (200 response instead of a 401):
location /api { auth_basic off; allow all; return 200 "test"; }
But of course I do not just want to return something.
comment:6 by , 4 years ago
Ok, so please test the configuration you've provided in the ticket description.
comment:7 by , 4 years ago
Found it! I think it's not a bug but maybe this can be explained better in the docs. By specifying anything in de http
/server
context will be applied to every location
. Let's have a look at these:
location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; fastcgi_index index.php; include fastcgi_params; }
The first one accepts everything without .php
and rewrites it to the index.php
. So when I do this:
location /api { auth_basic off; allow all; }
The auth is removed but then it's rewriting it so it goes to the location ~ \.php$
and the authentication is also applied there so I'm still getting the basic auth prompt. The options:
1) Disable it twice
2) Include the fastcgi_params in in the location /api
.
comment:8 by , 4 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
You've claimed you've tested the curl -IL https://website.com/api
, and the /api
request is only expected to be handled in the location /api
, not in location /
. And there is no rewrites and/or try_files
in the location /api
. So your explanation does seem to explain anything.
On the other hand, omitted parts of the configuration might actually explain what happens in your configuration. For example, error_page 404 /something
might be the reason if the /api
resource does not exist.
Either way, as initially suggested, this looks like a configuration bug, not an nginx issue. Closing this.
comment:9 by , 4 years ago
That makes sense, ended up with:
location /api { auth_basic off; allow all; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; }
What I wanted and meant was this:
location /api { auth_basic off; allow all; try_files $uri $uri/ /index.php?$query_string; }
But then location ~ \.php$
is processing it and disabling the auth doesn't have effect anymore. So it would be nice if try_files
passes through the auth_basic off;
and allow all;
to the next location. Can this ticket be re-opened for that or should I create a new ticket?
comment:10 by , 4 years ago
So it would be nice if try_files passes through the auth_basic off; and allow all; to the next location. Can this ticket be re-opened for that or should I create a new ticket?
No, it wouldn't be nice, it would be a nightmare to configure things when some parts of the configuration are "passed" to other parts of the configuration. Such approaches are known to be very bad from maintenance point of view, requiring a lot of effort to understand how a particular configuration works and how to modify it correctly. Consider using explicit configurations when you need different processing for requests.
You may also want to watch this talk by Igor Sysoev to better understand how nginx configuration is expected to be used:
Hope this helps.
Works fine here:
While the version you are using is old and no longer supported, it is expected to work fine as well. Please clarify how do you test things.