From 0c281d0c2c5fb2e584abaa0f3965076ebc130394 Mon Sep 17 00:00:00 2001
From: Robert Goldmann <deadlocker@gmx.de>
Date: Wed, 23 Sep 2020 22:23:40 +0200
Subject: [PATCH] Fixed #4 - api key authentication

---
 docs/api.yml                       |  7 +++++++
 settings-example.json              |  3 ++-
 src/blueprints/Routes.py           |  2 ++
 src/logic/AuthenticationWrapper.py | 22 ++++++++++++++++++++++
 4 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 src/logic/AuthenticationWrapper.py

diff --git a/docs/api.yml b/docs/api.yml
index 12d8f76..8f8ef45 100644
--- a/docs/api.yml
+++ b/docs/api.yml
@@ -139,6 +139,13 @@ paths:
     post:
       summary: Adds a new measurement. Non-existent device or sensor will be created automatically.
       operationId: addMeasurement
+      parameters:
+        - in: header
+          name: apiKey
+          description: The api key
+          required: true
+          schema:
+            type: string
       requestBody:
         description: Measurement to add
         required: true
diff --git a/settings-example.json b/settings-example.json
index 20725d4..3c724fa 100644
--- a/settings-example.json
+++ b/settings-example.json
@@ -11,6 +11,7 @@
         "databasePath": "storageLeaf.db"
     },
     "api": {
-        "url": "http://localhost:10003"
+        "url": "http://localhost:10003",
+        "key": ""
     }
 }
\ No newline at end of file
diff --git a/src/blueprints/Routes.py b/src/blueprints/Routes.py
index fe334f8..524e729 100644
--- a/src/blueprints/Routes.py
+++ b/src/blueprints/Routes.py
@@ -7,6 +7,7 @@ import yaml
 from flask import Blueprint, request, jsonify, render_template
 
 from logic import Constants
+from logic.AuthenticationWrapper import require_api_key
 from logic.Database import Database
 from logic.RequestValidator import ValidationError, RequestValidator
 
@@ -96,6 +97,7 @@ def construct_blueprint(settings, version):
         return jsonify(database.get_all_measurements_for_sensor(sensorID))
 
     @routes.route('/measurements', methods=['POST'])
+    @require_api_key(password=settings['api']['key'])
     def addMeasurement():
         try:
             parameters = RequestValidator.validate(request, DeviceParameters.get_values())
diff --git a/src/logic/AuthenticationWrapper.py b/src/logic/AuthenticationWrapper.py
new file mode 100644
index 0000000..f3a87ab
--- /dev/null
+++ b/src/logic/AuthenticationWrapper.py
@@ -0,0 +1,22 @@
+from functools import wraps
+
+from flask import request, jsonify
+
+
+def require_api_key(password):
+    def wrap_route(func):
+        @wraps(func)
+        def check_api_key(*args, **kwargs):
+            apiKey = request.headers.get('apiKey')
+            if not apiKey:
+                return jsonify({'message': 'apiKey missing'}), 401
+
+            if apiKey == password:
+                # redirect to requested url
+                return func(*args, **kwargs)
+
+            return jsonify({'message': 'apiKey invalid'}), 401
+
+        return check_api_key
+
+    return wrap_route
-- 
GitLab