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 89.7%
CSS 5.8%
HTML 4.4%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// « Se connecter avec KA » — endpoint SSO du hub.3// Une plateforme du groupe (ex. Lou·Ka) envoie l'utilisateur ici ;4// s'il a une session KA ID (créée par courriel ou via Google), on lui5// remet un jeton signé (HS256, secret partagé avec la plateforme) qui6// transporte son profil, puis on le renvoie vers la plateforme.7import { NextRequest, NextResponse } from "next/server";8import { SignJWT } from "jose";9import { getSessionUser, BASE_URL } from "@/lib/auth";10import { SSO_CLIENTS } from "@/lib/sso";11import { ensureKaId } from "@/lib/db";1213export async function GET(req: NextRequest) {14 const clientId = req.nextUrl.searchParams.get("client_id") ?? "";15 const redirectUri = req.nextUrl.searchParams.get("redirect_uri") ?? "";16 const state = req.nextUrl.searchParams.get("state") ?? "";1718 const client = SSO_CLIENTS[clientId];19 if (!client)20 return NextResponse.json(21 { error: `client_id inconnu : ${clientId}` },22 { status: 400 },23 );24 if (!client.redirectPrefixes.some((p) => redirectUri.startsWith(p)))25 return NextResponse.json(26 { error: "redirect_uri non autorisé pour ce client." },27 { status: 400 },28 );29 const secret = process.env[client.secretEnv];30 if (!secret)31 return NextResponse.json(32 { error: `Secret SSO non configuré pour ${clientId}.` },33 { status: 500 },34 );3536 const user = await getSessionUser();37 if (!user) {38 // Pas de session hub → page de connexion, puis retour ici.39 const back = req.nextUrl.pathname + "?" + req.nextUrl.searchParams.toString();40 return NextResponse.redirect(41 new URL(`/connexion?next=${encodeURIComponent(back)}&via=${clientId}`, BASE_URL),42 );43 }4445 const token = await new SignJWT({46 sub: String(user.id),47 ka_id: ensureKaId(user.id),48 email: user.email,49 name: user.name,50 picture: user.avatarUrl,51 provider: user.hasGoogle ? "google" : user.hasApple ? "apple" : "password",52 ka_role: user.role,53 })54 .setProtectedHeader({ alg: "HS256" })55 .setIssuer(BASE_URL)56 .setAudience(clientId)57 .setIssuedAt()58 .setExpirationTime("5m")59 .sign(new TextEncoder().encode(secret));6061 const dest = new URL(redirectUri);62 dest.searchParams.set("ka_token", token);63 if (state) dest.searchParams.set("state", state);64 return NextResponse.redirect(dest);65}66