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:
parent
f01c0b5594
commit
2264b0886f
2 changed files with 17 additions and 8 deletions
|
@ -33,7 +33,8 @@ def sendReq(url):
|
||||||
mac = hmac.new(key.encode('utf-8'),
|
mac = hmac.new(key.encode('utf-8'),
|
||||||
msg=str(int(time)).encode('utf-8'),
|
msg=str(int(time)).encode('utf-8'),
|
||||||
digestmod=hashlib.sha256)
|
digestmod=hashlib.sha256)
|
||||||
mac.update(json.dumps(payload).encode('utf-8'))
|
payload_enc = json.dumps(payload)
|
||||||
|
mac.update(payload_enc.encode('utf-8'))
|
||||||
|
|
||||||
auth = {
|
auth = {
|
||||||
'keyId': keyId,
|
'keyId': keyId,
|
||||||
|
@ -43,7 +44,7 @@ def sendReq(url):
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'auth': auth,
|
'auth': auth,
|
||||||
'req': payload,
|
'req': payload_enc,
|
||||||
}
|
}
|
||||||
|
|
||||||
def decorator(fct):
|
def decorator(fct):
|
||||||
|
|
20
api/views.py
20
api/views.py
|
@ -20,8 +20,7 @@ def authentify(data, payload):
|
||||||
except models.ApiKey.DoesNotExist:
|
except models.ApiKey.DoesNotExist:
|
||||||
return response.HttpResponseForbidden('Bad authentication')
|
return response.HttpResponseForbidden('Bad authentication')
|
||||||
|
|
||||||
normPayload = json.dumps(payload)
|
if not key.isCorrect(data['timestamp'], data['hmac'], payload):
|
||||||
if not key.isCorrect(data['timestamp'], data['hmac'], normPayload):
|
|
||||||
return response.HttpResponseForbidden('Bad authentication')
|
return response.HttpResponseForbidden('Bad authentication')
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,22 +29,31 @@ def apiView(required=[]):
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def wrap(request, *args, **kwargs):
|
def wrap(request, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
data = json.loads(request.body)
|
data = json.loads(request.body.decode('utf-8'))
|
||||||
except json.decoder.JSONDecoreError:
|
except TypeError:
|
||||||
|
return response.HttpResponseBadRequest("Bad packet format")
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
return response.HttpResponseBadRequest("Bad json")
|
return response.HttpResponseBadRequest("Bad json")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
authData = data['auth']
|
authData = data['auth']
|
||||||
reqData = data['req']
|
reqDataOrig = data['req']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return response.HttpResponseBadRequest("Bad request format")
|
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:
|
for field in required:
|
||||||
if field not in reqData:
|
if field not in reqData:
|
||||||
return response.HttpResponseBadRequest(
|
return response.HttpResponseBadRequest(
|
||||||
"Missing field {}".format(field))
|
"Missing field {}".format(field))
|
||||||
|
|
||||||
authVal = authentify(authData, reqData)
|
authVal = authentify(authData, reqDataOrig)
|
||||||
if authVal is not None:
|
if authVal is not None:
|
||||||
return authVal
|
return authVal
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue