refactor: switch OAuth2 to OpenID and update related configurations

This commit is contained in:
maxDorninger
2025-05-30 18:40:28 +02:00
parent 464e1eb8c7
commit 8dc8bf81aa
5 changed files with 28 additions and 49 deletions

View File

@@ -7,7 +7,7 @@ ENV IMAGE_DIRECTORY=/data/images
ENV TV_SHOW_DIRECTORY=/data/tv
ENV MOVIE_DIRECTORY=/data/movies
ENV TORRENT_DIRECTORY=/data/torrents
ENV OAUTH_ENABLED=FALSE
ENV OPENID_ENABLED=FALSE
WORKDIR /app
COPY media_manager ./media_manager

View File

@@ -14,11 +14,9 @@ class AuthConfig(BaseSettings):
return self._jwt_signing_key
class OAuth2Config(BaseSettings):
model_config = SettingsConfigDict(env_prefix="OAUTH_")
class OpenIdConfig(BaseSettings):
model_config = SettingsConfigDict(env_prefix="OPENID_")
client_id: str
client_secret: str
authorize_endpoint: str
access_token_endpoint: str
user_info_endpoint: str
name: str = "OAuth2"
configuration_endpoint: str
name: str = "OpenID"

View File

@@ -2,18 +2,18 @@ from fastapi import APIRouter, Depends
from fastapi import status
from sqlalchemy import select
from media_manager.auth.config import OAuth2Config
from media_manager.auth.config import OpenIdConfig
from media_manager.auth.db import User
from media_manager.auth.schemas import UserRead
from media_manager.auth.users import current_superuser
from media_manager.database import DbSessionDependency
from media_manager.auth.users import oauth_client
from media_manager.auth.users import openid_client
users_router = APIRouter()
auth_metadata_router = APIRouter()
oauth_enabled = oauth_client is not None
oauth_enabled = openid_client is not None
if oauth_enabled:
oauth_config = OAuth2Config()
oauth_config = OpenIdConfig()
@users_router.get(

View File

@@ -12,11 +12,11 @@ from fastapi_users.authentication import (
JWTStrategy,
)
from fastapi_users.db import SQLAlchemyUserDatabase
from httpx_oauth.oauth2 import OAuth2
from httpx_oauth.clients.openid import OpenID
from fastapi.responses import RedirectResponse, Response
from starlette import status
from media_manager.auth.config import AuthConfig, OAuth2Config
from media_manager.auth.config import AuthConfig, OpenIdConfig
from media_manager.auth.db import User, get_user_db
from media_manager.auth.schemas import UserUpdate
from media_manager.config import BasicConfig
@@ -25,39 +25,20 @@ config = AuthConfig()
SECRET = config.token_secret
LIFETIME = config.session_lifetime
class GenericOAuth2(OAuth2):
def __init__(self, user_info_endpoint: str, **kwargs):
super().__init__(**kwargs)
self.user_info_endpoint = user_info_endpoint
async def get_id_email(self, token: str):
userinfo_endpoint = self.user_info_endpoint
async with httpx.AsyncClient() as client:
resp = await client.get(
userinfo_endpoint, headers={"Authorization": f"Bearer {token}"}
)
resp.raise_for_status()
data = resp.json()
return data["sub"], data["email"]
if (
os.getenv("OAUTH_ENABLED") is not None
and os.getenv("OAUTH_ENABLED").upper() == "TRUE"
):
oauth2_config = OAuth2Config()
oauth_client = GenericOAuth2(
client_id=oauth2_config.client_id,
client_secret=oauth2_config.client_secret,
name=oauth2_config.name,
authorize_endpoint=oauth2_config.authorize_endpoint,
access_token_endpoint=oauth2_config.access_token_endpoint,
user_info_endpoint=oauth2_config.user_info_endpoint,
openid_config = OpenIdConfig()
openid_client = OpenID(
client_id=openid_config.client_id,
client_secret=openid_config.client_secret,
name=openid_config.name,
openid_configuration_endpoint=openid_config.configuration_endpoint,
base_scopes=["openid", "email", "profile"],
)
else:
oauth_client = None
openid_client = None
# TODO: implement on_xxx methods
@@ -111,7 +92,7 @@ class RedirectingCookieTransport(CookieTransport):
bearer_transport = BearerTransport(tokenUrl="auth/jwt/login")
cookie_transport = CookieTransport(cookie_max_age=LIFETIME)
oauth_cookie_transport = RedirectingCookieTransport(cookie_max_age=LIFETIME)
openid_cookie_transport = RedirectingCookieTransport(cookie_max_age=LIFETIME)
bearer_auth_backend = AuthenticationBackend(
name="jwt",
@@ -123,9 +104,9 @@ cookie_auth_backend = AuthenticationBackend(
transport=cookie_transport,
get_strategy=get_jwt_strategy,
)
oauth_cookie_auth_backend = AuthenticationBackend(
openid_cookie_auth_backend = AuthenticationBackend(
name="cookie",
transport=oauth_cookie_transport,
transport=openid_cookie_transport,
get_strategy=get_jwt_strategy,
)

View File

@@ -87,7 +87,7 @@ app.add_middleware(
import uvicorn
from fastapi.staticfiles import StaticFiles
from media_manager.auth.users import oauth_client
from media_manager.auth.users import openid_client
from media_manager.auth.users import SECRET as AUTH_USERS_SECRET
from media_manager.auth.router import users_router as custom_users_router
from media_manager.auth.router import auth_metadata_router
@@ -96,7 +96,7 @@ from media_manager.auth.users import (
bearer_auth_backend,
fastapi_users,
cookie_auth_backend,
oauth_cookie_auth_backend,
openid_cookie_auth_backend,
)
@@ -129,7 +129,7 @@ app.include_router(
# All users route router
app.include_router(custom_users_router, tags=["users"])
# OAuth Metadata Router
app.include_router(auth_metadata_router, tags=["oauth"])
app.include_router(auth_metadata_router, tags=["openid"])
# User Router
app.include_router(
fastapi_users.get_users_router(UserRead, UserUpdate),
@@ -137,16 +137,16 @@ app.include_router(
tags=["users"],
)
# OAuth2 Routers
if oauth_client is not None:
if openid_client is not None:
app.include_router(
fastapi_users.get_oauth_router(
oauth_client,
oauth_cookie_auth_backend,
openid_client,
openid_cookie_auth_backend,
AUTH_USERS_SECRET,
associate_by_email=True,
is_verified_by_default=True,
),
prefix=f"/auth/cookie/{oauth_client.name}",
prefix=f"/auth/cookie/{openid_client.name}",
tags=["oauth"],
)