From 3e148b92bfa81dd36c3516f5b47185c55d47c795 Mon Sep 17 00:00:00 2001
From: hanfi <ccc@spahan.ch>
Date: Mon, 24 Jul 2023 10:13:27 +0200
Subject: [PATCH] add auth for worker endpoints

---
 backend/config.py |  3 +++
 backend/main.py   | 33 +++++++++++++++++++++++++++++++--
 requirements.txt  |  1 +
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/backend/config.py b/backend/config.py
index 313984a..d2da3f0 100644
--- a/backend/config.py
+++ b/backend/config.py
@@ -8,6 +8,9 @@ class Settings(BaseSettings):
     backend_url: str = "http://localhost:8000"
     customer_url: str = "http://localhost:3000"
     worker_url: str = "http://localhost:3002"
+    shared_secret: str = "worker_secret"
+    signing_key: str = "2d18526256a001bc0553c9957897d75d"
+    token_lifetime: int = 60  # auth token lifetime
 
     class Config:
         env_file = ".env"
diff --git a/backend/main.py b/backend/main.py
index 82d1274..fc61189 100644
--- a/backend/main.py
+++ b/backend/main.py
@@ -1,7 +1,10 @@
+import datetime
 from uuid import UUID
 
-from fastapi import Depends, FastAPI, HTTPException, Request
+from fastapi import Depends, FastAPI, HTTPException, Request, status
 from fastapi.middleware.cors import CORSMiddleware
+from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
+from itsdangerous.serializer import Serializer
 from slowapi import Limiter, _rate_limit_exceeded_handler
 from slowapi.errors import RateLimitExceeded
 from slowapi.util import get_remote_address
@@ -26,6 +29,8 @@ app.add_middleware(
 limiter = Limiter(key_func=get_remote_address)
 app.state.limiter = limiter
 app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
+oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
+oauth2_tokener = Serializer(settings.signing_key)
 
 
 # Dependency
@@ -66,7 +71,16 @@ def get_item(item_uuid: str, db: Session = Depends(get_db)):
 
 
 @app.get("/items", response_model=list[schemas.Item])
-def get_items(db: Session = Depends(get_db)):
+def get_items(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
+    if (
+        datetime.datetime.fromtimestamp(oauth2_tokener.loads(token))
+        < datetime.datetime.now()
+    ):
+        raise HTTPException(
+            status_code=status.HTTP_401_UNAUTHORIZED,
+            detail="Invalid authentication credentials",
+            headers={"WWW-Authenticate": "Bearer"},
+        )
     return utils.get_stored_items(db)
 
 
@@ -92,3 +106,18 @@ def checkin_item_by_uuid(checkin: schemas.ItemCheckin, db: Session = Depends(get
     if storage is None:
         raise HTTPException(status_code=404, detail="Storage not found")
     return utils.receive_item(db, item, storage)
+
+
+@app.post("/token")
+def verify_supporter(form_data: OAuth2PasswordRequestForm = Depends()):
+    if form_data.password != settings.shared_secret:
+        raise HTTPException(status_code=400, detail="Incorrect username or password")
+    return {
+        "access_token": oauth2_tokener.dumps(
+            (
+                datetime.datetime.now()
+                + datetime.timedelta(minutes=settings.token_lifetime)
+            ).timestamp()
+        ),
+        "token_type": "bearer",
+    }
diff --git a/requirements.txt b/requirements.txt
index cba80ad..0b0bc39 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ python-multipart==0.0.6
 SQLAlchemy==2.0.9
 uvicorn[standard]==0.21.1
 slowapi==0.1.8
+itsdangerous==2.1.2
-- 
GitLab