feat:
--Added JWT Token session
This commit is contained in:
1 parent
df12fb5188
commit
85f2b1884b
2 files changed
+642
-9
No files matched your search
@@ -1,10 +1,28 @@
|
||||
from fastapi import FastAPI, HTTPException,WebSocket, WebSocketDisconnect
|
||||
from fastapi import FastAPI, HTTPException,WebSocket, WebSocketDisconnect, Header,Depends,Query,status
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import jwt
|
||||
from jwt import ExpiredSignatureError, InvalidTokenError
|
||||
from pydantic import BaseModel
|
||||
import psycopg2
|
||||
from psycopg2.extras import RealDictCursor
|
||||
import asyncio
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
origins = [
|
||||
"http://localhost:5173",
|
||||
"http://127.0.0.1:5173",
|
||||
]
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=origins,
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
class RegisterNodeRequest(BaseModel):
|
||||
node_name: str
|
||||
@@ -48,9 +66,97 @@ class LinkNodeRequest(BaseModel):
|
||||
# );
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JWT TOKEN CREATION
|
||||
# ============================================================
|
||||
SECRET_KEY = "my-super-secret-key-change-this"
|
||||
ALGORITHM = "HS256"
|
||||
|
||||
|
||||
@app.post("/get-token")
|
||||
def get_token():
|
||||
print("hio")
|
||||
payload = {
|
||||
"sub": "frontend",
|
||||
"exp": datetime.now(timezone.utc) + timedelta(hours=1)
|
||||
}
|
||||
|
||||
token = jwt.encode(
|
||||
payload,
|
||||
SECRET_KEY,
|
||||
algorithm=ALGORITHM
|
||||
)
|
||||
|
||||
return {
|
||||
"access_token": token,
|
||||
"token_type": "bearer"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JWT VERIFICATION
|
||||
# ============================================================
|
||||
def verify_token(
|
||||
authorization: str = Header(None),
|
||||
):
|
||||
|
||||
if not authorization:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Authorization header missing",
|
||||
headers={
|
||||
"WWW-Authenticate": "Bearer"
|
||||
},
|
||||
)
|
||||
|
||||
parts = authorization.split()
|
||||
|
||||
if len(parts) != 2:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid Authorization header",
|
||||
)
|
||||
|
||||
scheme = parts[0]
|
||||
token = parts[1]
|
||||
|
||||
if scheme.lower() != "bearer":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Authorization scheme must be Bearer",
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
payload = jwt.decode(
|
||||
token,
|
||||
SECRET_KEY,
|
||||
algorithms=[ALGORITHM],
|
||||
)
|
||||
|
||||
return payload
|
||||
|
||||
except ExpiredSignatureError:
|
||||
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Token expired",
|
||||
)
|
||||
|
||||
except InvalidTokenError:
|
||||
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid token",
|
||||
)
|
||||
|
||||
|
||||
|
||||
# Register Nodes
|
||||
@app.post("/register-node")
|
||||
def register_node(data: RegisterNodeRequest):
|
||||
def register_node(data: RegisterNodeRequest, token_data: dict = Depends(verify_token)):
|
||||
|
||||
conn = None
|
||||
cur = None
|
||||
@@ -126,7 +232,8 @@ def register_node(data: RegisterNodeRequest):
|
||||
"message": "Node registered",
|
||||
"node_id": node_id,
|
||||
"spock_version": spock[1],
|
||||
"nodes": nodes
|
||||
"nodes": nodes,
|
||||
"authenticated_as": token_data["sub"]
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
@@ -158,7 +265,7 @@ def register_node(data: RegisterNodeRequest):
|
||||
# "password": "postgres"
|
||||
# }
|
||||
@app.post("/link-nodes")
|
||||
def link_nodes(data: LinkNodeRequest):
|
||||
def link_nodes(data: LinkNodeRequest,token_data: dict = Depends(verify_token)):
|
||||
|
||||
conn = None
|
||||
cur = None
|
||||
@@ -215,7 +322,9 @@ def link_nodes(data: LinkNodeRequest):
|
||||
"subscription_id": subscription_id,
|
||||
"subscription_name": data.subscription_name,
|
||||
"subscriber": data.subscriber_host,
|
||||
"provider": data.provider_host
|
||||
"provider": data.provider_host,
|
||||
"authenticated_as": token_data["sub"],
|
||||
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
@@ -273,7 +382,18 @@ def get_spock_status():
|
||||
|
||||
|
||||
@app.websocket("/ws/spock-status")
|
||||
async def websocket_spock_status(websocket: WebSocket):
|
||||
async def websocket_spock_status(websocket: WebSocket, token: str = Query(...),):
|
||||
token_data = verify_websocket_token(token)
|
||||
|
||||
if token_data is None:
|
||||
|
||||
await websocket.close(
|
||||
code=1008,
|
||||
reason="Invalid or expired JWT",
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
await websocket.accept()
|
||||
|
||||
try:
|
||||
@@ -299,13 +419,15 @@ async def websocket_spock_status(websocket: WebSocket):
|
||||
await asyncio.sleep(2)
|
||||
|
||||
except WebSocketDisconnect:
|
||||
print("WebSocket client disconnected")
|
||||
print("WebSocket client disconnected" f"{token_data.get('sub')}")
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@app.get("/spock/subscriptions")
|
||||
def get_spock_subscription_status():
|
||||
def get_spock_subscription_status(token_data: dict = Depends(verify_token),):
|
||||
conn = None
|
||||
cursor = None
|
||||
try:
|
||||
conn = psycopg2.connect(**DB_CONFIG)
|
||||
|
||||
@@ -324,7 +446,9 @@ def get_spock_subscription_status():
|
||||
return {
|
||||
"success": True,
|
||||
"count": len(rows),
|
||||
"subscriptions": rows
|
||||
"subscriptions": rows,
|
||||
"authenticated_as": token_data["sub"],
|
||||
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
@@ -334,3 +458,5 @@ def get_spock_subscription_status():
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user