mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-30 13:50:42 -05:00
feat: Add OIDC_CLIENT_SECRET and other changes for v2 (#4254)
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,7 @@ from mealie.core.settings.static import APP_VERSION
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.db.models.users.users import User
|
||||
from mealie.repos.all_repositories import get_repositories
|
||||
from mealie.schema.admin.about import AppInfo, AppStartupInfo, AppTheme, OIDCInfo
|
||||
from mealie.schema.admin.about import AppInfo, AppStartupInfo, AppTheme
|
||||
|
||||
router = APIRouter(prefix="/about")
|
||||
|
||||
@@ -69,16 +69,3 @@ def get_app_theme(resp: Response):
|
||||
|
||||
resp.headers["Cache-Control"] = "public, max-age=604800"
|
||||
return AppTheme(**settings.theme.model_dump())
|
||||
|
||||
|
||||
@router.get("/oidc", response_model=OIDCInfo)
|
||||
def get_oidc_info(resp: Response):
|
||||
"""Get's the current OIDC configuration needed for the frontend"""
|
||||
settings = get_app_settings()
|
||||
|
||||
resp.headers["Cache-Control"] = "public, max-age=604800"
|
||||
return OIDCInfo(
|
||||
configuration_url=settings.OIDC_CONFIGURATION_URL,
|
||||
client_id=settings.OIDC_CLIENT_ID,
|
||||
groups_claim=settings.OIDC_GROUPS_CLAIM if settings.OIDC_USER_GROUP or settings.OIDC_ADMIN_GROUP else None,
|
||||
)
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from authlib.integrations.starlette_client import OAuth
|
||||
from fastapi import APIRouter, Depends, Request, Response, status
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi.responses import RedirectResponse
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy.orm.session import Session
|
||||
from starlette.datastructures import URLPath
|
||||
|
||||
from mealie.core import root_logger, security
|
||||
from mealie.core.config import get_app_settings
|
||||
from mealie.core.dependencies import get_current_user
|
||||
from mealie.core.exceptions import UserLockedOut
|
||||
from mealie.core.security.providers.openid_provider import OpenIDProvider
|
||||
from mealie.core.security.security import get_auth_provider
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes._base.routers import UserAPIRouter
|
||||
@@ -20,6 +25,20 @@ logger = root_logger.get_logger("auth")
|
||||
|
||||
remember_me_duration = timedelta(days=14)
|
||||
|
||||
settings = get_app_settings()
|
||||
if settings.OIDC_READY:
|
||||
oauth = OAuth()
|
||||
groups_claim = settings.OIDC_GROUPS_CLAIM if settings.OIDC_REQUIRES_GROUP_CLAIM else ""
|
||||
scope = f"openid email profile {groups_claim}"
|
||||
oauth.register(
|
||||
"oidc",
|
||||
client_id=settings.OIDC_CLIENT_ID,
|
||||
client_secret=settings.OIDC_CLIENT_SECRET,
|
||||
server_metadata_url=settings.OIDC_CONFIGURATION_URL,
|
||||
client_kwargs={"scope": scope.rstrip()},
|
||||
code_challenge_method="S256",
|
||||
)
|
||||
|
||||
|
||||
class MealieAuthToken(BaseModel):
|
||||
access_token: str
|
||||
@@ -31,7 +50,7 @@ class MealieAuthToken(BaseModel):
|
||||
|
||||
|
||||
@public_router.post("/token")
|
||||
async def get_token(
|
||||
def get_token(
|
||||
request: Request,
|
||||
response: Response,
|
||||
data: CredentialsRequestForm = Depends(),
|
||||
@@ -46,8 +65,8 @@ async def get_token(
|
||||
ip = request.client.host if request.client else "unknown"
|
||||
|
||||
try:
|
||||
auth_provider = get_auth_provider(session, request, data)
|
||||
auth = await auth_provider.authenticate()
|
||||
auth_provider = get_auth_provider(session, data)
|
||||
auth = auth_provider.authenticate()
|
||||
except UserLockedOut as e:
|
||||
logger.error(f"User is locked out from {ip}")
|
||||
raise HTTPException(status_code=status.HTTP_423_LOCKED, detail="User is locked out") from e
|
||||
@@ -61,7 +80,61 @@ async def get_token(
|
||||
|
||||
expires_in = duration.total_seconds() if duration else None
|
||||
response.set_cookie(
|
||||
key="mealie.access_token", value=access_token, httponly=True, max_age=expires_in, expires=expires_in
|
||||
key="mealie.access_token",
|
||||
value=access_token,
|
||||
httponly=True,
|
||||
max_age=expires_in,
|
||||
secure=settings.PRODUCTION,
|
||||
)
|
||||
|
||||
return MealieAuthToken.respond(access_token)
|
||||
|
||||
|
||||
@public_router.get("/oauth")
|
||||
async def oauth_login(request: Request):
|
||||
if not oauth:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Could not initialize OAuth client",
|
||||
)
|
||||
client = oauth.create_client("oidc")
|
||||
redirect_url = None
|
||||
if not settings.PRODUCTION:
|
||||
# in development, we want to redirect to the frontend
|
||||
redirect_url = "http://localhost:3000/login"
|
||||
else:
|
||||
redirect_url = URLPath("/login").make_absolute_url(request.base_url)
|
||||
|
||||
response: RedirectResponse = await client.authorize_redirect(request, redirect_url)
|
||||
return response
|
||||
|
||||
|
||||
@public_router.get("/oauth/callback")
|
||||
async def oauth_callback(request: Request, response: Response, session: Session = Depends(generate_session)):
|
||||
if not oauth:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Could not initialize OAuth client",
|
||||
)
|
||||
client = oauth.create_client("oidc")
|
||||
token = await client.authorize_access_token(request)
|
||||
auth_provider = OpenIDProvider(session, token["userinfo"])
|
||||
auth = auth_provider.authenticate()
|
||||
|
||||
if not auth:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
)
|
||||
access_token, duration = auth
|
||||
|
||||
expires_in = duration.total_seconds() if duration else None
|
||||
|
||||
response.set_cookie(
|
||||
key="mealie.access_token",
|
||||
value=access_token,
|
||||
httponly=True,
|
||||
max_age=expires_in,
|
||||
secure=settings.PRODUCTION,
|
||||
)
|
||||
|
||||
return MealieAuthToken.respond(access_token)
|
||||
|
||||
Reference in New Issue
Block a user