spb/groupe-ka Public
Groupe KA — site du holding + KA ID (compte unique & SSO des 7 plateformes). Next.js 16, SQLite, Google & Apple login.
TypeScript 85.5%
HTML 8.9%
CSS 5.5%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// Départ du flux Sign in with Apple : pose state + next en témoins,3// redirige vers l'écran de consentement Apple.4//5// ⚠️ Avec les scopes « name email », Apple impose response_mode=form_post :6// le retour arrive en POST cross-site, donc les témoins d'état doivent être7// SameSite=None; Secure (Lax ne serait pas renvoyé). Conséquence : le flux8// exige HTTPS — Apple refuse de toute façon les redirect_uri en http.9import { NextRequest, NextResponse } from "next/server";10import crypto from "crypto";11import { BASE_URL, safeNext } from "@/lib/auth";1213export async function GET(req: NextRequest) {14 const clientId = process.env.APPLE_CLIENT_ID;15 if (!clientId) {16 return NextResponse.redirect(17 new URL("/connexion?error=apple-non-configure", BASE_URL),18 );19 }20 const next = safeNext(req.nextUrl.searchParams.get("next"));21 const state = crypto.randomBytes(16).toString("hex");2223 const url = new URL("https://appleid.apple.com/auth/authorize");24 url.searchParams.set("client_id", clientId);25 url.searchParams.set("redirect_uri", `${BASE_URL}/api/auth/callback/apple`);26 url.searchParams.set("response_type", "code");27 url.searchParams.set("scope", "name email");28 url.searchParams.set("response_mode", "form_post");29 url.searchParams.set("state", state);3031 const res = NextResponse.redirect(url);32 const opts = {33 httpOnly: true,34 secure: true,35 sameSite: "none" as const,36 path: "/",37 maxAge: 600,38 };39 res.cookies.set("ka_apple_state", state, opts);40 res.cookies.set("ka_apple_next", next, opts);41 return res;42}43