'Nginx - custom login page
I'm trying to secure my webapp by using nginx base authentication.
What I'm looking for is a way to force the browser to show my custom html login page instead of the default login popup but still handle the authorization process.
I try to omit the 'WWW-Authenticate' header and the popup wasn't display but I've no idea how to force the browser to add the 'Authorization' header for each request.
hereby nginx.conf:
location /{
auth_basic "Restricted";
auth_basic_user_file htpasswd;
proxy_pass http://tomcat:8080/;
error_page 401 /login.html;
}
location = /login.html {
root html;
more_clear_headers 'WWW-Authenticate';
}
Solution 1:[1]
*has* to be a better way to accomplish this, but i managed to do it with X-Accel-Redirect and php, here's how:
i wanted to have a custom login page for folder /foo/ (and recursively all its content)
... first i renamed the on-disk folder /var/www/html/foo to /var/www/html/internal_foo , then i added to nginx config:
location ~ /internal_foo {
internal;
# even if this is the default root, the internal-directive seems to prevent inheriting the root directive, so have to explicitly specify it here...
root /var/www/html;
}
location ~ /foo {
try_files "" /foo.php$is_args$args;
}
then i created a /var/www/html/foo.php with the contents:
<?php
// warning: script vulnerable to timing attack which can disclose existence of files. (realpath() is not constant-time)
if(is_authorised()){
$translated="/internal_foo/".urldecode(substr($_SERVER['REQUEST_URI'],strlen("/foo/")));
$file=__DIR__.$translated;
$file=realpath($file);
if(false===$file){http_response_code(404);exit();}
if(0!==strpos($file,__DIR__.DIRECTORY_SEPARATOR."internal_foo")){
// probably a hacker attempting ../../../etc/passwd schenanigans.
http_response_code(400);
exit();
}
header("X-accel-redirect: ".$translated);
}else{
show_loginpage();
}
and voila, if a user is authorized, the request is sent to nginx, otherwise show_loginpage(); is executed (where you can put your custom login page), mission accomplished :)
Solution 2:[2]
You need to add proxy_intercept_errors on; or you will not be able to define error_page. Otherwise NGINX just passes the HTTP 401 response back to the client.
location /{
auth_basic "Restricted";
auth_basic_user_file htpasswd;
proxy_pass http://tomcat:8080/;
proxy_intercept_errors on;
error_page 401 /login.html;
}
location = /login.html {
root html;
more_clear_headers 'WWW-Authenticate';
}
Syntax: proxy_intercept_errors on | off;
Default: proxy_intercept_errors off;
Context: http, server, location
Determines whether proxied responses with codes greater than or equal to 300 should be passed to a client or be intercepted and redirected to nginx for processing with the error_page directive.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Marc |
