mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Validate jwts in the scanner
This commit is contained in:
parent
4a796d2058
commit
d4e5afd514
@ -13,3 +13,13 @@ THEMOVIEDB_API_ACCESS_TOKEN=""
|
||||
KYOO_URL="http://api:3567/api"
|
||||
KYOO_APIKEY=""
|
||||
|
||||
JWKS_URL="http://auth:4568/.well-known/jwks.json"
|
||||
JWT_ISSUER=$PUBLIC_URL
|
||||
|
||||
# The behavior of the below variables match what is documented here:
|
||||
# https://www.postgresql.org/docs/current/libpq-envars.html
|
||||
PGUSER=kyoo
|
||||
PGPASSWORD=password
|
||||
PGDATABASE=kyooDB
|
||||
PGHOST=postgres
|
||||
PGPORT=5432
|
||||
|
@ -5,3 +5,4 @@ aiohttp
|
||||
watchfiles
|
||||
langcodes
|
||||
asyncpg
|
||||
pyjwt[crypto]
|
||||
|
@ -1,12 +1,14 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Annotated
|
||||
|
||||
import asyncpg
|
||||
from fastapi import BackgroundTasks, FastAPI
|
||||
from fastapi import BackgroundTasks, FastAPI, Security
|
||||
|
||||
from .client import KyooClient
|
||||
from .fsscan import Scanner
|
||||
from .jwt import validate_bearer
|
||||
from .providers.composite import CompositeProvider
|
||||
from .providers.themoviedatabase import TheMovieDatabase
|
||||
from .requests import RequestCreator, RequestProcessor
|
||||
@ -71,8 +73,13 @@ app = FastAPI(
|
||||
@app.put(
|
||||
"/scan",
|
||||
status_code=204,
|
||||
description="Trigger a full scan of the filesystem, trying to find new videos & deleting old ones.",
|
||||
response_description="Scan started.",
|
||||
)
|
||||
async def trigger_scan(tasks: BackgroundTasks):
|
||||
async def trigger_scan(
|
||||
tasks: BackgroundTasks,
|
||||
_: Annotated[None, Security(validate_bearer, scopes=["scanner."])],
|
||||
):
|
||||
"""
|
||||
Trigger a full scan of the filesystem, trying to find new videos & deleting old ones.
|
||||
"""
|
||||
tasks.add_task(scanner.scan)
|
||||
|
41
scanner/scanner/jwt.py
Normal file
41
scanner/scanner/jwt.py
Normal file
@ -0,0 +1,41 @@
|
||||
import os
|
||||
from typing import Annotated
|
||||
|
||||
import jwt
|
||||
from fastapi import Depends, HTTPException
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer, SecurityScopes
|
||||
from jwt import PyJWKClient
|
||||
|
||||
jwks_client = PyJWKClient(
|
||||
os.environ.get("JWKS_URL", "http://auth:4568/.well-known/jwks.json")
|
||||
)
|
||||
|
||||
security = HTTPBearer(scheme_name="Bearer")
|
||||
|
||||
|
||||
def validate_bearer(
|
||||
token: Annotated[HTTPAuthorizationCredentials, Depends(security)],
|
||||
perms: SecurityScopes,
|
||||
):
|
||||
try:
|
||||
payload = jwt.decode(
|
||||
token.credentials,
|
||||
jwks_client.get_signing_key_from_jwt(token.credentials).key,
|
||||
issuer=os.environ.get("JWT_ISSUER"),
|
||||
)
|
||||
for scope in perms.scopes:
|
||||
if scope not in payload["permissions"]:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail=f"Missing permissions {', '.join(perms.scopes)}",
|
||||
headers={
|
||||
"WWW-Authenticate": f'Bearer permissions="{",".join(perms.scopes)}"'
|
||||
},
|
||||
)
|
||||
return payload
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="Could not validate credentials",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
) from e
|
@ -8,6 +8,7 @@
|
||||
watchfiles
|
||||
langcodes
|
||||
asyncpg
|
||||
pyjwt
|
||||
]);
|
||||
in
|
||||
pkgs.mkShell {
|
||||
|
Loading…
x
Reference in New Issue
Block a user