Changes on auth.py: better token extraction and validation, better logging, fix to validate response interpretation + changes to oauth.py to properly test changes to auth.py
authordurandn
Fri, 01 Apr 2016 11:43:01 +0200
changeset 40 10a829681179
parent 39 5fb10e370c61
child 41 376b5d6e9756
Changes on auth.py: better token extraction and validation, better logging, fix to validate response interpretation + changes to oauth.py to properly test changes to auth.py
oauth/oauth.py
server/src/metaeducation/auth.py
--- a/oauth/oauth.py	Thu Mar 31 17:16:22 2016 +0200
+++ b/oauth/oauth.py	Fri Apr 01 11:43:01 2016 +0200
@@ -230,13 +230,24 @@
 @app.route('/rest/oauth/validate/<token>')
 def validate_token(token):
     database_token = Token.query.filter_by(access_token=token).first()
-    related_client = database_token.client
+    uris = ""
+    scopes = ""
+    if database_token is not None:
+        related_client = database_token.client
+        scopes = database_token.scopes
+        uris = related_client.redirect_uris
+    if database_token is not None and database_token.access_token == token:
+        validate_errors = "0"
+        error_description = ""
+    else:
+        validate_errors = "1"
+        error_description = "token not found in db?"
     return jsonify(
         access_token=token,
-        redirect_uri= related_client.redirect_uris, 
-        error=0,
-        description= "",
-        scope=database_token.scopes
+        redirect_uri= uris, 
+        errors=validate_errors,
+        description= error_description,
+        scope=scopes
     )
 
 @app.route('/ws/resource/', methods=["POST", "PUT"])
--- a/server/src/metaeducation/auth.py	Thu Mar 31 17:16:22 2016 +0200
+++ b/server/src/metaeducation/auth.py	Fri Apr 01 11:43:01 2016 +0200
@@ -25,18 +25,52 @@
             logger.debug("CLIENT CREDENTIAL AUTH: User does not exist, abort")
             return
         if 'HTTP_AUTHORIZATION' not in request.META:
-            logger.debug("CLIENT CREDENTIAL AUTH: no token, abort")
+            logger.debug("CLIENT CREDENTIAL AUTH: no Authorization header, abort")
             return
         else:
-            token = re.search("(?<=\s).*", request.META["HTTP_AUTHORIZATION"]).group(0)
+            match = re.search("(?<=Bearer\s).*", request.META["HTTP_AUTHORIZATION"])
+            if match is None or len(match.group(0)) == 0:
+                logger.debug("CLIENT CREDENTIAL AUTH: Authorization header format is invalid: %r", request.META["HTTP_AUTHORIZATION"])
+                return
+            else:    
+                token = match.group(0)
             logger.debug("CLIENT CREDENTIAL AUTH: token is %r", token)
         # send token to Oauth server
-        token_validate_response = requests.get(
-            settings.MTDC_VALIDATE_TOKEN_BASE_URL+token+"?redirect_uri="+parse.quote_plus(settings.MTDC_GED_BASE_URL)
-        )
+        validation_service_url = settings.MTDC_VALIDATE_TOKEN_BASE_URL+token+"?redirect_uri="+parse.quote_plus(settings.MTDC_GED_BASE_URL)
+        logger.debug("CLIENT CREDENTIAL AUTH: Requesting validation service %r", validation_service_url)
+        token_validate_response = requests.get(validation_service_url)
         if token_validate_response.status_code != 200:
-            logger.debug("CLIENT CREDENTIAL AUTH: token validate failed, abort")
+            logger.warning("CLIENT CREDENTIAL AUTH: Validation service didn't response with 200, there may be a problem")
             return
+        validate_response_json = json.loads(token_validate_response.text)
+        
+        # Response json validation
+        if "access_token" not in validate_response_json.keys():
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token validate response doesn't have an access_token key!")
+        elif validate_response_json["access_token"] != token:
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token in response %r is different from token extracted from header %r", validate_response_json["access_token"], token)
+        
+        if "redirect_uri" not in validate_response_json.keys():
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token validate response doesn't have a redirect_uri key!")
+        elif validate_response_json["redirect_uri"] != parse.quote_plus(settings.MTDC_GED_BASE_URL):
+            logger.warning("CLIENT_CREDENTIAL_AUTH: redirect_uri in response %r is different from redirect_uri transmitted in request %r", validate_response_json["redirect_uri"], parse.quote_plus(settings.MTDC_GED_BASE_URL))
+        
+        if "errors" not in validate_response_json.keys():
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token validate  response doesn't have an error key!")
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Aborting as the errors keys is required to check if token was validated")
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Response was %r", validate_response_json)
+            return
+        elif validate_response_json["errors"] != "0" :
+            logger.debug("CLIENT CREDENTIAL AUTH: There was an error validating the token: %r", validate_response_json.get("description", "no error description in json response"))
+            return
+
+        if "description" not in validate_response_json.keys():
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token validate response doesn't have a description key!")
+            
+        if "scope" not in validate_response_json.keys():
+            logger.warning("CLIENT_CREDENTIAL_AUTH: Token validate response doesn't have a scope key!")
+        
+        
         logger.debug("CLIENT CREDENTIAL AUTH: user %r is authenticated by token %r, auth success", external_id, token)
         return (user, None)