Skip to content

Instantly share code, notes, and snippets.

@teidesu
Last active June 8, 2023 19:00
Show Gist options
  • Save teidesu/5e7becbd6ae9f24d5925e69e71a95285 to your computer and use it in GitHub Desktop.
Save teidesu/5e7becbd6ae9f24d5925e69e71a95285 to your computer and use it in GitHub Desktop.
web-based password protection, in pure nginx, with php support
dummy file for gist title
limit_req_zone $binary_remote_addr zone=phpfront_auth:10m rate=1r/s;
map $arg_login:$arg_password $phpfront_logpass_to_token {
"user1:SOME_PASSWORD" "SOME_SECRET";
"user2:SOME_PASSWORD" "SOME_SECRET";
default 0;
}
map $cookie_secure $phpfront_secure_access {
"SOME_SECRET" 1;
"SOME_SECRET2" 1;
default 0;
}
server {
listen 80;
server_name example.com;
root /var/www/example;
index index.html index.htm index.php;
location @secure_auth {
try_files /_secure/auth.html =418;
}
location /_secure/auth {
limit_req zone=phpfront_auth;
limit_req_status 429;
if ($phpfront_secure_access = 1) {
return 200 "You are already authed, please reload page";
}
if ($phpfront_logpass_to_token) {
add_header Set-Cookie "secure=$phpfront_logpass_to_token;max-age=3153600000;path=/;Secure;HttpOnly";
return 200 "OK";
}
return 200 "Invalid login or password";
}
location /_secure/ {
if ($phpfront_secure_access = 0) {
error_page 463 = @secure_auth;
return 463;
}
try_files $uri $uri/ =404;
}
location ~ ^/_secure/.*\.php$ {
if ($phpfront_secure_access = 0) {
error_page 463 = @secure_auth;
return 463;
}
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
}
<!-- Based on: https://flowbite.com/blocks/marketing/login/. Place this in $root/_secure/auth.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vibe check</title>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
primary: {"50":"#eff6ff","100":"#dbeafe","200":"#bfdbfe","300":"#93c5fd","400":"#60a5fa","500":"#3b82f6","600":"#2563eb","700":"#1d4ed8","800":"#1e40af","900":"#1e3a8a"}
}
},
}
}
</script>
</head>
<body>
<section class="bg-gray-50 dark:bg-gray-900">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full bg-white rounded-lg shadow dark:border md:mt-0 sm:max-w-md xl:p-0 dark:bg-gray-800 dark:border-gray-700">
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 hidden" role="alert" id="alert-error">
<p class="font-bold">Error</p>
<p id="alert-error-text"></p>
</div>
<div class="bg-green-100 border-l-4 border-green-500 text-green-700 p-4 hidden" role="alert" id="alert-ok">
<p class="font-bold">OK</p>
<p>You will be redirected in a second.</p>
</div>
<h1 class="text-xl font-bold leading-tight tracking-tight text-gray-900 md:text-2xl dark:text-white">
Vibe check required
</h1>
<form class="space-y-4 md:space-y-6" action="/_secure/auth" method="GET">
<div>
<label for="login" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Username</label>
<input name="login" id="login" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="john-doe" required="">
</div>
<div>
<label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Password</label>
<input type="password" name="password" id="password" placeholder="••••••••" class="bg-gray-50 border border-gray-300 text-gray-900 sm:text-sm rounded-lg focus:ring-primary-600 focus:border-primary-600 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required="">
</div>
<button type="submit" class="w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Sign in</button>
<p class="text-sm font-light text-gray-500 dark:text-gray-400">
Don’t have an account? Then you likely don't need to access this.
</p>
</form>
</div>
</div>
</div>
</section>
<script>
const alertOk = document.querySelector('#alert-ok')
const alertError = document.querySelector('#alert-error')
const alertErrorText = document.querySelector('#alert-error-text')
document.querySelector('form').addEventListener('submit', (e) => {
e.preventDefault()
const login = document.querySelector('#login').value
const password = document.querySelector('#password').value
alertOk.classList.add('hidden')
alertError.classList.add('hidden')
fetch('/_secure/auth?login=' + encodeURIComponent(login) + '&password=' + encodeURIComponent(password))
.then(res => res.text())
.then(data => {
if (data === 'OK') {
alertOk.classList.remove('hidden')
setTimeout(() => {
location.reload()
}, 1000)
} else {
alertErrorText.innerText = data
alertError.classList.remove('hidden')
}
})
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment