I’m trying to enable HTTP Basic Authentication for all URLs except a few, but no matter what I try, I either get auth for all non-static URLs or no auth for all.
My config:
server {
listen 80;
server_name dev.website.com *.dev.website.com;
return 301 https://dev.website.com;
}
server {
listen 443 ssl;
include snippets/fastcgi-php-controller.conf;
server_name dev.website.com;
root /var/www/website/web/;
ssl_certificate /etc/ssl/localcerts/website/dev/website.crt;
ssl_certificate_key /etc/ssl/localcerts/website/dev/website.key;
auth_basic_user_file /var/www/website/web/.htpasswd;
auth_basic "Restricted Access!";
location /just_a_simple.html {
try_files /static$uri =404;
}
location / {
rewrite ^ /index.php;
}
location /static {
try_files $uri =404;
}
location ~ ^/en/(url1|url2) {
auth_basic off;
rewrite ^ /index.php;
}
}
I’m trying to:
- have the just_a_simple.html file served as static, unprotected and it works
- have everything in /static served as static, unprotected and it works
- have /en/url1 and /en/url2 passed off to FPM, interpreted as PHP, unprotected and it doesn’t work, it’s protected
- have all other URLs passed off to FPM, interpreted as PHP, protected and it works
How can I make point 3 above work and achieve all 4 requirements?
snippets/fastcgi-php-controller.conf
location ~ .php$ {
fastcgi_split_path_info ^(.+.php)(/.+)$;
try_files $uri /index.php;
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
2
Answers
Have you tried adding this to the location blocks you want to allow?
For example:
You are right about request processing phases (described in the development guide). Your
rewrite
directive will be executed at theNGX_HTTP_REWRITE_PHASE
whilebasic_auth
one register its handler at the laterNGX_HTTP_ACCESS_PHASE
. If you’d need to do an opposite thing, protect the/en/url1
and/en/url2
URIs leaving all the others unprotected, you’d have an option to use atry_files
directive to jump to the PHP handler location at the even more laterNGX_HTTP_PRECONTENT_PHASE
:However this is not an option for your particular case. What you can do instead is to rely on the
$request_uri
built-in nginx variable, which is always contains an original non-normalized request URI and does not get changed during internal URI rewrites (in is the normalized$uri
one that does). Usually you have at least two options:if
block to conditionally set theauth_basic
directive parameter:However since you have a customized
try_files
directive inside your PHP handler location, it won’t be an option here sincetry_files
does not get inherited into the virtual nested locations created byif
directive when used in thelocation
context. Do you remember thatif
is evil? So we should either move the$realm
variable evaluation one level up to theserver
context (thus being executed at theNGX_HTTP_SERVER_REWRITE_PHASE
):or better go straight to the second option:
map
block to evaluate theauth_basic
directive parameter:The second option will be somewhat more optimal since the
$realm
variable will be evaluated only when it needs to be.P.S. Dealing with
PATH_INFO
inside your PHP handler makes no sense; you can read here why is it.P.P.S. Did I mention you don’t need that
location ~ ^/en/(url1|url2) { ... }
location in order for this to work?