Skip to content
Snippets Groups Projects

Refactor auth handling wrapper

@@ -6,23 +6,19 @@
"""
import re
import scitokens
from flask import request, current_app
from functools import wraps
from flask import request, current_app
from jwt import InvalidTokenError
import scitokens
from scitokens.utils.errors import SciTokensException
__author__ = 'Duncan Meacher <duncan.meacher@ligo.org>'
from .api.utils import error_as_json
__author__ = 'Duncan Meacher <duncan.meacher@ligo.org>'
def _get_scitokens_params():
config = current_app.config
audience = config['scitokens_audience']
if isinstance(audience, str):
audience = [audience]
scope = config['scitokens_scope']
issuer = config['scitokens_issuer']
return audience, scope, issuer
AUTH_METHODS = {}
def _get_auth_type():
@@ -54,6 +50,22 @@ def _get_auth_type():
return authType
# -- scitokens --------------
def _request_has_token(request):
return request.headers.get("Authorization", "").startswith("Bearer")
def _get_scitokens_params():
config = current_app.config
audience = config['scitokens_audience']
if isinstance(audience, str):
audience = [audience]
scope = config['scitokens_scope']
issuer = config['scitokens_issuer']
return audience, scope, issuer
def _validate_scitoken(request):
# Get token from header
bearer = request.headers.get("Authorization")
@@ -87,6 +99,18 @@ def _validate_scitoken(request):
current_app.logger.info('User SciToken authorised.')
AUTH_METHODS["scitoken"] = (_request_has_token, _validate_scitoken)
# -- X.509 ------------------
def _request_has_x509(request):
return (
'SSL_CLIENT_S_DN' in request.headers
and 'SSL_CLIENT_I_DN' in request.headers
)
def _validate_x509(request):
# Get subject and issuer from header
subject_dn_header = request.headers.get("SSL_CLIENT_S_DN")
@@ -106,55 +130,47 @@ def _validate_x509(request):
current_app.logger.info('User X.509 proxy certificate authorised.')
AUTH_METHODS["grid-mapfile"] = (_request_has_x509, _validate_x509)
# -- handler ----------------
def _auth_error(exc):
current_app.logger.info(f"auth error: '{exc}'")
return error_as_json(exc, 403)
def _authorize(request):
errors = []
authtypes = _get_auth_type()
if authtypes is None:
current_app.logger.info('View request, no authentication required')
return
for authtype in authtypes:
_has, _validate = AUTH_METHODS[authtype]
if _has(request):
try:
_validate(request)
except RuntimeError as exc:
# record the error in case nothing works
errors.append(_auth_error(exc))
continue
# authorized!
return
if not errors:
errors.append(_auth_error("no authorization presented"))
return errors[0] # return the first error
def validate(func):
@wraps(func)
def validator(*args, **kwargs):
try:
authType = _get_auth_type()
if authType is None:
current_app.logger.info('View request, no authentication '
'required')
else:
# Check for SciToken in header
if (
'scitoken' in authType
and 'Authorization' in request.headers
):
current_app.logger.info('View request with SciToken.')
try:
_validate_scitoken(request)
except RuntimeError as exc:
msg = "SciToken authentication failed: {!r}"\
.format(exc)
current_app.logger.info('View request error:'
'{}'.format(msg))
content = {"Error, {}.".format(msg): ""}
return content, 403
# Else, check for X.509 certificate info in header
elif (
'grid-mapfile' in authType
and 'SSL_CLIENT_S_DN' in request.headers
and 'SSL_CLIENT_I_DN' in request.headers
):
current_app.logger.info("View request with X.509 proxy "
"certificate.")
try:
_validate_x509(request)
except RuntimeError as exc:
msg = "X.509 authentication failed: {!r}".format(exc)
current_app.logger.info('View request error:'
'{}'.format(msg))
content = {"Error, {}.".format(msg): ""}
return content, 403
else:
raise RuntimeError("No Authentication Header or X.509 "
"cert info in header")
return func(*args, **kwargs)
except RuntimeError as exc:
msg = "Authentication failed: {!r}".format(exc)
current_app.logger.info('View request error:'
'{}'.format(msg))
content = {"Error, {}.".format(msg): ""}
return content, 403
errors = _authorize(request)
if errors:
return {"errors": errors}, 403
return func(*args, **kwargs)
return validator
Loading