mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-23 15:18:04 +02:00
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
66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
import { randomBytes } from "node:crypto";
|
|
import { NextResponse } from "next/server";
|
|
import { getSession } from "@/lib/session";
|
|
import { can } from "@/lib/rbac";
|
|
import {
|
|
authorizeUrl,
|
|
getDecryptedAppSecret,
|
|
getSocialAccount,
|
|
publicBaseUrl,
|
|
SOCIAL_NETWORKS,
|
|
type SocialNetwork,
|
|
} from "@/lib/social-accounts";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const SETTINGS = "/backend/reseaux";
|
|
|
|
function back(request: Request, error: string) {
|
|
return NextResponse.redirect(new URL(`${SETTINGS}?error=${encodeURIComponent(error)}`, request.url));
|
|
}
|
|
|
|
export async function GET(
|
|
request: Request,
|
|
{ params }: { params: Promise<{ network: string }> }
|
|
) {
|
|
const session = await getSession();
|
|
if (!can(session?.user.role, "manageSettings")) {
|
|
return NextResponse.redirect(new URL("/backend", request.url));
|
|
}
|
|
|
|
const { network: raw } = await params;
|
|
const network = raw as SocialNetwork;
|
|
if (!SOCIAL_NETWORKS.includes(network)) {
|
|
return back(request, "Réseau inconnu.");
|
|
}
|
|
|
|
// Réglage enregistré, sinon l'adresse par laquelle l'administrateur est
|
|
// arrivé : c'est celle où le réseau nous renverra.
|
|
const base = await publicBaseUrl();
|
|
if (!base) {
|
|
return back(
|
|
request,
|
|
"Impossible de déterminer l'adresse publique du site : renseignez-la dans la section « URL publique du site »."
|
|
);
|
|
}
|
|
|
|
const account = await getSocialAccount(network);
|
|
const appSecret = await getDecryptedAppSecret(network);
|
|
if (!account?.appId || !appSecret) {
|
|
return back(request, "Enregistrez d'abord l'identifiant et le secret de l'application.");
|
|
}
|
|
|
|
// `state` en cookie httpOnly : vérifié au retour pour écarter toute requête
|
|
// de rappel forgée.
|
|
const state = randomBytes(24).toString("hex");
|
|
const response = NextResponse.redirect(await authorizeUrl(network, account.appId, state));
|
|
response.cookies.set(`plr_oauth_${network}`, state, {
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: new URL(base).protocol === "https:",
|
|
path: "/",
|
|
maxAge: 600,
|
|
});
|
|
return response;
|
|
}
|