Change API protocol to fix json normalization

A dictionnary's order is not deterministic (eg. when switching python
versions), thus the previous protocol would often fail to authenticate a
legitimate request.
This commit is contained in:
Théophile Bastian 2017-10-16 20:02:36 +02:00
parent f01c0b5594
commit 2264b0886f
2 changed files with 17 additions and 8 deletions

View file

@ -33,7 +33,8 @@ def sendReq(url):
mac = hmac.new(key.encode('utf-8'),
msg=str(int(time)).encode('utf-8'),
digestmod=hashlib.sha256)
mac.update(json.dumps(payload).encode('utf-8'))
payload_enc = json.dumps(payload)
mac.update(payload_enc.encode('utf-8'))
auth = {
'keyId': keyId,
@ -43,7 +44,7 @@ def sendReq(url):
return {
'auth': auth,
'req': payload,
'req': payload_enc,
}
def decorator(fct):

View file

@ -20,8 +20,7 @@ def authentify(data, payload):
except models.ApiKey.DoesNotExist:
return response.HttpResponseForbidden('Bad authentication')
normPayload = json.dumps(payload)
if not key.isCorrect(data['timestamp'], data['hmac'], normPayload):
if not key.isCorrect(data['timestamp'], data['hmac'], payload):
return response.HttpResponseForbidden('Bad authentication')
@ -30,22 +29,31 @@ def apiView(required=[]):
@csrf_exempt
def wrap(request, *args, **kwargs):
try:
data = json.loads(request.body)
except json.decoder.JSONDecoreError:
data = json.loads(request.body.decode('utf-8'))
except TypeError:
return response.HttpResponseBadRequest("Bad packet format")
except json.decoder.JSONDecodeError:
return response.HttpResponseBadRequest("Bad json")
try:
authData = data['auth']
reqData = data['req']
reqDataOrig = data['req']
except KeyError:
return response.HttpResponseBadRequest("Bad request format")
try:
reqData = json.loads(reqDataOrig)
except TypeError:
return response.HttpResponseBadRequest("Bad packet format")
except json.decoder.JSONDecodeError:
return response.HttpResponseBadRequest("Bad inner json")
for field in required:
if field not in reqData:
return response.HttpResponseBadRequest(
"Missing field {}".format(field))
authVal = authentify(authData, reqData)
authVal = authentify(authData, reqDataOrig)
if authVal is not None:
return authVal