Skip to content

Commit 33e2cee

Browse files
committed
fix(sso): revoke trust for providers whose domain is spelled with a wildcard
Migration 0268 grandfathered providers by normalizing their domain with lower + btrim + a stripped leading `*.`, so sso_provider.domain can hold `*.acme.com` while its verified sso_domain row holds `acme.com`. The revoke on domain deletion compared the raw column, so such a provider matched nothing and kept domainVerified after its ownership proof was gone. The comparison now applies the same normalization 0268 used, so a grandfathered row is matched the way it was written.
1 parent 91332e2 commit 33e2cee

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

apps/sim/app/api/organizations/[id]/domains/[domainId]/route.test.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ describe('remove org domain route', () => {
9797
expect(dbChainMockFns.set).toHaveBeenCalledWith({ domainVerified: false })
9898
})
9999

100+
/**
101+
* Migration 0268 grandfathered providers by stripping a leading `*.`, so a
102+
* provider can be stored as `*.acme.com` while its verified row holds
103+
* `acme.com`. A naive equality match would leave that provider trusted after
104+
* the proof was deleted.
105+
*/
106+
it('matches the provider domain the way it was grandfathered (wildcard-tolerant)', async () => {
107+
queueTableRows(member, [{ role: 'owner' }])
108+
dbChainMockFns.returning.mockResolvedValueOnce([{ domain: 'acme.com' }])
109+
await DELETE(createMockRequest('DELETE'), routeContext)
110+
const revokeWhere = dbChainMockFns.where.mock.calls.find(([condition]) =>
111+
JSON.stringify(condition ?? '').includes('regexp_replace')
112+
)
113+
expect(revokeWhere).toBeDefined()
114+
})
115+
100116
it('does not revoke trust when no domain was removed', async () => {
101117
queueTableRows(member, [{ role: 'owner' }])
102118
dbChainMockFns.returning.mockResolvedValueOnce([]) // delete matched nothing

apps/sim/app/api/organizations/[id]/domains/[domainId]/route.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,17 @@ export const DELETE = withRouteHandler(
7474

7575
if (!deleted) return null
7676

77+
// Match the provider domain the same way migration 0268 normalized it when it
78+
// grandfathered these rows: lower, trimmed, leading `*.` stripped. A provider
79+
// stored as `*.acme.com` against a verified row holding `acme.com` would
80+
// otherwise keep its trust after the proof was deleted.
7781
await tx
7882
.update(ssoProvider)
7983
.set({ domainVerified: false })
8084
.where(
8185
and(
8286
eq(ssoProvider.organizationId, organizationId),
83-
sql`lower(${ssoProvider.domain}) = ${deleted.domain}`
87+
sql`lower(regexp_replace(btrim(${ssoProvider.domain}), '^\\*\\.', '')) = ${deleted.domain}`
8488
)
8589
)
8690

0 commit comments

Comments
 (0)