From 7f0275aaa1f38e0f58d9d196dae7938dfb756c68 Mon Sep 17 00:00:00 2001 From: Varun Valada Date: Thu, 26 Sep 2024 15:53:34 -0500 Subject: [PATCH] Change endpoint to post and use basic authorization scheme --- server/src/api/v1.py | 21 +++++++++++++++------ server/tests/conftest.py | 22 ++++++++++------------ server/tests/test_v1.py | 33 +++++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/server/src/api/v1.py b/server/src/api/v1.py index 91298a97..ca7b2fdc 100644 --- a/server/src/api/v1.py +++ b/server/src/api/v1.py @@ -675,8 +675,6 @@ def validate_client_key_pair(client_id: str, client_key: str): """ Checks client_id and key pair for validity and returns their permissions """ - if client_key is None: - return None client_key_bytes = client_key.encode("utf-8") client_permissions_entry = database.mongo.db.client_permissions.find_one( { @@ -685,7 +683,8 @@ def validate_client_key_pair(client_id: str, client_key: str): ) if client_permissions_entry is None or not bcrypt.checkpw( - client_key_bytes, client_permissions_entry["client_secret_hash"] + client_key_bytes, + client_permissions_entry["client_secret_hash"].encode("utf8"), ): return None permissions = client_permissions_entry["permissions"] @@ -695,10 +694,20 @@ def validate_client_key_pair(client_id: str, client_key: str): SECRET_KEY = os.environ.get("JWT_SIGNING_KEY") -@v1.get("/authenticate/token/") -def authenticate_client_get(client_id: str): +@v1.post("/oauth2/token") +def authenticate_client_post(): """Get JWT with priority and queue permissions""" - client_key = request.headers.get("client-key") + auth_header = request.authorization + if auth_header is None: + return "No authorization header specified", 401 + client_id = auth_header["username"] + client_key = auth_header["password"] + if client_id is None or client_key is None: + return ( + "Client id and key must be specified in authorization header", + 401, + ) + allowed_resources = validate_client_key_pair(client_id, client_key) if allowed_resources is None: return "Invalid client id or client key", 401 diff --git a/server/tests/conftest.py b/server/tests/conftest.py index 249ace8e..bdf2a3f6 100644 --- a/server/tests/conftest.py +++ b/server/tests/conftest.py @@ -16,7 +16,6 @@ """ Fixtures for testing """ - from dataclasses import dataclass import pytest import mongomock @@ -71,17 +70,16 @@ def mongo_app_with_permissions(mongo_app): client_id = "my_client_id" client_key = "my_client_key" client_salt = bcrypt.gensalt() - client_key_hash = bcrypt.hashpw(client_key.encode("utf-8"), client_salt) - permissions = [ - { - "max_priority": 100, - "queue_name": "myqueue", - }, - { - "max_priority": 200, - "queue_name": "myqueue2", - }, - ] + client_key_hash = bcrypt.hashpw( + client_key.encode("utf-8"), client_salt + ).decode("utf-8") + + permissions = { + "max_priority": { + "myqueue": 100, + "myqueue2": 200, + } + } mongo.client_permissions.insert_one( { "client_id": client_id, diff --git a/server/tests/test_v1.py b/server/tests/test_v1.py index 317a5390..16c0c1b0 100644 --- a/server/tests/test_v1.py +++ b/server/tests/test_v1.py @@ -21,6 +21,7 @@ from io import BytesIO import json import os +import base64 import jwt @@ -729,13 +730,25 @@ def test_get_queue_wait_times(mongo_app): assert output.json["queue2"]["50"] == 30.0 -def test_authenticate_client_get(mongo_app_with_permissions): +def create_auth_header(client_id: str, client_key: str) -> dict: + """ + Creates authorization header with base64 encoded client_id + and client key using the Basic scheme + """ + id_key_pair = f"{client_id}:{client_key}" + base64_encoded_pair = base64.b64encode(id_key_pair.encode("utf-8")).decode( + "utf-8" + ) + return {"Authorization": f"Basic {base64_encoded_pair}"} + + +def test_authenticate_client_post(mongo_app_with_permissions): """Tests authentication endpoint which returns JWT with permissions""" app, _, client_id, client_key, permissions = mongo_app_with_permissions v1.SECRET_KEY = "my_secret_key" - output = app.get( - f"/v1/authenticate/token/{client_id}", - headers={"client-key": client_key}, + output = app.post( + "/v1/oauth2/token", + headers=create_auth_header(client_id, client_key), ) assert output.status_code == 200 token = output.data @@ -756,9 +769,9 @@ def test_authenticate_invalid_client_id(mongo_app_with_permissions): app, _, _, client_key, _ = mongo_app_with_permissions v1.SECRET_KEY = "my_secret_key" client_id = "my_wrong_id" - output = app.get( - f"/v1/authenticate/token/{client_id}", - headers={"client-key": client_key}, + output = app.post( + "/v1/oauth2/token", + headers=create_auth_header(client_id, client_key), ) assert output.status_code == 401 @@ -772,8 +785,8 @@ def test_authenticate_invalid_client_key(mongo_app_with_permissions): v1.SECRET_KEY = "my_secret_key" client_key = "my_wrong_key" - output = app.get( - f"/v1/authenticate/token/{client_id}", - headers={"client-key": client_key}, + output = app.post( + "/v1/oauth2/token", + headers=create_auth_header(client_id, client_key), ) assert output.status_code == 401