Very simple authentication using one-time cookie on nginx Very simple authentication using one-time cookie on nginx nginx nginx

Very simple authentication using one-time cookie on nginx


There is a really quite simple looking solution that I found from a blog post by Christian Stocker. It implements the following rules:

  1. If the user is on an internal IP, they are allowed.
  2. If the user has a cookie set, they are allowed.
  3. If neither matches, the user is presented with http basic authentication, and if they successfully authenticate a long term cookie is set

This is really the best of both worlds.

Here's the config:

map $cookie_letmein $mysite_hascookie {  "someRandomValue" "yes";  default           "no";}geo $mysite_geo {  192.168.0.0/24 "yes": #some network which should have access  10.10.10.0/24  "yes": #some other network which should have access  default        "no";}map $mysite_hascookie$mysite_geo $mysite_authentication{  "yesyes" "off";  #both cookie and IP are correct  => OK  "yesno"  "off"; #cookie is ok, but IP not  => OK  "noyes"  "off";  #cookie is not ok, but IP is ok => OK  default  "Your credentials please"; #everythingles => NOT OK}server {  listen 80;  server_name mysite.example.org;  location / {    auth_basic  $mysite_authentication;    auth_basic_user_file  htpasswd/mysite;    add_header Set-Cookie "letmein=someRandomValue;max-age=3153600000;path=/"; #set that special cookie, when everything is ok    proxy_pass http://127.0.0.1:8000/;    proxy_set_header Host $host;    proxy_set_header X-Forwarded-For $remote_addr;  }}


To have Nginx filter by a cookie, you could perform some action if the cookie isn't present, and then your real action for the 3 people that have access, for example:

server {    listen 443 ssl http2;  # Use HTTPS to protect the secret    ...    if ($http_cookie !~ 'secretvalue') {        return 401;     }    location / {       # Auth'd behaviour goes here    }}

And to set a cookie that never expires, fire up your browser's JavaScript console on a page that's on your server's hostname, and enter:

document.cookie = 'cookie=secretvalue;max-age=3153600000;path=/;secure';

That's technically not forever, but 100 years ought to do it. You can also use expires= for an absolute date in RFC1123 format if you're so inclined and can easily adjust the path if you need to. This also sets the secure flag on the cookie so it will only get sent over HTTPS.

There are also browser add-ons that will allow you to create arbitrary cookies, but all modern browsers have a JavaScript console.