Files
media-player-server/media_server/auth.py
alexei.dolgolyov 83acf5f1ec Initial commit: Media Server for remote media control
FastAPI REST API server for controlling system-wide media playback
on Windows, Linux, macOS, and Android.

Features:
- Play/Pause/Stop/Next/Previous track controls
- Volume control and mute
- Seek within tracks
- Current track info (title, artist, album, artwork)
- WebSocket real-time status updates
- Script execution API
- Token-based authentication
- Cross-platform support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:41:00 +03:00

112 lines
3.2 KiB
Python

"""Authentication middleware and utilities."""
from typing import Optional
from fastapi import Depends, HTTPException, Query, Request, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from .config import settings
security = HTTPBearer(auto_error=False)
async def verify_token(
request: Request,
credentials: HTTPAuthorizationCredentials = Depends(security),
) -> str:
"""Verify the API token from the Authorization header.
Args:
request: The incoming request
credentials: The bearer token credentials
Returns:
The validated token
Raises:
HTTPException: If the token is missing or invalid
"""
if credentials is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Missing authentication token",
headers={"WWW-Authenticate": "Bearer"},
)
if credentials.credentials != settings.api_token:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication token",
headers={"WWW-Authenticate": "Bearer"},
)
return credentials.credentials
class TokenAuth:
"""Dependency class for token authentication."""
def __init__(self, auto_error: bool = True):
self.auto_error = auto_error
async def __call__(
self,
request: Request,
credentials: HTTPAuthorizationCredentials = Depends(security),
) -> str | None:
"""Verify the token and return it or raise an exception."""
if credentials is None:
if self.auto_error:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Missing authentication token",
headers={"WWW-Authenticate": "Bearer"},
)
return None
if credentials.credentials != settings.api_token:
if self.auto_error:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication token",
headers={"WWW-Authenticate": "Bearer"},
)
return None
return credentials.credentials
async def verify_token_or_query(
credentials: HTTPAuthorizationCredentials = Depends(security),
token: Optional[str] = Query(None, description="API token as query parameter"),
) -> str:
"""Verify the API token from header or query parameter.
Useful for endpoints that need to be accessed via URL (like images).
Args:
credentials: The bearer token credentials from header
token: Token from query parameter
Returns:
The validated token
Raises:
HTTPException: If the token is missing or invalid
"""
# Try header first
if credentials is not None:
if credentials.credentials == settings.api_token:
return credentials.credentials
# Try query parameter
if token is not None:
if token == settings.api_token:
return token
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Missing or invalid authentication token",
headers={"WWW-Authenticate": "Bearer"},
)