Skip to content

Commit e668c3f

Browse files
fix(web): Support multiple IDPs of the same type (#1177)
1 parent d2843aa commit e668c3f

31 files changed

Lines changed: 9144 additions & 4090 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2424
- Upgraded `hono` to `^4.12.24`. [#1289](https://github.com/sourcebot-dev/sourcebot/pull/1289)
2525
- Surfaced an actionable error when the Lighthouse licensing service is unreachable, instead of a generic "unexpected error". [#1293](https://github.com/sourcebot-dev/sourcebot/pull/1293)
2626
- Fixed the selected language model rapidly flipping in local storage after a language model was removed. [#1295](https://github.com/sourcebot-dev/sourcebot/pull/1295)
27+
- Fixed issue where using multiple identity providers of the same type (e.g., gitlab) would result in unexpected behaviours. [#1177](https://github.com/sourcebot-dev/sourcebot/pull/1177)
2728

2829
## [5.0.1] - 2026-06-04
2930

docs/docs/configuration/idp.mdx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import LicenseKeyRequired from '/snippets/license-key-required.mdx'
1010
You can connect Sourcebot to various **external identity providers** to associate a Sourcebot user with one or more external service accounts (ex. Google, GitHub, etc).
1111

1212
External identity providers can be used for [authentication](/docs/configuration/auth) and/or [permission syncing](/docs/features/permission-syncing). They're defined in the
13-
[config file](/docs/configuration/config-file) in the top-level `identityProviders` object:
13+
[config file](/docs/configuration/config-file) in the top-level `identityProviders` array:
1414

1515
```json wrap icon="code" Example config with both google and github identity providers defined
1616
{
@@ -42,6 +42,8 @@ External identity providers can be used for [authentication](/docs/configuration
4242

4343
Secret values (such as `clientId` and `clientSecret`) can be provided as environment variables or Google Cloud secrets via [tokens](/docs/configuration/config-file#tokens).
4444

45+
To configure **multiple providers of the same type**, see [Configuring multiple providers of the same type](#configuring-multiple-providers-of-the-same-type).
46+
4547
# Supported External Identity Providers
4648

4749
Sourcebot uses [Auth.js](https://authjs.dev/) to connect to external identity providers. If there's a provider supported by Auth.js that you don't see below, please submit a
@@ -642,4 +644,49 @@ GCP IAP works differently from other identity providers. Instead of redirecting
642644
</Steps>
643645
</Accordion>
644646

647+
# Configuring multiple providers of the same type
648+
649+
By default, each provider in the `identityProviders` array is identified by an **id** equal to its `provider` value. This id determines the provider's OAuth **callback URL** (sometimes called the redirect URL):
650+
651+
```
652+
<sourcebot_url>/api/auth/callback/<id>
653+
```
654+
655+
This is why the examples above register callback URLs like `<sourcebot_url>/api/auth/callback/github`. The array form supports only **one instance per provider type**.
656+
657+
To configure **multiple instances of the same provider type** (for example, gitlab.com alongside a self-hosted GitLab instance), switch `identityProviders` to its object form, where you assign each provider a unique id:
658+
659+
```json wrap icon="code" Two GitLab providers, one for gitlab.com and one for a self-hosted instance
660+
{
661+
"$schema": "https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json",
662+
"identityProviders": {
663+
"gitlab-cloud": {
664+
"provider": "gitlab",
665+
"purpose": "sso",
666+
"displayName": "GitLab.com",
667+
"clientId": { "env": "GITLAB_CLOUD_CLIENT_ID" },
668+
"clientSecret": { "env": "GITLAB_CLOUD_CLIENT_SECRET" }
669+
},
670+
"gitlab-selfhosted": {
671+
"provider": "gitlab",
672+
"purpose": "sso",
673+
"displayName": "Selfhosted GitLab",
674+
"baseUrl": "https://gitlab.example.com",
675+
"clientId": { "env": "GITLAB_SELFHOSTED_CLIENT_ID" },
676+
"clientSecret": { "env": "GITLAB_SELFHOSTED_CLIENT_SECRET" }
677+
}
678+
}
679+
}
680+
```
681+
682+
Each provider keeps the same fields documented above. The only differences are:
683+
684+
- `identityProviders` is an **object** keyed by id instead of an array.
685+
- The id you choose (`gitlab-cloud`, `gitlab-selfhosted`) sets the callback URL, so you register `<sourcebot_url>/api/auth/callback/gitlab-cloud` and `<sourcebot_url>/api/auth/callback/gitlab-selfhosted` with their respective OAuth clients.
686+
- Set an optional `displayName` on each provider to give it a distinct label on the login screen. Without it, both instances fall back to the same provider-type name (for example, "GitLab"), making them hard to tell apart.
687+
688+
<Note>
689+
Each instance needs its own OAuth client (its own `clientId` and `clientSecret`) registered with the matching callback URL.
690+
</Note>
691+
645692

docs/snippets/schemas/v3/identityProvider.schema.mdx

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
"provider": {
1212
"const": "github"
1313
},
14+
"displayName": {
15+
"type": "string",
16+
"description": "Optional human-readable label shown on the login screen. Defaults to 'GitHub'."
17+
},
1418
"purpose": {
1519
"enum": [
1620
"sso",
@@ -107,6 +111,10 @@
107111
"provider": {
108112
"const": "gitlab"
109113
},
114+
"displayName": {
115+
"type": "string",
116+
"description": "Optional human-readable label shown on the login screen. Defaults to 'GitLab'."
117+
},
110118
"purpose": {
111119
"enum": [
112120
"sso",
@@ -203,6 +211,10 @@
203211
"provider": {
204212
"const": "google"
205213
},
214+
"displayName": {
215+
"type": "string",
216+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Google'."
217+
},
206218
"purpose": {
207219
"const": "sso"
208220
},
@@ -281,6 +293,10 @@
281293
"provider": {
282294
"const": "okta"
283295
},
296+
"displayName": {
297+
"type": "string",
298+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Okta'."
299+
},
284300
"purpose": {
285301
"const": "sso"
286302
},
@@ -390,6 +406,10 @@
390406
"provider": {
391407
"const": "keycloak"
392408
},
409+
"displayName": {
410+
"type": "string",
411+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Keycloak'."
412+
},
393413
"purpose": {
394414
"const": "sso"
395415
},
@@ -499,6 +519,10 @@
499519
"provider": {
500520
"const": "microsoft-entra-id"
501521
},
522+
"displayName": {
523+
"type": "string",
524+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Microsoft Entra ID'."
525+
},
502526
"purpose": {
503527
"const": "sso"
504528
},
@@ -608,6 +632,10 @@
608632
"provider": {
609633
"const": "gcp-iap"
610634
},
635+
"displayName": {
636+
"type": "string",
637+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Google Cloud IAP'."
638+
},
611639
"purpose": {
612640
"const": "sso"
613641
},
@@ -655,6 +683,10 @@
655683
"provider": {
656684
"const": "bitbucket-cloud"
657685
},
686+
"displayName": {
687+
"type": "string",
688+
"description": "Optional human-readable label shown on the login screen and account settings. Defaults to 'Bitbucket Cloud'."
689+
},
658690
"purpose": {
659691
"enum": [
660692
"sso",
@@ -740,6 +772,10 @@
740772
"provider": {
741773
"const": "authentik"
742774
},
775+
"displayName": {
776+
"type": "string",
777+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Authentik'."
778+
},
743779
"purpose": {
744780
"const": "sso"
745781
},
@@ -849,6 +885,10 @@
849885
"provider": {
850886
"const": "jumpcloud"
851887
},
888+
"displayName": {
889+
"type": "string",
890+
"description": "Optional human-readable label shown on the login screen. Defaults to 'JumpCloud'."
891+
},
852892
"purpose": {
853893
"const": "sso"
854894
},
@@ -958,6 +998,10 @@
958998
"provider": {
959999
"const": "bitbucket-server"
9601000
},
1001+
"displayName": {
1002+
"type": "string",
1003+
"description": "Optional human-readable label shown on the login screen and account settings. Defaults to 'Bitbucket Server'."
1004+
},
9611005
"purpose": {
9621006
"enum": [
9631007
"sso",
@@ -1054,6 +1098,10 @@
10541098
"provider": {
10551099
"const": "github"
10561100
},
1101+
"displayName": {
1102+
"type": "string",
1103+
"description": "Optional human-readable label shown on the login screen. Defaults to 'GitHub'."
1104+
},
10571105
"purpose": {
10581106
"enum": [
10591107
"sso",
@@ -1150,6 +1198,10 @@
11501198
"provider": {
11511199
"const": "gitlab"
11521200
},
1201+
"displayName": {
1202+
"type": "string",
1203+
"description": "Optional human-readable label shown on the login screen. Defaults to 'GitLab'."
1204+
},
11531205
"purpose": {
11541206
"enum": [
11551207
"sso",
@@ -1246,6 +1298,10 @@
12461298
"provider": {
12471299
"const": "google"
12481300
},
1301+
"displayName": {
1302+
"type": "string",
1303+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Google'."
1304+
},
12491305
"purpose": {
12501306
"const": "sso"
12511307
},
@@ -1324,6 +1380,10 @@
13241380
"provider": {
13251381
"const": "okta"
13261382
},
1383+
"displayName": {
1384+
"type": "string",
1385+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Okta'."
1386+
},
13271387
"purpose": {
13281388
"const": "sso"
13291389
},
@@ -1433,6 +1493,10 @@
14331493
"provider": {
14341494
"const": "keycloak"
14351495
},
1496+
"displayName": {
1497+
"type": "string",
1498+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Keycloak'."
1499+
},
14361500
"purpose": {
14371501
"const": "sso"
14381502
},
@@ -1542,6 +1606,10 @@
15421606
"provider": {
15431607
"const": "microsoft-entra-id"
15441608
},
1609+
"displayName": {
1610+
"type": "string",
1611+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Microsoft Entra ID'."
1612+
},
15451613
"purpose": {
15461614
"const": "sso"
15471615
},
@@ -1651,6 +1719,10 @@
16511719
"provider": {
16521720
"const": "gcp-iap"
16531721
},
1722+
"displayName": {
1723+
"type": "string",
1724+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Google Cloud IAP'."
1725+
},
16541726
"purpose": {
16551727
"const": "sso"
16561728
},
@@ -1698,6 +1770,10 @@
16981770
"provider": {
16991771
"const": "authentik"
17001772
},
1773+
"displayName": {
1774+
"type": "string",
1775+
"description": "Optional human-readable label shown on the login screen. Defaults to 'Authentik'."
1776+
},
17011777
"purpose": {
17021778
"const": "sso"
17031779
},
@@ -1807,6 +1883,10 @@
18071883
"provider": {
18081884
"const": "bitbucket-cloud"
18091885
},
1886+
"displayName": {
1887+
"type": "string",
1888+
"description": "Optional human-readable label shown on the login screen and account settings. Defaults to 'Bitbucket Cloud'."
1889+
},
18101890
"purpose": {
18111891
"enum": [
18121892
"sso",
@@ -1892,6 +1972,10 @@
18921972
"provider": {
18931973
"const": "jumpcloud"
18941974
},
1975+
"displayName": {
1976+
"type": "string",
1977+
"description": "Optional human-readable label shown on the login screen. Defaults to 'JumpCloud'."
1978+
},
18951979
"purpose": {
18961980
"const": "sso"
18971981
},
@@ -2001,6 +2085,10 @@
20012085
"provider": {
20022086
"const": "bitbucket-server"
20032087
},
2088+
"displayName": {
2089+
"type": "string",
2090+
"description": "Optional human-readable label shown on the login screen and account settings. Defaults to 'Bitbucket Server'."
2091+
},
20042092
"purpose": {
20052093
"enum": [
20062094
"sso",

0 commit comments

Comments
 (0)