I have users resource in my app and have implemented a BasicAuth scheme.
Here are my security requirements -
The simplest way to implement these requirements would be to have access to the lookup dictionary in the check_auth method, then I could compare the authenticated user with the email param. But I could not find any way to do this. Instead I came up with the following hacky solution using event hooks.
class UserAuth(BasicAuth):
def check_auth(self, username, password, allowed_roles, resource, method):
try:
user = db.session.query(User).filter(User.email == username).one()
return user.authenticate(password)
except Exception as e:
# TODO: Log this exception
print('Error - {}'.format(e))
return False
def authz(req, lookup):
authn_user = db.session.query(User).filter(User.email == req.authorization['username']).one()
if 'email' in lookup and lookup['email'] == req.authorization['username']:
print('User requesting their own profile')
return
elif authn_user.is_superuser:
print('Superuser requesting something')
return
else:
print('Not authorized. Sabotaging request.')
lookup['email'] = 'None'
app.on_pre_GET_users += authz
Snippet from my settings.py file -
DOMAIN['users']['public_methods'] = ['POST']
DOMAIN['users']['additional_lookup'] = {'url': 'regex("[\w]+@[\w]+\.[\w]+")', 'field': 'email'}
Is there a better way to design this?
One simple option is to use the request
object from Flask:
from flask import request
class UserAuth(BasicAuth):
def check_auth(self, username, password, allowed_roles, resource, method):
# you can inspect the request object here
print request.args, request.url, request.headers
return True