Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed issue where file references in copied chat answers were relative paths instead of full browse URLs. [#847](https://github.com/sourcebot-dev/sourcebot/pull/847)
- [EE] Fixed issue where account driven permission syncing would fail when attempting to authenticate with a GitHub App user token. [#850](https://github.com/sourcebot-dev/sourcebot/pull/850)

### Added
- [EE] Added `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` env var that, when enabled, will automatically link SSO accounts with the same email address. [#849](https://github.com/sourcebot-dev/sourcebot/pull/849)

## [4.10.24] - 2026-02-03

### Fixed
Expand Down
1 change: 1 addition & 0 deletions docs/docs/configuration/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ The following environment variables allow you to configure your Sourcebot deploy
| `AUTH_EE_GCP_IAP_ENABLED` | `false` | <p>When enabled, allows Sourcebot to automatically register/login from a successful GCP IAP redirect</p> |
| `AUTH_EE_GCP_IAP_AUDIENCE` | - | <p>The GCP IAP audience to use when verifying JWT tokens. Must be set to enable GCP IAP JIT provisioning</p> |
| `EXPERIMENT_EE_PERMISSION_SYNC_ENABLED` | `false` | <p>Enables [permission syncing](/docs/features/permission-syncing).</p> |
| `AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING` | `false` | <p>When enabled, different SSO accounts with the same email address will automatically be linked.</p> |


### Review Agent Environment Variables
Expand Down
6 changes: 6 additions & 0 deletions packages/shared/src/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ export const env = createEnv({
AUTH_EMAIL_CODE_LOGIN_ENABLED: booleanSchema.default('false'),

// Enterprise Auth

AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING:
booleanSchema
.default('false')
.describe('When enabled, different SSO accounts with the same email address will automatically be linked.'),

AUTH_EE_GITHUB_CLIENT_ID: z.string().optional(),
AUTH_EE_GITHUB_CLIENT_SECRET: z.string().optional(),
AUTH_EE_GITHUB_BASE_URL: z.string().optional(),
Expand Down
25 changes: 16 additions & 9 deletions packages/web/src/ee/features/sso/sso.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const createGitHubProvider = (clientId: string, clientSecret: string, baseUrl?:
].join(' '),
},
},
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

Expand Down Expand Up @@ -168,13 +169,15 @@ const createGitLabProvider = (clientId: string, clientSecret: string, baseUrl?:
userinfo: {
url: `${url}/api/v4/user`,
},
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

const createGoogleProvider = (clientId: string, clientSecret: string): Provider => {
return Google({
clientId: clientId,
clientSecret: clientSecret,
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

Expand All @@ -183,6 +186,7 @@ const createOktaProvider = (clientId: string, clientSecret: string, issuer: stri
clientId: clientId,
clientSecret: clientSecret,
issuer: issuer,
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

Expand All @@ -191,6 +195,7 @@ const createKeycloakProvider = (clientId: string, clientSecret: string, issuer:
clientId: clientId,
clientSecret: clientSecret,
issuer: issuer,
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

Expand All @@ -199,6 +204,16 @@ const createMicrosoftEntraIDProvider = (clientId: string, clientSecret: string,
clientId: clientId,
clientSecret: clientSecret,
issuer: issuer,
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

export const createAuthentikProvider = (clientId: string, clientSecret: string, issuer: string): Provider => {
return Authentik({
clientId: clientId,
clientSecret: clientSecret,
issuer: issuer,
allowDangerousEmailAccountLinking: env.AUTH_EE_ALLOW_EMAIL_ACCOUNT_LINKING === 'true',
});
}

Expand All @@ -207,7 +222,7 @@ const createGCPIAPProvider = (audience: string): Provider => {
id: "gcp-iap",
name: "Google Cloud IAP",
credentials: {},
authorize: async (credentials, req) => {
authorize: async (_credentials, req) => {
try {
const iapAssertion = req.headers?.get("x-goog-iap-jwt-assertion");
if (!iapAssertion || typeof iapAssertion !== "string") {
Expand Down Expand Up @@ -277,11 +292,3 @@ const createGCPIAPProvider = (audience: string): Provider => {
},
});
}

export const createAuthentikProvider = (clientId: string, clientSecret: string, issuer: string): Provider => {
return Authentik({
clientId: clientId,
clientSecret: clientSecret,
issuer: issuer,
});
}