Helper functions (and blueprints) for integrating tinyauth authorization into your flask microservices.
from flask import Flask
from flask_tinyauth import authorize_or_401
app = Flask(__name__)
app.config['TINYAUTH_SERVICE'] = 'test'
app.config['TINYAUTH_ENDPOINT'] = 'http://localhost/'
app.config['TINYAUTH_ACCESS_KEY_ID'] = 'gatekeeper'
app.config['TINYAUTH_SECRET_ACCESS_KEY'] = 'keymaster'
@app.route('/api/v1/apples/list')
def list_apples():
authorize_or_401('ListApples', 'apples')
return jsonify([{'name': 'fred', 'weight': 50, 'color': 'red'}])
@app.route('/api/v1/apples/<name:path>')
def get_apple(name):
authorize_or_401('GetApple', 'apples', name)
return jsonify({'name': 'fred', 'weight': 50, 'color': 'red'})
Accessing /api/v1/apples/list
will do a permissions test for ListApples
with resource set to arn:tinyauth:test:default::apples/
. Accessing /api/v1/apples/fred
will do a permissions test for GetApple
with resource set to arn:tinyauth:test:default::apples/fred
.
This helper will return a 401 response (via flasks abort()
mechanism) with a JSON error message if the user is not authenticated or does not have the required access.
The authorize_or_raise
variant works exactly the same as authorize_or_401
only it allows authentication and authorization exceptions to be raised. These can then be handled by flask and app.errorhandler
:
from flask import Flask
from flask_tinyauth import AuthorizationFailed, authorize_or_401
app = Flask(__name__)
app.config['TINYAUTH_SERVICE'] = 'test'
app.config['TINYAUTH_ENDPOINT'] = 'http://localhost/'
app.config['TINYAUTH_ACCESS_KEY_ID'] = 'gatekeeper'
app.config['TINYAUTH_SECRET_ACCESS_KEY'] = 'keymaster'
@app.route('/api/v1/apples/list')
def list_apples():
authorize_or_raise('ListApples', 'apples')
return jsonify([{'name': 'fred', 'weight': 50, 'color': 'red'}])
@self.app.errorhandler(AuthorizationFailed)
def handle_invalid_usage(error):
return 'Authorization has failed'
flask_tinyauth is primarily for authenticating for API microservices. But you can build user interfaces with it too. In that case authorize_or_401
is not appropriate - you will want to redirect the user to a login page not show them a JSON 401.
You can do this with authorize_or_login
from flask import Flask
from flask_tinyauth import authorize_or_login
app = Flask(__name__)
app.config['TINYAUTH_SERVICE'] = 'test'
app.config['TINYAUTH_ENDPOINT'] = 'http://localhost/'
app.config['TINYAUTH_ACCESS_KEY_ID'] = 'gatekeeper'
app.config['TINYAUTH_SECRET_ACCESS_KEY'] = 'keymaster'
@app.route('/')
def list_apples():
authorize_or_login('AccessWebInterface')
return '<html></html>'
The following is the bare minimum required to get a functional login page for your site (and logoff). Note that this does not protect any of your views by itself.
from flask import Flask
from flask_tinyauth import login_blueprint
app = Flask(__name__)
app.config['TINYAUTH_SERVICE'] = 'test'
app.config['TINYAUTH_ENDPOINT'] = 'http://localhost/'
app.config['TINYAUTH_ACCESS_KEY_ID'] = 'gatekeeper'
app.config['TINYAUTH_SECRET_ACCESS_KEY'] = 'keymaster'
app.register_blueprint(login_blueprint)
This assumes that you have an API at /api
guarded with authorize_or_401
or authorize_or_raise
and a page at /
that serves your React app guarded with authorize_or_login
.
The backend to connect to is controlled by these settings:
TINYAUTH_ENDPOINT
: Thehttps://
endpoint to access to authorize a HTTP request.TINYAUTH_ACCESS_KEY_ID
: Access key for a tinyauth user with permission to authorize requests for this service.TINYAUTH_SECRET_ACCESS_KEY
: Secret key for this userTINYAUTH_ENDPOINT_VERIFY
: Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use. Defaults to True.
Each permission check is for a permission and an arn
that globally identifies an instance of a resource. An arn is constructed in the following form:
arn:partition:service:region::resource_type/resource_instance
The following settings control the arn
used for your service.
TINYAUTH_PARTITION
: Optional, defaults totinyauth
. A partition is a multi-region tinyauth cluster. For example, Amazon have theaws
partition and theaws-cn
partition. IAM users existing in theaws
partition work for all regions in theaws
partition. At a more modest scale, you likely have a production and test partition.TINYAUTH_SERVICE
: Required. This is your services name. This should be short and lowercase. Its how your microservice can be differentiated from other microservices of different types.TINYAUTH_REGION
: Optional, defaults todefault
. If you have multiple instances of your service in different data centers then you have regions, and tinyauth can consider there authorization requirements seperately.
Additionally development environments can set:
TINYAUTH_BYPASS
: Allauthorize_*
functions return that a user is authorized, completely bypassing auditing, authentication and authorization.
You can get a simple dev environment with Docker and docker-compose. Dev happens on macOS with Docker for Mac:
docker-compose build
docker-compose up
This will automatically run any migrations.
You can run tests with:
docker-compose run --rm flask py.test flask_tinyauth/
And run flake8 with:
docker-compose run --rm flask flake8 flask_tinyauth/