Multiple authentication schemes#
At times it may be required to have multiple authentication schemes, for example if your application supports separated staff and admin logins. Quart-Auth supports this via the usage of multiple non-singleton instances.
Note
The documentation throughout assumes a single, singleton, instance is being used except on this page.
To utilise this feature you can setup multiple non-singleton instances, for example,
from quart_auth import QuartAuth
staff_auth = QuartAuth(
app, attribute_name="staff", cookie_name="STAFF", salt="staff salt", singleton=False
)
admin_auth = QuartAuth(
app, attribute_name="admin", cookie_name="ADMIN", salt="admin salt", singleton=False
)
The unique naming is critical if you wish to avoid security vulnerabilities.
The existing global functions all map to methods on the QuartAuth
class with the exception of login_required
and
current_user
. These can be implmeneted as follows,
from werkzeug.local import LocalProxy
current_staff = LocalProxy(lambda: staff_auth.load_user())
def staff_login_required(func):
@wraps(func)
async def wrapper(*args, **kwargs):
if not await current_staff.is_authenticated:
raise Unauthorized()
else:
return await current_app.ensure_async(func)(*args, **kwargs)
return wrapper
current_admin = LocalProxy(lambda: admin_auth.load_user())
def admin_login_required(func):
@wraps(func)
async def wrapper(*args, **kwargs):
if not await current_admin.is_authenticated:
raise Unauthorized()
else:
return await current_app.ensure_async(func)(*args, **kwargs)
return wrapper
As a warning/reminder when logging a user in, be sure to set the
action to WRITE
or WRITE_PERMANENT
as makes sense to you, i.e.
@app.post("/staff/login/")
async def login_staff() -> ResponseReturnValue:
...
staff_auth.login_user(AuthUser("2", Action.WRITE))