Git Product home page Git Product logo

nginx-auth's Introduction

nginx-auth

A demo of how to leverage OpenResty (a dynamic web platform based on NGINX and LuaJIT), JSON Web Tokens and OAuth2 to authenticate nginx routes.

The idea is that in order to access any resource, one needs either:

  • Basic Authentication Credentials
  • A JWT token.
  • An OAuth2 provider.

OAuth2

OAuth2 authentication uses oauth2_proxy. specifically in this example, we use GitHub authentication.

JWT

Each token encodes the following data:

{
  "service": "my-service",
  "client": "name-of-client",
  "expires-at": "time-since-epoch"
}

for sake of clarity, our example token would be:

{
  "service": "foo",
  "client": "john.doe",
}

Once a client performs a request, the token is decrypted, and the following checks are made:

  • The request domain equals to the encoded service field. In our example, if a request was made to foo.example.com, it would be authorized. to authorize the root domain, than the service should be "_".

  • The encoded client field is validated against a Redis cluster, to allow more granular token revocation. Redis holds all the registered clients for the specific service, and checks that the encoded client is still registered. Adding a token is as easy as SADD <service> <client>, and to revoke a token one only needs to SREM <service> <client>.

  • The encoded expires-at field is checked against the current time. the request wouldn't pass if the token has expired.

Getting Started

A demo docker-compose file has been created, that fires up Redis & nginx instances. The demo contains a default user with the following user/password: john.doe/secret

open one terminal, and type:

$ docker network create nginx-auth
$ docker-compose nginx up

open another and use the auth tool to perform requests.

Setup

Domain

This example uses the example.com domain:

$ sudo bash -c 'echo "127.0.0.1 auth.example.com foo.example.com  bar.example.com example.com" >> /etc/hosts'`
OAuth2
  1. Go through the steps to setup GitHub OAuth2 authentication.
  2. Use the following Authorization callback URL - http://auth.example.com/oauth2/callback
  3. update the client_id and client_secret values in oath2_proxy/config/oauth2_proxy.cfg
jwt-tool
  1. install the nginx-auth tool into a temporary virtualenv: mktmpenv -n
  2. install the tool: pip install -r tools/requirements.txt
Basic authentication

Use the following snippet to generate basic auth users:

$ cd /path/to/nginx-auth
$ echo -n '<username>:' >> nginx/conf/.htpasswd
$ openssl passwd -apr1 >> nginx/conf/.htpasswd
# Enter a password...

Example usage

The root location (/) handles requests in the following manner:

if request has an 'Authorization' header that starts with `Basic`:
   authorize the request with basic authentication
elif request has an 'Authorization' header that starts with `Bearer`:
   authorize the request using its jwt token
else:
   authorize the request using OAuth2
Basic authentication
# curl while supplying an invalid user
$ curl -u invalid:user http://foo.example.com/secure
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty/1.9.15.1</center>
</body>
</html>

# curl while supplying a valid user
$ curl -u john.doe:secret http://example.com/secure
Hello! you have been authorized!

JWT

# the tool adds the 'expires-at' field that expires 10 seconds after it was generated
$ echo '{"service": "foo", "client": "12345" }'| python tools/auth.py http://foo.example.com/secure
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty/1.9.15.1</center>
</body>
</html>

# Lets add this client, so we'll be able to authenticate...
$ echo '{"service": "foo", "client": "12345" }'| python tools/auth.py http://foo.example.com/secure add
Hello! you have been authorized!

# Lets check if the client can access a different service (bar)
# it shouldn't, because the token is only for the 'foo' sub-domain,
# and we're trying to access the 'bar' sub-domain.
$ echo '{"service": "foo", "client": "12345" }'| python tools/auth.py http://bar.example.com/secure
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty/1.9.15.1</center>
</body>
</html>

# Lets remove the client and check if it can access the 'foo' sub-domain...
$ echo '{"service": "foo", "client": "12345" }'| python tools/auth.py http://foo.example.com/secure rem
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>openresty/1.9.15.1</center>
</body>
</html>
OAuth2 Single-Sign-On
  1. fire up the browser and go to: example.com/secure
  2. you will be redirected to a Sign in page
  3. press the Sign in with a GitHub Account button
  4. you will be redirected to example.com/secure

Environment Variables

Environment Variables Type Description
REDIS_HOST string The redis host. defaults to redis
REDIS_PORT int The redis port. defaults to 6379

nginx-auth's People

Contributors

odedlaz avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.