Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/cheshirekow/oauthsub

Simple oauth2 subrequest handler for nginx
https://github.com/cheshirekow/oauthsub

nginx oauth2 python python-3 python3

Last synced: 3 days ago
JSON representation

Simple oauth2 subrequest handler for nginx

Awesome Lists containing this project

README

        

========
oauthsub
========

.. image:: https://travis-ci.com/cheshirekow/oauthsub.svg?branch=master
:target: https://travis-ci.com/cheshirekow/oauthsub

.. image:: https://readthedocs.org/projects/oauthsub/badge/
:target: https://oauthsub.rtfd.io

Simple oauth2 subrequest handler for reverse proxies

-------
Purpose
-------

The goal of ``oauthsub`` is to enable simple and secure Single Sign On by
deferring authentication to an ``oauth2`` provider (like google, github,
microsoft, etc).

See the examples in `the documentation`__ for ideas on how best to use it.

.. __: https://oauthsub.rtfd.io

------------
Installation
------------

Install through pip::

pip install oauthsub

or see `the documentation`__ for more options.

.. __: https://oauthsub.rtfd.io

-----
Usage
-----

.. dynamic: usage-begin

.. code:: text

usage: oauthsub [-h] [--dump-config] [-v] [-l {debug,info,warning,error}]
[-c CONFIG_FILE] [-s {flask,gevent,twisted}]
[--rooturl ROOTURL] [--flask-debug [FLASK_DEBUG]]
[--flask-privkey FLASK_PRIVKEY]
[--response-header RESPONSE_HEADER]
[--allowed-domains [ALLOWED_DOMAINS [ALLOWED_DOMAINS ...]]]
[--host HOST] [--port PORT] [--logdir LOGDIR]
[--route-prefix ROUTE_PREFIX]
[--session-key-prefix SESSION_KEY_PREFIX]
[--bypass-key BYPASS_KEY] [--custom-template CUSTOM_TEMPLATE]
[--enable-forbidden [ENABLE_FORBIDDEN]]

This lightweight web service performs authentication. All requests that reach
this service should be proxied through nginx. See:
https://developers.google.com/api-client-library/python/auth/web-app

optional arguments:
-h, --help show this help message and exit
--dump-config Dump configuration and exit
-v, --version show program's version number and exit
-l {debug,info,warning,error}, --log-level {debug,info,warning,error}
Increase log level to include info/debug
-c CONFIG_FILE, --config-file CONFIG_FILE
use a configuration file
-s {flask,gevent,twisted}, --server {flask,gevent,twisted}
Which WGSI server to use
--rooturl ROOTURL The root URL for browser redirects
--flask-debug [FLASK_DEBUG]
Enable flask debugging for testing
--flask-privkey FLASK_PRIVKEY
Secret key used to sign cookies
--response-header RESPONSE_HEADER
If specified, the authenticated user's ``username``
will be passed as a response header with this key.
--allowed-domains [ALLOWED_DOMAINS [ALLOWED_DOMAINS ...]]
List of domains that we allow in the `hd` field of
thegoogle response. Set this to your company gsuite
domains.
--host HOST The address to listening on
--port PORT The port to listen on
--logdir LOGDIR Directory where we store resource files
--route-prefix ROUTE_PREFIX
All flask routes (endpoints) are prefixed with this
--session-key-prefix SESSION_KEY_PREFIX
All session keys are prefixed with this
--bypass-key BYPASS_KEY
Secret string which can be used to bypass
authorization if provided in an HTTP header
`X-OAuthSub-Bypass`
--custom-template CUSTOM_TEMPLATE
Path to custom jinja template
--enable-forbidden [ENABLE_FORBIDDEN]
If true, enables the /forbidden endpoint, to which you
can redirect 401 errors from your reverse proxy. This
page is a simple message with active template but
includes login links that will redirect back to the
forbidden page after a successful auth.

.. dynamic: usage-end

-------------
Configuration
-------------

``oauthsub`` is configurable through a configuration file in python (the file
is ``exec``ed). Each configuration variable can also be specified on the
command line (use ``oauthsub --help`` to see a list of options). If you'd
like to dump a configuration file containing default values use::

oauthsub --dump-config

Which outputs something like:

.. dynamic: config-begin

.. code:: python

# The root URL for browser redirects
rooturl = 'http://localhost'

# Enable flask debugging for testing
flask_debug = False

# Secret key used to sign cookies
flask_privkey = 'KALJE0Unas2dd8ao3p/T55htwbL5RrKX'

# If specified, the authenticated user's ``username`` will be passed as a
# response header with this key.
response_header = None

# List of domains that we allow in the `hd` field of thegoogle response. Set
# this to your company gsuite domains.
allowed_domains = ['gmail.com']

# The address to listening on
host = '0.0.0.0'

# The port to listen on
port = 8081

# Directory where we store resource files
logdir = '/tmp/oauthsub/logs'

# Flask configuration options. Set session config here.
flaskopt = {
"PERMANENT_SESSION_LIFETIME": 864000,
"SESSION_FILE_DIR": "/tmp/oauthsub/session_data",
"SESSION_TYPE": "filesystem"
}

# All flask routes (endpoints) are prefixed with this
route_prefix = '/auth'

# All session keys are prefixed with this
session_key_prefix = 'oauthsub-'

# Secret string which can be used to bypass authorization if provided in an HTTP
# header `X-OAuthSub-Bypass`
bypass_key = None

# Dictionary mapping oauth privider names to the client secrets for that
# provider.
client_secrets = {}

# Path to custom jinja template
custom_template = None

# If true, enables the /forbidden endpoint, to which you can redirect 401 errors
# from your reverse proxy. This page is a simple message with active template
# but includes login links that will redirect back to the forbidden page after a
# successful auth.
enable_forbidden = True

# Which WGSI server to use (flask, gevent, twisted)
server = 'flask'

# This is not used internally, but is used to implement our user lookup
# callback below
_user_map = {
"[email protected]": "alice",
"[email protected]": "bob"
}

# This is a callback used to lookup the user identity based on the credentials
# provided by the authenticator.
def user_lookup(authenticator, parsed_response):
if authenticator.type == "GOOGLE":
# Could also use `id` to lookup based on google user id
return _user_map.get(parsed_response.get("email"))

return None

.. dynamic: config-end

-------------------
Testing the service
-------------------

Test the service directly on localhost, put your client secrets in a
configuration file and (assuming you've enabled
``http://lvh.me:8081/auth/callback`` as an authorized redirect on google)
run with::

oauthsub --flask-debug \
--config /path/to/your/config.py

And then navigate to ``http://localhost:8081/auth`` from your browser.

See the documentation for more detailed testing instructions including how
to test with NGINX.