Reputation: 1326
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
Upvotes: 21
Views: 20072
Reputation: 37505
There is a really quite simple looking solution that I found from a blog post by Christian Stocker. It implements the following rules:
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;
}
}
Upvotes: 31
Reputation: 8727
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.
Upvotes: 16