I'm trying to replace http basic auth with something more user friendly, appealing, and most of all that can be filled automatically by my password manager, expecially on mobile phones.
I've copied most of it from this blog, but this example uses cross domain cookies.
So I made some minor changes to make it work with session cookies.
And here's my examples files:
/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
keepalive_timeout 0;
gzip on;
server {
listen 80;
listen [::]:80;
server_name www.example.com;
index index.php;
root /var/www/secured;
location / {
auth_request /auth;
try_files $uri $uri/ /index.php?$args;
}
location = /auth {
internal;
proxy_pass http://auth.example.com;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
error_page 401 = @login;
location @login {
proxy_pass http://auth.example.com/?login&return=$http_host;
}
location = /logout {
proxy_pass http://auth.example.com/?logout&return=$http_host;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include /etc/nginx/fastcgi.conf;
}
}
server {
listen 80;
listen [::]:80;
server_name auth.example.com;
index index.php;
root /var/www/auth;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
include /etc/nginx/fastcgi.conf;
}
}
}
/var/www/auth/index.php
<?php
session_start();
if (!isset($_GET['login']) && !isset($_GET['logout'])) {
if (isset($_SESSION['authorized']) && $_SESSION['authorized']) {
http_response_code(200);
} else {
http_response_code(401);
}
die();
}
$error = "";
$loginUser = 'user';
$loginPass = 'pass';
$return = filter_input(INPUT_GET, 'return');
if (isset($_GET['logout'])) {
session_destroy();
if (!empty($return)) {
header("Location: http://{$return}");
}
die();
}
if (isset($_POST['submit'])) {
$postUser = filter_input(INPUT_POST, 'username');
$postPass = filter_input(INPUT_POST, 'password');
$_SESSION['authorized'] = ($postUser === $loginUser && $postPass === $loginPass);
if (!$_SESSION['authorized']) {
$error = "Invalid username or password.";
} else if (!empty($return)) {
header("Location: http://{$return}");
die();
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Authentication</title>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="icon.png">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.min.js" crossorigin="anonymous"></script>
<style>
html, body {
height: 100%;
width: 100%;
}
.loginOuter {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
width: 100%;
}
.loginInner {
min-width: 200px;
width: 15%;
}
</style>
</head>
<body>
<div class="loginOuter">
<div class="loginInner">
<form method="POST">
<div class="form-group">
<label for="username"><b>Username:</b></label>
<input type="text" id="username" name="username" value="<?= $loginUser; ?>" class="form-control"/>
</div>
<div class="form-group">
<label for="password"><b>Password:</b></label>
<input type="password" id="password" name="password" value="<?= $loginPass; ?>" class="form-control"/>
</div>
<?php if (!empty($error)) { ?><div class="alert alert-danger" role="alert"><?= $error; ?></div><?php } ?>
<button type="submit" name="submit" class="btn btn-success">Login</button>
<?php if (!empty($return)) { ?><a href="http://<?= $return; ?>" class="btn btn-primary">Cancel</a><?php } ?>
</form>
</div>
</div>
</body>
</html>
/var/www/secured/index.php
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Private</title>
</head>
<body>
<h1>Welcome!</h1><br>
<a href="/logout">Logout</a><br>
<pre>
<?= json_encode($_SERVER, JSON_PRETTY_PRINT) ?>
<?= json_encode($_COOKIE, JSON_PRETTY_PRINT) ?>
<?= json_encode($_POST, JSON_PRETTY_PRINT) ?>
<?= json_encode($_GET, JSON_PRETTY_PRINT) ?>
</pre>
</body>
</html>
My question and my worry are: am I poking a giant hole in my reliable basic auth?
Thanks