Files
dokploy/packages/server/src/lib/auth-cli.ts
T
Mauricio Siu 67f6890fc8 fix(sso): trust admin-configured SSO providers for account linking
better-auth's account-linking guard requires either the IdP asserting
email_verified or the sso_provider row being domainVerified before it
will link an SSO login to an existing local user with the same email.
Entra ID never asserts email_verified (neither via its OIDC userinfo
endpoint nor via SAML attributes), and Dokploy never persisted
domainVerified at all, so linking was permanently impossible for any
Entra-backed provider (OIDC or SAML) regardless of the local user's
own emailVerified state.

Add the domainVerified column, defaulting to true — Dokploy already
scopes providers to an admin-configured domain and gates registration
behind enterprise/admin permissions, so that domain match (still
enforced by better-auth's validateEmailDomain check) is trust enough.

Fixes #5099
2026-09-08 03:17:02 -06:00

55 lines
1.6 KiB
TypeScript

import { apiKey } from "@better-auth/api-key";
import { passkey } from "@better-auth/passkey";
import { scim } from "@better-auth/scim";
import { sso } from "@better-auth/sso";
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { admin, organization, twoFactor } from "better-auth/plugins";
import { db } from "../db";
import * as schema from "../db/schema";
import { ac, adminRole, memberRole, ownerRole } from "./access-control";
// CLI-only config for `@better-auth/cli generate` — must mirror the plugin set
// in auth.ts. Never import this from runtime code.
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
schema,
}),
user: {
modelName: "user",
fields: {
name: "firstName",
},
additionalFields: {
role: { type: "string", input: false },
ownerId: { type: "string", input: false },
allowImpersonation: { type: "boolean", defaultValue: false },
lastName: { type: "string", required: false, defaultValue: "" },
enableEnterpriseFeatures: { type: "boolean", required: false },
isValidEnterpriseLicense: { type: "boolean", required: false },
},
},
plugins: [
apiKey({ enableMetadata: true, references: "user" }),
sso({
trustEmailVerified: true,
domainVerification: {
enabled: true,
},
}),
twoFactor(),
passkey(),
organization({
ac,
roles: { owner: ownerRole, admin: adminRole, member: memberRole },
dynamicAccessControl: {
enabled: true,
maximumRolesPerOrganization: 10,
},
}),
scim(),
admin(),
],
});