Very simple authentication using one-time cookie on nginx

Ash picture Ash · May 23, 2012 · Viewed 11k times · Source

I have a site intended only for private consumption by 3 coders. It's simple HTML served by nginx directly but intended for consumption inside and outside the office.

I want to have a simple password or authentication scheme. I could use HTTP auth but these tend to expire fairly often which makes it a pain for people to use. I'm also nervous it's much easier for someone to sniff than cookies.

So I'm wondering if I could just set a cookie on their browsers in JavaScript with a unique long ID and somehow tell nginx to only accept requests (for a particular subdomain) which has this cookie.

Is this simple enough to do? How do I

  1. tell nginx to filter by cookie
  2. in the browser, set a cookie that never expires?

Answer

JosephH picture JosephH · Aug 15, 2017

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;
  }
}