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
--- 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)