mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-11-03 18:53:17 -05:00 
			
		
		
		
	fix: Enabled Using Mealie In iframe If Served Over HTTPS (#6128)
This commit is contained in:
		@@ -1,3 +1,5 @@
 | 
			
		||||
from typing import Literal
 | 
			
		||||
 | 
			
		||||
from authlib.integrations.starlette_client import OAuth
 | 
			
		||||
from fastapi import APIRouter, Depends, Request, Response, status
 | 
			
		||||
from fastapi.exceptions import HTTPException
 | 
			
		||||
@@ -52,7 +54,9 @@ class MealieAuthToken(BaseModel):
 | 
			
		||||
    token_type: str = "bearer"
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def set_cookie(cls, response: Response, token: str, expires_in: int | float | None = None):
 | 
			
		||||
    def set_cookie(
 | 
			
		||||
        cls, response: Response, token: str, *, expires_in: int | float | None = None, samesite: str | None = None
 | 
			
		||||
    ):
 | 
			
		||||
        expires_in = int(expires_in) if expires_in else None
 | 
			
		||||
 | 
			
		||||
        # httponly=False to allow JS access for frontend
 | 
			
		||||
@@ -62,6 +66,7 @@ class MealieAuthToken(BaseModel):
 | 
			
		||||
            httponly=False,
 | 
			
		||||
            max_age=expires_in,
 | 
			
		||||
            secure=settings.PRODUCTION,
 | 
			
		||||
            samesite=samesite,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
@@ -69,6 +74,22 @@ class MealieAuthToken(BaseModel):
 | 
			
		||||
        return cls(access_token=token, token_type=token_type).model_dump()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_samesite(request: Request) -> Literal["lax", "none"]:
 | 
			
		||||
    """
 | 
			
		||||
    Determine the appropriate samesite attribute for cookies.
 | 
			
		||||
 | 
			
		||||
    `samesite="none"` is required for iframe support (i.e. embedding Mealie in another site)
 | 
			
		||||
    but only works over HTTPS. If `samesite="none"` is set over HTTP, most browsers will reject the cookie.
 | 
			
		||||
 | 
			
		||||
    `samesite="lax"` is the default, which works regardless of HTTP or HTTPS,
 | 
			
		||||
    but does not support hosting in iframes.
 | 
			
		||||
    """
 | 
			
		||||
    if request.url.scheme == "https" and settings.PRODUCTION:
 | 
			
		||||
        return "none"
 | 
			
		||||
    else:
 | 
			
		||||
        return "lax"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@public_router.post("/token")
 | 
			
		||||
def get_token(
 | 
			
		||||
    request: Request,
 | 
			
		||||
@@ -100,7 +121,12 @@ def get_token(
 | 
			
		||||
    access_token, duration = auth
 | 
			
		||||
    expires_in = duration.total_seconds() if duration else None
 | 
			
		||||
 | 
			
		||||
    MealieAuthToken.set_cookie(response, access_token, expires_in)
 | 
			
		||||
    MealieAuthToken.set_cookie(
 | 
			
		||||
        response,
 | 
			
		||||
        access_token,
 | 
			
		||||
        expires_in=expires_in,
 | 
			
		||||
        samesite=get_samesite(request),
 | 
			
		||||
    )
 | 
			
		||||
    return MealieAuthToken.respond(access_token)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -153,7 +179,12 @@ async def oauth_callback(request: Request, response: Response, session: Session
 | 
			
		||||
    access_token, duration = auth
 | 
			
		||||
    expires_in = duration.total_seconds() if duration else None
 | 
			
		||||
 | 
			
		||||
    MealieAuthToken.set_cookie(response, access_token, expires_in)
 | 
			
		||||
    MealieAuthToken.set_cookie(
 | 
			
		||||
        response,
 | 
			
		||||
        access_token,
 | 
			
		||||
        expires_in=expires_in,
 | 
			
		||||
        samesite=get_samesite(request),
 | 
			
		||||
    )
 | 
			
		||||
    return MealieAuthToken.respond(access_token)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user