Flask: how to register a wrapper to all methods
You can definitely some of the functionality of flask-httpauth yourself, if you wish :-P
I would think you will need to play some before_request
games (not very beautiful), or alternatively call flask's add_url_rule
with a decorated method for each api endpoint (or have a route
decorator of your own that will do this). The add_url_rule
gets a view function that is usually your api endpoint handler, but in your case, will be a wrapped method in a manner very much like the one you gave in the post (auth_middleware
).
The gist of it:
from flask import Flask, make_response, requestapp = Flask(__name__)def view_wrapper(fn): """ Create a wrapped view function that checks user authorization """ def protected_view(*a, **ka): # if the allow_anonymous annotation is set then bypass this auth if hasattr(fn, '_allow_anonymous') and fn._allow_anonymous: return fn(*a, **ka) # consult werkzeug's authorization mixin user, password = (request.authorization.username, request.authorization.password) if request.authorization else (None, None) if user is None or not check(user, password): err_response = make_response(text, 401) err_response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm return err_response return fn(*a, **ka) return protected_view# An endpointdef hello(): return 'hello there'app.add_url_rule('/', 'hello', view_wrapper(hello))
Of course, this can (and should) be further enhanced with Blueprints, etc.
Note #1: this is cribbed from separate answers in SO.
Note #2: this doesnt use blueprints. Again, I'm new to flask and I appreciate that blueprints will help the app scale but one step at a time...
def allow_anonymous(decorated_function): decorated_function.is_public = True return decorated_function@app.before_requestdef auth_middleware(): fn = app.view_functions[request.endpoint] if hasattr(fn, 'allow_anonymous') and fn.allow_anonymous: # anonymous permitted return elif my_custom_authentication(): # anonymous not permitted authentication succeeded return else: # anonymous not permitted authentication failed err_response = make_response(text, 401) err_response.headers['WWW-Authenticate'] = 'Basic realm="%s"' % realm return err_response@app.route('/public_thing')@allow_anonymousdef public_thing(): return 'yo'@app.route('/regular_thing')def regular_thing(): return 'if you can read this youre authenticated.'