mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-01-20 03:40:26 +00:00
- Add JWT authentication for cabinet users - Add Telegram WebApp authentication - Add subscription management endpoints - Add balance and transactions endpoints - Add referral system endpoints - Add tickets support for cabinet - Add webhooks and websocket for real-time updates - Add email verification service 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
107 lines
2.6 KiB
Python
107 lines
2.6 KiB
Python
"""JWT token handling for cabinet authentication."""
|
|
|
|
import jwt
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional, Dict, Any
|
|
|
|
from app.config import settings
|
|
|
|
JWT_ALGORITHM = "HS256"
|
|
|
|
|
|
def create_access_token(user_id: int, telegram_id: int) -> str:
|
|
"""
|
|
Create a short-lived access token.
|
|
|
|
Args:
|
|
user_id: Database user ID
|
|
telegram_id: Telegram user ID
|
|
|
|
Returns:
|
|
Encoded JWT access token
|
|
"""
|
|
expire_minutes = settings.get_cabinet_access_token_expire_minutes()
|
|
expires = datetime.utcnow() + timedelta(minutes=expire_minutes)
|
|
|
|
payload = {
|
|
"sub": str(user_id),
|
|
"telegram_id": telegram_id,
|
|
"type": "access",
|
|
"exp": expires,
|
|
"iat": datetime.utcnow(),
|
|
}
|
|
|
|
secret = settings.get_cabinet_jwt_secret()
|
|
return jwt.encode(payload, secret, algorithm=JWT_ALGORITHM)
|
|
|
|
|
|
def create_refresh_token(user_id: int) -> str:
|
|
"""
|
|
Create a long-lived refresh token.
|
|
|
|
Args:
|
|
user_id: Database user ID
|
|
|
|
Returns:
|
|
Encoded JWT refresh token
|
|
"""
|
|
expire_days = settings.get_cabinet_refresh_token_expire_days()
|
|
expires = datetime.utcnow() + timedelta(days=expire_days)
|
|
|
|
payload = {
|
|
"sub": str(user_id),
|
|
"type": "refresh",
|
|
"exp": expires,
|
|
"iat": datetime.utcnow(),
|
|
}
|
|
|
|
secret = settings.get_cabinet_jwt_secret()
|
|
return jwt.encode(payload, secret, algorithm=JWT_ALGORITHM)
|
|
|
|
|
|
def decode_token(token: str) -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Decode and validate a JWT token.
|
|
|
|
Args:
|
|
token: JWT token string
|
|
|
|
Returns:
|
|
Decoded payload dict or None if invalid/expired
|
|
"""
|
|
try:
|
|
secret = settings.get_cabinet_jwt_secret()
|
|
return jwt.decode(token, secret, algorithms=[JWT_ALGORITHM])
|
|
except jwt.ExpiredSignatureError:
|
|
return None
|
|
except jwt.InvalidTokenError:
|
|
return None
|
|
|
|
|
|
def get_token_payload(token: str, expected_type: str = "access") -> Optional[Dict[str, Any]]:
|
|
"""
|
|
Decode token and verify its type.
|
|
|
|
Args:
|
|
token: JWT token string
|
|
expected_type: Expected token type ("access" or "refresh")
|
|
|
|
Returns:
|
|
Decoded payload dict or None if invalid/expired/wrong type
|
|
"""
|
|
payload = decode_token(token)
|
|
|
|
if not payload:
|
|
return None
|
|
|
|
if payload.get("type") != expected_type:
|
|
return None
|
|
|
|
return payload
|
|
|
|
|
|
def get_refresh_token_expires_at() -> datetime:
|
|
"""Get the expiration datetime for a new refresh token."""
|
|
expire_days = settings.get_cabinet_refresh_token_expire_days()
|
|
return datetime.utcnow() + timedelta(days=expire_days)
|