feat(stream): require auth on GET /stream/{id} via token query param
The audio stream endpoint was unauthenticated. Add a get_streaming_user dependency that accepts the access token either as a ?token= query param (the browser <audio> element can't send an Authorization header) or a bearer header for native clients. Update streaming tests accordingly and add a test asserting unauthenticated requests are rejected with 401. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -167,3 +167,23 @@ async def get_current_superuser(user: CurrentUser) -> User:
|
||||
|
||||
|
||||
SuperUser = Annotated[User, Depends(get_current_superuser)]
|
||||
|
||||
|
||||
async def get_streaming_user(
|
||||
auth: AuthServiceDep,
|
||||
credentials: BearerDep,
|
||||
token: str | None = None,
|
||||
) -> User:
|
||||
"""Authenticate a stream request.
|
||||
|
||||
The browser ``<audio>`` element cannot send an ``Authorization`` header, so
|
||||
the access token is accepted as a ``?token=`` query param; native clients may
|
||||
still use a bearer header. Either way it's the same access token.
|
||||
"""
|
||||
raw = token or (credentials.credentials if credentials else None)
|
||||
if not raw:
|
||||
raise AuthenticationError("Missing access token.")
|
||||
return await auth.authenticate_access(raw)
|
||||
|
||||
|
||||
StreamUser = Annotated[User, Depends(get_streaming_user)]
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing import Annotated
|
||||
from fastapi import APIRouter, Header
|
||||
from fastapi.responses import StreamingResponse
|
||||
|
||||
from app.api.deps import StreamingServiceDep
|
||||
from app.api.deps import StreamingServiceDep, StreamUser
|
||||
|
||||
router = APIRouter(prefix="/stream", tags=["streaming"])
|
||||
|
||||
@@ -15,6 +15,7 @@ router = APIRouter(prefix="/stream", tags=["streaming"])
|
||||
async def stream_track(
|
||||
track_id: uuid.UUID,
|
||||
service: StreamingServiceDep,
|
||||
_user: StreamUser,
|
||||
range_header: Annotated[str | None, Header(alias="Range")] = None,
|
||||
) -> StreamingResponse:
|
||||
result = await service.open_stream(track_id, range_header)
|
||||
|
||||
Reference in New Issue
Block a user