7827cda224
- logger.py: note why log path uses abspath(__file__) instead of a relative path - token.py: note why [7:] slice is safe (startswith already verified) - ipcalc.py: explain /32 single-host and /31 RFC-3021 point-to-point special cases; explain why (~netmask) must be masked with 0xFFFFFFFF (Python ~int returns a negative arbitrary-precision value, not a 32-bit unsigned integer) - notes.py: document the module-level _table_ready flag lifetime; explain why tzinfo is stripped before passing datetime to mysql-connector - admin.py: document the module-level _tables_initialized flag lifetime Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
31 lines
1002 B
Python
31 lines
1002 B
Python
import os
|
||
from flask import request
|
||
from jwt import decode, ExpiredSignatureError, InvalidTokenError
|
||
from util.logger import logger
|
||
|
||
# SECRET_KEY must be provided via environment for production safety
|
||
SECRET_KEY = os.environ.get("SECRET_KEY")
|
||
if not SECRET_KEY:
|
||
logger.error("SECRET_KEY environment variable is not set – authentication disabled until configured.")
|
||
|
||
|
||
def verify_token():
|
||
if not SECRET_KEY:
|
||
return None
|
||
|
||
auth_header = request.headers.get("Authorization", "")
|
||
if not auth_header.startswith("Bearer "):
|
||
logger.warning("🔐 Invalid Bearer header")
|
||
return None
|
||
|
||
token = auth_header[7:] # len("Bearer ") == 7; safe because startswith is verified above
|
||
try:
|
||
decoded = decode(token, SECRET_KEY, algorithms=["HS256"])
|
||
return decoded
|
||
except ExpiredSignatureError:
|
||
logger.warning("🔐 Token expired")
|
||
return None
|
||
except InvalidTokenError:
|
||
logger.warning("🔐 Invalid token")
|
||
return None
|