| 1 | package movement |
| 2 | |
| 3 | import "strings" |
| 4 | |
| 5 | // signinOrigins are the hosts a sign-in may hand the browser off to. |
| 6 | // |
| 7 | // This exists because the app's own Content-Security-Policy was breaking its |
| 8 | // own admin sign-in. rastrillo ships `form-action 'self'`, and a browser |
| 9 | // applies form-action to the whole redirect chain a form submission starts — |
| 10 | // not just to the URL the form posts to. So the POST to /signin succeeded, |
| 11 | // answered 303 to keymail.dev's approval ceremony, and the browser refused |
| 12 | // to follow its own server's redirect. Nothing failed server-side; the only |
| 13 | // evidence was a console line. |
| 14 | // |
| 15 | // The host is not ours to guess in general: rastrillo/auth sends the browser |
| 16 | // to whatever provider the submitted address delegates to. It is knowable |
| 17 | // here only because the admin allowlist is a closed set we control. |
| 18 | // |
| 19 | // ADDING AN ADMIN ON ANOTHER PROVIDER MEANS ADDING ITS HOST HERE. Miss it |
| 20 | // and their sign-in fails the same silent way: a 303 the browser declines, |
| 21 | // no server error, nothing in the logs. |
| 22 | var signinOrigins = []string{"https://keymail.dev"} |
| 23 | |
| 24 | // CSP is the policy every response carries. It is rastrillo's default with |
| 25 | // the sign-in providers added to form-action, and nothing else widened: |
| 26 | // scripts, styles and images stay same-origin, framing stays refused. |
| 27 | func CSP() string { |
| 28 | return "default-src 'self'; " + |
| 29 | "style-src 'self' 'unsafe-inline'; " + |
| 30 | "img-src 'self' data:; " + |
| 31 | "frame-ancestors 'none'; " + |
| 32 | "base-uri 'self'; " + |
| 33 | "form-action 'self' " + strings.Join(signinOrigins, " ") |
| 34 | } |
| 35 | |