Support return_to redirect with token for iOS Safari

Login page accepts return_to URL. After login, redirects to
return_to with auth_token in URL so target site can set its
own first-party cookie (works around iOS Safari ITP).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-09 17:06:27 +00:00
parent f2397e0a73
commit 990ac44108

View File

@@ -358,8 +358,8 @@ def format_date(value, length: int = 10) -> str:
# ============ Auth UI Endpoints ============
@app.get("/login", response_class=HTMLResponse)
async def ui_login_page(request: Request):
"""Login page."""
async def ui_login_page(request: Request, return_to: str = None):
"""Login page. Accepts optional return_to URL for redirect after login."""
username = get_user_from_cookie(request)
if username:
return HTMLResponse(base_html("Already Logged In", f'''
@@ -369,10 +369,14 @@ async def ui_login_page(request: Request):
<p><a href="/" class="text-blue-400 hover:text-blue-300">Go to home page</a></p>
''', username))
content = '''
# Hidden field for return_to URL
return_to_field = f'<input type="hidden" name="return_to" value="{return_to}">' if return_to else ''
content = f'''
<h2 class="text-xl font-semibold text-white mb-6">Login</h2>
<div id="login-result"></div>
<form hx-post="/login" hx-target="#login-result" hx-swap="innerHTML" class="space-y-4 max-w-md">
{return_to_field}
<div>
<label for="username" class="block text-sm font-medium text-gray-300 mb-2">Username</label>
<input type="text" id="username" name="username" required
@@ -398,6 +402,7 @@ async def ui_login_submit(request: Request):
form = await request.form()
username = form.get("username", "").strip()
password = form.get("password", "")
return_to = form.get("return_to", "").strip()
if not username or not password:
return HTMLResponse('<div class="bg-red-900/50 border border-red-700 text-red-300 px-4 py-3 rounded-lg mb-4">Username and password are required</div>')
@@ -408,10 +413,22 @@ async def ui_login_submit(request: Request):
token = create_access_token(user.username, l2_server=f"https://{DOMAIN}")
response = HTMLResponse(f'''
<div class="bg-green-900/50 border border-green-700 text-green-300 px-4 py-3 rounded-lg mb-4">Login successful! Redirecting...</div>
<script>window.location.href = "/";</script>
''')
# If return_to is specified, redirect there with token for the other site to set its own cookie
if return_to and return_to.startswith("http"):
# Append token to return_to URL for the target site to set its own cookie
separator = "&" if "?" in return_to else "?"
redirect_url = f"{return_to}{separator}auth_token={token.access_token}"
response = HTMLResponse(f'''
<div class="bg-green-900/50 border border-green-700 text-green-300 px-4 py-3 rounded-lg mb-4">Login successful! Redirecting...</div>
<script>window.location.href = "{redirect_url}";</script>
''')
else:
response = HTMLResponse(f'''
<div class="bg-green-900/50 border border-green-700 text-green-300 px-4 py-3 rounded-lg mb-4">Login successful! Redirecting...</div>
<script>window.location.href = "/";</script>
''')
# Always set cookie on L2 as well
response.set_cookie(
key="auth_token",
value=token.access_token,