From ffbb516c310c48316e75b6237bb206bfe77c783e Mon Sep 17 00:00:00 2001 From: Narciso Date: Thu, 17 Sep 2026 18:43:12 -0400 Subject: [PATCH] fix(sso): mark self-hosted owner as verified when SSO is configured --- apps/dokploy/server/api/routers/proprietary/sso.ts | 3 +++ apps/dokploy/server/api/routers/settings.ts | 4 ++++ packages/server/src/services/proprietary/sso.ts | 14 +++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/server/api/routers/proprietary/sso.ts b/apps/dokploy/server/api/routers/proprietary/sso.ts index 0581ae4db..80b3e9135 100644 --- a/apps/dokploy/server/api/routers/proprietary/sso.ts +++ b/apps/dokploy/server/api/routers/proprietary/sso.ts @@ -5,6 +5,7 @@ import { member, ssoProvider, user } from "@dokploy/server/db/schema"; import { ssoProviderBodySchema } from "@dokploy/server/db/schema/sso"; import { getOrganizationOwnerId, + markOrganizationOwnerVerified, requestToHeaders, } from "@dokploy/server/index"; import { auth } from "@dokploy/server/lib/auth"; @@ -212,6 +213,7 @@ export const ssoRouter = createTRPCRouter({ body: updateBody, headers: requestToHeaders(ctx.req), }); + await markOrganizationOwnerVerified(ctx.session.activeOrganizationId); return { success: true }; }), deleteProvider: enterpriseProcedure @@ -292,6 +294,7 @@ export const ssoRouter = createTRPCRouter({ }, headers: requestToHeaders(ctx.req), }); + await markOrganizationOwnerVerified(organizationId); return { success: true }; }), addTrustedOrigin: enterpriseProcedure diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index db2951ae4..ff6496c8e 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -19,6 +19,7 @@ import { getUpdateData, getWebServerSettings, IS_CLOUD, + markOrganizationOwnerVerified, parseRawConfig, paths, prepareEnvironmentVariables, @@ -467,6 +468,9 @@ export const settingsRouter = createTRPCRouter({ await updateWebServerSettings({ enforceSSO: input.enforceSSO, }); + if (input.enforceSSO) { + await markOrganizationOwnerVerified(ctx.session.activeOrganizationId); + } await audit(ctx, { action: "update", diff --git a/packages/server/src/services/proprietary/sso.ts b/packages/server/src/services/proprietary/sso.ts index 352a042e0..ed0452cef 100644 --- a/packages/server/src/services/proprietary/sso.ts +++ b/packages/server/src/services/proprietary/sso.ts @@ -1,5 +1,6 @@ +import { IS_CLOUD } from "@dokploy/server/constants"; import { db } from "@dokploy/server/db"; -import { organization } from "@dokploy/server/db/schema"; +import { organization, user } from "@dokploy/server/db/schema"; import { eq } from "drizzle-orm"; export const getSSOProviders = async () => { @@ -44,3 +45,14 @@ export const getOrganizationOwnerId = async (organizationId: string) => { if (!org) return null; return org.ownerId; }; + +// better-auth won't link SSO to an unverified user; self-hosted owners never verify +export const markOrganizationOwnerVerified = async (organizationId: string) => { + if (IS_CLOUD) return; + const ownerId = await getOrganizationOwnerId(organizationId); + if (!ownerId) return; + await db + .update(user) + .set({ emailVerified: true }) + .where(eq(user.id, ownerId)); +};