# Case Study: ephron.ren Login Redirect Failure (2026-05-05)

## Context
- Site: ephron.ren (multi-service: Home/Auth/Blog/Canvas/Prompt)
- Auth service at auth.ephron.ren, CSP includes `form-action 'self'`
- Login page at `/login` accepts `?redirect=<url>` query parameter

## Symptom
- User on www.ephron.ren clicks "未登录" → jumps to auth.ephron.ren/login?redirect=https%3A//www.ephron.ren/
- Enters credentials, clicks login
- Browser stays on login page, no redirect happens
- But: auth cookie IS set (server responded correctly)

## Root Cause
The Jinja2 template rendered the form action as:
```html
<form action="/api/login?redirect=https%3A//www.ephron.ren/">
```
Chrome's CSP `form-action 'self'` evaluator decoded `%3A` → `:` in the query string, saw `://`, interpreted it as cross-origin, and blocked the form submission.

## Playwright Evidence
```
[error] Sending form data to 'https://auth.ephron.ren/api/login?redirect=https%3A//www.ephron.ren/' 
violates the following Content Security Policy directive: "form-action 'self'". 
The request has been blocked.
```

Network trace showed `net::ERR_ABORTED` with no blocked reason.

## Fix Applied
1. Template: `<form action="/api/login">` + `<input type="hidden" name="redirect" value="{{ redirect }}">`
2. Backend: Changed `redirect: str | None = Query(default=None)` → `Form(default=None)`

## Key Learning
The Jinja2 `urlencode` filter preserves `/` as safe characters (`%3A//` not `%3A%2F%2F`), but even fully encoding (`%3A%2F%2F`) doesn't help — Chrome normalizes URLs before CSP evaluation.
