X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=o2common%2Fauthmw%2Fauthmiddleware.py;h=31412633379d1c1cb116b8662794db50e5234f09;hb=81a50cbca7ff0b0535463ed4aa21cf5d819d5cd7;hp=c70adfcf7dc8a88785f572be542eb6728205a0aa;hpb=5601b5899b0fd15748ae0474de9f5f6dda72864c;p=pti%2Fo2.git diff --git a/o2common/authmw/authmiddleware.py b/o2common/authmw/authmiddleware.py index c70adfc..3141263 100644 --- a/o2common/authmw/authmiddleware.py +++ b/o2common/authmw/authmiddleware.py @@ -15,6 +15,8 @@ from werkzeug.wrappers import Request, Response from o2common.helper import o2logging from o2common.authmw.authprov import auth_definer +from flask_restx._http import HTTPStatus +import json logger = o2logging.get_logger(__name__) @@ -28,6 +30,30 @@ class AuthRequiredExp(Exception): 'WWW-Authenticate': '{}'.format(self.value)} +class AuthProblemDetails(): + def __init__(self, code: int, detail: str, path: str, + title=None, instance=None + ) -> None: + self.status = code + self.detail = detail + self.type = path + self.title = title if title is not None else self.getTitle(code) + self.instance = instance if instance is not None else [] + + def getTitle(self, code): + return HTTPStatus(code).phrase + + def serialize(self): + details = {} + for key in dir(self): + if key == 'ns' or key.startswith('__') or \ + callable(getattr(self, key)): + continue + else: + details[key] = getattr(self, key) + return json.dumps(details, indent=True) + + class AuthFailureExp(Exception): def __init__(self, value): self.value = value @@ -37,9 +63,14 @@ class AuthFailureExp(Exception): 'WWW-Authenticate': '{}'.format(self.value)} -def _response_wrapper(environ, start_response, header): +def _response_wrapper(environ, start_response, header, detail): res = Response(headers=header, - mimetype='text/plain', status=401) + mimetype='application/json', status=401, response=detail) + return res(environ, start_response) + + +def _internal_err_response_wrapper(environ, start_response, detail): + res = Response(mimetype='application/json', status=500, response=detail) return res(environ, start_response) @@ -53,11 +84,11 @@ class authmiddleware(): self.app = app def __call__(self, environ, start_response): - logger.info(__name__ + 'authentication middleware') + logger.debug(__name__ + 'authentication middleware') req = Request(environ, populate_request=True, shallow=True) + auth_token = None try: - auth_header = req.headers['Authorization'] - + auth_header = req.headers.get('Authorization', None) if auth_header: auth_token = auth_header.split(" ")[1] @@ -65,19 +96,44 @@ class authmiddleware(): # invoke underlying auth mdw to make k8s/keystone api ret = ad.authenticate(auth_token) if ret is True: - logger.info( + logger.debug( "auth success with oauth token: " + auth_token) - return self.app(environ, start_response) + try: + return self.app(environ, start_response) + except Exception as ex: + logger.error( + 'Internal exception happend \ + ed {}'.format(str(ex)), exc_info=True) + prb = AuthProblemDetails( + 500, 'Internal error.', req.path) + return \ + _internal_err_response_wrapper( + environ, + start_response, prb.serialize()) else: raise AuthFailureExp( 'Bearer realm="Authentication Failed"') else: raise AuthRequiredExp('Bearer realm="Authentication Required"') except AuthRequiredExp as ex: - return _response_wrapper(environ, start_response, ex.dictize()) + prb = AuthProblemDetails(401, ex.value, req.path) + return _response_wrapper(environ, start_response, + ex.dictize(), prb.serialize()) except AuthFailureExp as ex: - return _response_wrapper(environ, start_response, ex.dictize()) - except Exception: - hint = 'Bearer realm="Authentication Required"' + prb = AuthProblemDetails(401, ex.value, req.path) return _response_wrapper(environ, start_response, - AuthRequiredExp(hint).dictize()) + ex.dictize(), prb.serialize()) + except Exception as ex: + if auth_token: + logger.error('Internal exception happended {}'.format( + str(ex)), exc_info=True) + prb = AuthProblemDetails(500, 'Internal error.', req.path) + return \ + _internal_err_response_wrapper( + environ, start_response, prb.serialize()) + else: + logger.debug('Auth token missing or not obtained.') + ex = AuthRequiredExp('Bearer realm="Authentication Required"') + prb = AuthProblemDetails(401, ex.value, req.path) + return _response_wrapper(environ, start_response, + ex.dictize(), prb.serialize())