Make the auth error in ProblemDetails. 94/9794/1
authordliu5 <david.liu@windriver.com>
Mon, 14 Nov 2022 05:35:05 +0000 (13:35 +0800)
committerJackie Huang <jackie.huang@windriver.com>
Fri, 25 Nov 2022 08:19:23 +0000 (16:19 +0800)
Issue: INF-355

Signed-off-by: dliu5 <david.liu@windriver.com>
Change-Id: If9a469b4bd689e0aa7f1248968d1e72a925826da

o2common/authmw/authmiddleware.py

index 032e735..cd9df4b 100644 (file)
@@ -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,14 +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):
-    res = Response(mimetype='text/plain', status=500)
+def _internal_err_response_wrapper(environ, start_response, detail):
+    res = Response(mimetype='application/json', status=500, response=detail)
     return res(environ, start_response)
 
 
@@ -77,19 +103,29 @@ class authmiddleware():
                         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)
+                            _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())
+            prb = AuthProblemDetails(401, ex.value, req.path)
+            return _response_wrapper(environ, start_response,
+                                     ex.dictize(), prb.serialize())
         except Exception as ex:
             logger.error('Internal exception happended {}'.format(
                 str(ex)), exc_info=True)
-            return _internal_err_response_wrapper(environ, start_response)
+            prb = AuthProblemDetails(500, 'Internal error.', req.path)
+            return \
+                _internal_err_response_wrapper(environ,
+                                               start_response, prb.serialize())