/home/techb158/balavpn.abdallabala.com/src/services
NameSizeModeActions
audit-service.js6590644editdlrm
auth-service.js47790644editdlrm
dashboard-service.js11090644editdlrm
gate-service.js45120644editdlrm
integration-service.js165950644editdlrm
project-service.js59730644editdlrm
reporting-service.js86440644editdlrm
risk-service.js125050644editdlrm
sso-service.js31670644editdlrm
Edit: /home/techb158/balavpn.abdallabala.com/src/services/sso-service.js (3167B)
const { prisma } = require("../lib/prisma"); const { createSession } = require("./auth-service"); const { getOidcConfig, discoverProvider, generateNonce, decodeJwtPayload } = require("../lib/oidc"); async function exchangeCode(code, redirectUrl, clientId, clientSecret, tokenEndpoint) { const body = new URLSearchParams({ grant_type: "authorization_code", code, redirect_uri: redirectUrl, client_id: clientId, client_secret: clientSecret, }); const res = await fetch(tokenEndpoint, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: body.toString(), }); if (!res.ok) { const text = await res.text(); throw new Error(`Token exchange failed (${res.status}): ${text}`); } return res.json(); } async function handleSsoCallback(code) { const config = getOidcConfig(); if (!config) throw Object.assign(new Error("SSO not configured"), { status: 501 }); const disco = await discoverProvider(config.issuer); const tokens = await exchangeCode(code, config.redirectUrl, config.clientId, config.clientSecret, disco.token_endpoint); const idToken = tokens.id_token; if (!idToken) throw Object.assign(new Error("No id_token returned from provider"), { status: 400 }); const claims = decodeJwtPayload(idToken); const email = claims.email; if (!email) throw Object.assign(new Error("Email not provided by SSO provider"), { status: 400 }); const displayName = claims.name || claims.preferred_username || email.split("@")[0]; let user = await prisma.user.findUnique({ where: { email } }); if (!user) { user = await prisma.user.create({ data: { email, displayName, emailVerifiedAt: new Date() }, }); const slug = displayName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") + "-" + Date.now().toString(36); const role = await prisma.role.upsert({ where: { code: "owner" }, update: {}, create: { code: "owner", name: "Owner", permissions: ["*"], system: true }, }); const org = await prisma.organization.create({ data: { name: `${displayName}'s Organization`, slug, status: "TRIAL", planCode: "pilot", manualBilling: true }, }); await prisma.membership.create({ data: { organizationId: org.id, userId: user.id, roleId: role.id, status: "ACTIVE" }, }); await prisma.subscription.create({ data: { organizationId: org.id, source: "MANUAL", status: "TRIALING", planCode: "pilot", userLimit: 5, projectLimit: 3 }, }).catch(() => {}); const workspace = await prisma.workspace.create({ data: { organizationId: org.id, name: "Default Workspace", slug: "default-workspace", type: "B2B_TEAM", status: "TRIAL" }, }); await prisma.project.create({ data: { workspaceId: workspace.id, name: "My Project", projectType: "AI-Enabler", status: "Active", riskAppetite: 50 }, }); } else { await prisma.user.update({ where: { id: user.id }, data: { lastLoginAt: new Date(), displayName }, }); } const session = await createSession(user.id); return { user, session }; } module.exports = { handleSsoCallback };