Edd Mann Developer

Creating a Basic Auth. WSGI Middleware in Python

With my recent dedicated introduction to the Python language I have become very appreciative of the highly composable nature of WSGI applications. In a functional style you are able to compose a desired application from many different components, using the middleware ideology. The benefits of this approach can be clearly seen in the contrived example depicted below, which is based on my previous Flask example.

class Auth():

    def __init__(self, app):
        self._app = app

    def __call__(self, environ, start_response):
        if self._authenticated(environ.get('HTTP_AUTHORIZATION')):
            return self._app(environ, start_response)
        return self._login(environ, start_response)

    def _authenticated(self, header):
        from base64 import b64decode
        if not header:
            return False
        _, encoded = header.split(None, 1)
        decoded = b64decode(encoded).decode('UTF-8')
        username, password = decoded.split(':', 1)
        return username == password

    def _login(self, environ, start_response):
        start_response('401 Authentication Required',
            [('Content-Type', 'text/html'),
             ('WWW-Authenticate', 'Basic realm="Login"')])
        return [b'Login']


def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'Hello, world!']


if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    httpd = make_server('', 8080, Auth(app))
    print('Serving on port 8080...')
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        print('Goodbye!')

As you can see we are able to secure a specified WSGI application with the provided ‘Auth’ middleware. The advantages of using this loosely coupled approach allows us to easily replace the authentication implementation with an alternative (i.e. OAuth) in future builds, without alteration to encapsulated applications.