Connexion réseaux : adresse de retour déduite de la requête, CSP sans upgrade en HTTP

Cliquer sur « Connecter » sans avoir enregistré l'URL publique du site
renvoyait une erreur, et la redirection retombait sur https://0.0.0.0 :
la directive upgrade-insecure-requests était posée même sur une page
servie en HTTP, le navigateur basculait donc la navigation vers un
https:// inexistant.

- `publicBaseUrl()` : réglage `site_public_url`, variables d'environnement,
  puis origine de la requête (X-Forwarded-Host / X-Forwarded-Proto). L'adresse
  de retour OAuth et le lien des publications l'utilisent ; `seo-server`
  s'appuie dessus au lieu de dupliquer la déduction.
- `src/lib/site-url.ts` : déduction pure et testée de l'origine, HTTP par
  défaut pour localhost et les IP nues, HTTPS pour un nom de domaine.
- Middleware : `upgrade-insecure-requests` uniquement quand la page est servie
  en HTTPS.
- Page Réseaux : l'adresse détectée est annoncée comme valeur par défaut, avec
  le rappel que Facebook et LinkedIn exigent du HTTPS sur un domaine.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QXNXRC4j5VLfKvpyyisrnb
This commit is contained in:
Claude committed 2026-09-06 10:11:06 +00:00
1 parent 23d1d14a49
commit 17511a73c3
10 files changed
+157 -41

No files matched your search

+11 -4
View File
@@ -18,7 +18,7 @@ const { auth } = NextAuth(authConfig);
* `style` et sur la feuille Google Fonts. C'est un compromis assumé — une
* injection de style est sans commune mesure avec une injection de script.
*/
function contentSecurityPolicy(nonce: string, isDev: boolean): string {
function contentSecurityPolicy(nonce: string, isDev: boolean, isHttps: boolean): string {
return [
"default-src 'self'",
"base-uri 'self'",
@@ -35,14 +35,21 @@ function contentSecurityPolicy(nonce: string, isDev: boolean): string {
"connect-src 'self'",
// Carte « Nous situer » de la fiche adhérent.
"frame-src https://www.google.com https://maps.google.com",
"upgrade-insecure-requests",
].join("; ");
// Uniquement quand la page est servie en HTTPS : sur une page HTTP (test
// par IP avant la pose du DNS, accès direct au port), le navigateur
// basculerait toutes les navigations vers un https:// inexistant.
isHttps ? "upgrade-insecure-requests" : "",
]
.filter(Boolean)
.join("; ");
}
export default auth((request: NextRequest) => {
// `btoa` et non `Buffer` : le middleware tourne sur le runtime Edge.
const nonce = btoa(crypto.randomUUID());
const csp = contentSecurityPolicy(nonce, process.env.NODE_ENV !== "production");
const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim();
const isHttps = forwardedProto ? forwardedProto === "https" : request.nextUrl.protocol === "https:";
const csp = contentSecurityPolicy(nonce, process.env.NODE_ENV !== "production", isHttps);
// L'en-tête est posé sur la REQUÊTE : Next y lit le nonce pour l'appliquer à
// ses balises <script>. Il est ensuite renvoyé sur la réponse au navigateur.