@open-mercato/enterprise 0.4.6-develop-15c18897fc → 0.4.6-develop-34aa847ce6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/modules/sso/acl.js +11 -0
- package/dist/modules/sso/acl.js.map +7 -0
- package/dist/modules/sso/api/admin-context.js +27 -0
- package/dist/modules/sso/api/admin-context.js.map +7 -0
- package/dist/modules/sso/api/callback/oidc/route.js +103 -0
- package/dist/modules/sso/api/callback/oidc/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/activate/route.js +49 -0
- package/dist/modules/sso/api/config/[id]/activate/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/domains/route.js +96 -0
- package/dist/modules/sso/api/config/[id]/domains/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/route.js +103 -0
- package/dist/modules/sso/api/config/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/config/[id]/test/route.js +41 -0
- package/dist/modules/sso/api/config/[id]/test/route.js.map +7 -0
- package/dist/modules/sso/api/config/route.js +83 -0
- package/dist/modules/sso/api/config/route.js.map +7 -0
- package/dist/modules/sso/api/error-handler.js +28 -0
- package/dist/modules/sso/api/error-handler.js.map +7 -0
- package/dist/modules/sso/api/hrd/route.js +52 -0
- package/dist/modules/sso/api/hrd/route.js.map +7 -0
- package/dist/modules/sso/api/initiate/route.js +66 -0
- package/dist/modules/sso/api/initiate/route.js.map +7 -0
- package/dist/modules/sso/api/scim/context.js +68 -0
- package/dist/modules/sso/api/scim/context.js.map +7 -0
- package/dist/modules/sso/api/scim/logs/route.js +65 -0
- package/dist/modules/sso/api/scim/logs/route.js.map +7 -0
- package/dist/modules/sso/api/scim/tokens/[id]/route.js +42 -0
- package/dist/modules/sso/api/scim/tokens/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/scim/tokens/route.js +83 -0
- package/dist/modules/sso/api/scim/tokens/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/ServiceProviderConfig/route.js +42 -0
- package/dist/modules/sso/api/scim/v2/ServiceProviderConfig/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/Users/[id]/route.js +94 -0
- package/dist/modules/sso/api/scim/v2/Users/[id]/route.js.map +7 -0
- package/dist/modules/sso/api/scim/v2/Users/route.js +86 -0
- package/dist/modules/sso/api/scim/v2/Users/route.js.map +7 -0
- package/dist/modules/sso/backend/page.js +173 -0
- package/dist/modules/sso/backend/page.js.map +7 -0
- package/dist/modules/sso/backend/page.meta.js +31 -0
- package/dist/modules/sso/backend/page.meta.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.js +749 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.meta.js +19 -0
- package/dist/modules/sso/backend/sso/config/[id]/page.meta.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/new/page.js +381 -0
- package/dist/modules/sso/backend/sso/config/new/page.js.map +7 -0
- package/dist/modules/sso/backend/sso/config/new/page.meta.js +19 -0
- package/dist/modules/sso/backend/sso/config/new/page.meta.js.map +7 -0
- package/dist/modules/sso/data/entities.js +299 -0
- package/dist/modules/sso/data/entities.js.map +7 -0
- package/dist/modules/sso/data/validators.js +114 -0
- package/dist/modules/sso/data/validators.js.map +7 -0
- package/dist/modules/sso/di.js +26 -0
- package/dist/modules/sso/di.js.map +7 -0
- package/dist/modules/sso/events.js +24 -0
- package/dist/modules/sso/events.js.map +7 -0
- package/dist/modules/sso/i18n/de.json +146 -0
- package/dist/modules/sso/i18n/en.json +146 -0
- package/dist/modules/sso/i18n/es.json +146 -0
- package/dist/modules/sso/i18n/pl.json +146 -0
- package/dist/modules/sso/index.js +11 -0
- package/dist/modules/sso/index.js.map +7 -0
- package/dist/modules/sso/lib/domains.js +30 -0
- package/dist/modules/sso/lib/domains.js.map +7 -0
- package/dist/modules/sso/lib/oidc-provider.js +140 -0
- package/dist/modules/sso/lib/oidc-provider.js.map +7 -0
- package/dist/modules/sso/lib/registry.js +15 -0
- package/dist/modules/sso/lib/registry.js.map +7 -0
- package/dist/modules/sso/lib/scim-filter.js +43 -0
- package/dist/modules/sso/lib/scim-filter.js.map +7 -0
- package/dist/modules/sso/lib/scim-mapper.js +49 -0
- package/dist/modules/sso/lib/scim-mapper.js.map +7 -0
- package/dist/modules/sso/lib/scim-patch.js +63 -0
- package/dist/modules/sso/lib/scim-patch.js.map +7 -0
- package/dist/modules/sso/lib/scim-response.js +34 -0
- package/dist/modules/sso/lib/scim-response.js.map +7 -0
- package/dist/modules/sso/lib/scim-utils.js +9 -0
- package/dist/modules/sso/lib/scim-utils.js.map +7 -0
- package/dist/modules/sso/lib/state-cookie.js +67 -0
- package/dist/modules/sso/lib/state-cookie.js.map +7 -0
- package/dist/modules/sso/lib/types.js +1 -0
- package/dist/modules/sso/lib/types.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260219000000_sso.js +20 -0
- package/dist/modules/sso/migrations/Migration20260219000000_sso.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260222000000_sso_add_name.js +13 -0
- package/dist/modules/sso/migrations/Migration20260222000000_sso_add_name.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.js +15 -0
- package/dist/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260223000000_scim_tables.js +22 -0
- package/dist/modules/sso/migrations/Migration20260223000000_scim_tables.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224000000_sso_external_id.js +15 -0
- package/dist/modules/sso/migrations/Migration20260224000000_sso_external_id.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224100000_sso_role_grants.js +17 -0
- package/dist/modules/sso/migrations/Migration20260224100000_sso_role_grants.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260224200000_drop_default_role_id.js +13 -0
- package/dist/modules/sso/migrations/Migration20260224200000_drop_default_role_id.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.js +23 -0
- package/dist/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.js.map +7 -0
- package/dist/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.js +14 -0
- package/dist/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.js.map +7 -0
- package/dist/modules/sso/services/accountLinkingService.js +298 -0
- package/dist/modules/sso/services/accountLinkingService.js.map +7 -0
- package/dist/modules/sso/services/hrdService.js +18 -0
- package/dist/modules/sso/services/hrdService.js.map +7 -0
- package/dist/modules/sso/services/scimService.js +372 -0
- package/dist/modules/sso/services/scimService.js.map +7 -0
- package/dist/modules/sso/services/scimTokenService.js +94 -0
- package/dist/modules/sso/services/scimTokenService.js.map +7 -0
- package/dist/modules/sso/services/ssoConfigService.js +254 -0
- package/dist/modules/sso/services/ssoConfigService.js.map +7 -0
- package/dist/modules/sso/services/ssoService.js +125 -0
- package/dist/modules/sso/services/ssoService.js.map +7 -0
- package/dist/modules/sso/setup.js +47 -0
- package/dist/modules/sso/setup.js.map +7 -0
- package/dist/modules/sso/subscribers/user-deleted-cleanup.js +21 -0
- package/dist/modules/sso/subscribers/user-deleted-cleanup.js.map +7 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.client.js +106 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.client.js.map +7 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.js +16 -0
- package/dist/modules/sso/widgets/injection/login-sso/widget.js.map +7 -0
- package/dist/modules/sso/widgets/injection-table.js +14 -0
- package/dist/modules/sso/widgets/injection-table.js.map +7 -0
- package/package.json +5 -4
- package/src/index.ts +1 -1
- package/src/modules/sso/acl.ts +7 -0
- package/src/modules/sso/api/admin-context.ts +36 -0
- package/src/modules/sso/api/callback/oidc/route.ts +115 -0
- package/src/modules/sso/api/config/[id]/activate/route.ts +53 -0
- package/src/modules/sso/api/config/[id]/domains/route.ts +107 -0
- package/src/modules/sso/api/config/[id]/route.ts +114 -0
- package/src/modules/sso/api/config/[id]/test/route.ts +44 -0
- package/src/modules/sso/api/config/route.ts +88 -0
- package/src/modules/sso/api/error-handler.ts +36 -0
- package/src/modules/sso/api/hrd/route.ts +55 -0
- package/src/modules/sso/api/initiate/route.ts +70 -0
- package/src/modules/sso/api/scim/context.ts +85 -0
- package/src/modules/sso/api/scim/logs/route.ts +69 -0
- package/src/modules/sso/api/scim/tokens/[id]/route.ts +45 -0
- package/src/modules/sso/api/scim/tokens/route.ts +89 -0
- package/src/modules/sso/api/scim/v2/ServiceProviderConfig/route.ts +40 -0
- package/src/modules/sso/api/scim/v2/Users/[id]/route.ts +103 -0
- package/src/modules/sso/api/scim/v2/Users/route.ts +94 -0
- package/src/modules/sso/backend/page.meta.ts +29 -0
- package/src/modules/sso/backend/page.tsx +232 -0
- package/src/modules/sso/backend/sso/config/[id]/page.meta.ts +15 -0
- package/src/modules/sso/backend/sso/config/[id]/page.tsx +1024 -0
- package/src/modules/sso/backend/sso/config/new/page.meta.ts +15 -0
- package/src/modules/sso/backend/sso/config/new/page.tsx +463 -0
- package/src/modules/sso/data/entities.ts +240 -0
- package/src/modules/sso/data/validators.ts +140 -0
- package/src/modules/sso/di.ts +25 -0
- package/src/modules/sso/docs/entra-id-setup.md +281 -0
- package/src/modules/sso/docs/google-workspace-setup.md +174 -0
- package/src/modules/sso/docs/sso-overview.md +218 -0
- package/src/modules/sso/docs/sso-security-audit-2026-02-27.md +118 -0
- package/src/modules/sso/docs/zitadel-setup.md +195 -0
- package/src/modules/sso/events.ts +21 -0
- package/src/modules/sso/i18n/de.json +146 -0
- package/src/modules/sso/i18n/en.json +146 -0
- package/src/modules/sso/i18n/es.json +146 -0
- package/src/modules/sso/i18n/pl.json +146 -0
- package/src/modules/sso/index.ts +7 -0
- package/src/modules/sso/lib/domains.ts +31 -0
- package/src/modules/sso/lib/oidc-provider.ts +196 -0
- package/src/modules/sso/lib/registry.ts +13 -0
- package/src/modules/sso/lib/scim-filter.ts +62 -0
- package/src/modules/sso/lib/scim-mapper.ts +88 -0
- package/src/modules/sso/lib/scim-patch.ts +88 -0
- package/src/modules/sso/lib/scim-response.ts +40 -0
- package/src/modules/sso/lib/scim-utils.ts +5 -0
- package/src/modules/sso/lib/state-cookie.ts +79 -0
- package/src/modules/sso/lib/types.ts +50 -0
- package/src/modules/sso/migrations/.snapshot-open-mercato.json +912 -0
- package/src/modules/sso/migrations/Migration20260219000000_sso.ts +21 -0
- package/src/modules/sso/migrations/Migration20260222000000_sso_add_name.ts +13 -0
- package/src/modules/sso/migrations/Migration20260222000001_sso_partial_unique_org.ts +15 -0
- package/src/modules/sso/migrations/Migration20260223000000_scim_tables.ts +24 -0
- package/src/modules/sso/migrations/Migration20260224000000_sso_external_id.ts +15 -0
- package/src/modules/sso/migrations/Migration20260224100000_sso_role_grants.ts +18 -0
- package/src/modules/sso/migrations/Migration20260224200000_drop_default_role_id.ts +13 -0
- package/src/modules/sso/migrations/Migration20260225000000_sso_identities_partial_unique.ts +25 -0
- package/src/modules/sso/migrations/Migration20260305000000_sso_role_grants_org_id.ts +14 -0
- package/src/modules/sso/services/accountLinkingService.ts +386 -0
- package/src/modules/sso/services/hrdService.ts +22 -0
- package/src/modules/sso/services/scimService.ts +461 -0
- package/src/modules/sso/services/scimTokenService.ts +136 -0
- package/src/modules/sso/services/ssoConfigService.ts +337 -0
- package/src/modules/sso/services/ssoService.ts +167 -0
- package/src/modules/sso/setup.ts +56 -0
- package/src/modules/sso/subscribers/user-deleted-cleanup.ts +33 -0
- package/src/modules/sso/widgets/injection/login-sso/widget.client.tsx +130 -0
- package/src/modules/sso/widgets/injection/login-sso/widget.ts +16 -0
- package/src/modules/sso/widgets/injection-table.ts +12 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react'
|
|
3
|
+
import type { InjectionWidgetComponentProps } from '@open-mercato/shared/modules/widgets/injection'
|
|
4
|
+
import type { LoginFormWidgetContext } from '@open-mercato/core/modules/auth/frontend/login-injection'
|
|
5
|
+
import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
|
|
6
|
+
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
7
|
+
import { translateWithFallback } from '@open-mercato/shared/lib/i18n/translate'
|
|
8
|
+
|
|
9
|
+
const SSO_ERROR_CODES = [
|
|
10
|
+
'sso_failed',
|
|
11
|
+
'sso_missing_config',
|
|
12
|
+
'sso_email_not_verified',
|
|
13
|
+
'sso_state_missing',
|
|
14
|
+
'sso_idp_error',
|
|
15
|
+
'sso_missing_params',
|
|
16
|
+
] as const
|
|
17
|
+
|
|
18
|
+
const HRD_DEBOUNCE_MS = 300
|
|
19
|
+
|
|
20
|
+
type HrdResponse = {
|
|
21
|
+
hasSso: boolean
|
|
22
|
+
configId?: string
|
|
23
|
+
protocol?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function SsoLoginWidget({ context }: InjectionWidgetComponentProps<LoginFormWidgetContext>) {
|
|
27
|
+
const t = useT()
|
|
28
|
+
const translate = useCallback(
|
|
29
|
+
(key: string, fallback: string) => translateWithFallback(t, key, fallback),
|
|
30
|
+
[t],
|
|
31
|
+
)
|
|
32
|
+
const [ssoActive, setSsoActive] = useState(false)
|
|
33
|
+
const lastCheckedEmail = useRef('')
|
|
34
|
+
const debounceTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const errorParam = context.searchParams.get('error')
|
|
38
|
+
if (!errorParam) return
|
|
39
|
+
|
|
40
|
+
const errorMessages: Record<string, string> = {
|
|
41
|
+
sso_failed: translate('sso.login.errors.failed', 'SSO login failed. Please try again.'),
|
|
42
|
+
sso_missing_config: translate('sso.login.errors.missingConfig', 'SSO is not configured for this account.'),
|
|
43
|
+
sso_email_not_verified: translate('sso.login.errors.emailNotVerified', 'Your email address is not verified by the identity provider. Please verify your email and try again.'),
|
|
44
|
+
sso_state_missing: translate('sso.login.errors.stateMissing', 'SSO session expired. Please try again.'),
|
|
45
|
+
sso_idp_error: translate('sso.login.errors.idpError', 'The identity provider returned an error. Please try again or contact your administrator.'),
|
|
46
|
+
sso_missing_params: translate('sso.login.errors.missingParams', 'SSO callback was incomplete. Please try again.'),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (SSO_ERROR_CODES.includes(errorParam as typeof SSO_ERROR_CODES[number])) {
|
|
50
|
+
context.setError(errorMessages[errorParam] ?? errorMessages.sso_failed)
|
|
51
|
+
}
|
|
52
|
+
}, [context.searchParams, context.setError, translate])
|
|
53
|
+
|
|
54
|
+
const checkHrd = useCallback(async (email: string) => {
|
|
55
|
+
if (!email || !email.includes('@')) {
|
|
56
|
+
context.setAuthOverride(null)
|
|
57
|
+
setSsoActive(false)
|
|
58
|
+
lastCheckedEmail.current = ''
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (email === lastCheckedEmail.current) return
|
|
63
|
+
lastCheckedEmail.current = email
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const body: Record<string, string> = { email }
|
|
67
|
+
if (context.tenantId) {
|
|
68
|
+
body.tenantId = context.tenantId
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const res = await apiCall<HrdResponse>(
|
|
72
|
+
'/api/sso/hrd',
|
|
73
|
+
{ method: 'POST', body: JSON.stringify(body), headers: { 'Content-Type': 'application/json' } },
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if (res.result?.hasSso && res.result.configId) {
|
|
77
|
+
const configId = res.result.configId
|
|
78
|
+
setSsoActive(true)
|
|
79
|
+
context.setAuthOverride({
|
|
80
|
+
providerId: 'sso',
|
|
81
|
+
providerLabel: translate('sso.login.continueWithSso', 'Continue with SSO'),
|
|
82
|
+
onSubmit: () => {
|
|
83
|
+
const returnUrl = context.searchParams.get('returnUrl') || '/backend'
|
|
84
|
+
window.location.href = `/api/sso/initiate?configId=${encodeURIComponent(configId)}&returnUrl=${encodeURIComponent(returnUrl)}`
|
|
85
|
+
},
|
|
86
|
+
hidePassword: true,
|
|
87
|
+
hideRememberMe: true,
|
|
88
|
+
hideForgotPassword: true,
|
|
89
|
+
})
|
|
90
|
+
} else {
|
|
91
|
+
setSsoActive(false)
|
|
92
|
+
context.setAuthOverride(null)
|
|
93
|
+
}
|
|
94
|
+
} catch {
|
|
95
|
+
setSsoActive(false)
|
|
96
|
+
context.setAuthOverride(null)
|
|
97
|
+
}
|
|
98
|
+
}, [context, translate])
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
if (debounceTimer.current) {
|
|
102
|
+
clearTimeout(debounceTimer.current)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!context.email) {
|
|
106
|
+
setSsoActive(false)
|
|
107
|
+
context.setAuthOverride(null)
|
|
108
|
+
lastCheckedEmail.current = ''
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
debounceTimer.current = setTimeout(() => {
|
|
113
|
+
checkHrd(context.email)
|
|
114
|
+
}, HRD_DEBOUNCE_MS)
|
|
115
|
+
|
|
116
|
+
return () => {
|
|
117
|
+
if (debounceTimer.current) {
|
|
118
|
+
clearTimeout(debounceTimer.current)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}, [context.email, checkHrd])
|
|
122
|
+
|
|
123
|
+
if (!ssoActive) return null
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className="rounded-md border border-blue-200 bg-blue-50 px-3 py-2 text-center text-xs text-blue-800">
|
|
127
|
+
{translate('sso.login.ssoEnabled', 'SSO is enabled for this account')}
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InjectionWidgetModule } from '@open-mercato/shared/modules/widgets/injection'
|
|
2
|
+
import type { LoginFormWidgetContext } from '@open-mercato/core/modules/auth/frontend/login-injection'
|
|
3
|
+
import Widget from './widget.client'
|
|
4
|
+
|
|
5
|
+
const widgetModule: InjectionWidgetModule<LoginFormWidgetContext> = {
|
|
6
|
+
metadata: {
|
|
7
|
+
id: 'sso.injection.login-sso',
|
|
8
|
+
title: 'SSO Login',
|
|
9
|
+
features: [],
|
|
10
|
+
priority: 100,
|
|
11
|
+
enabled: true,
|
|
12
|
+
},
|
|
13
|
+
Widget,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default widgetModule
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ModuleInjectionTable } from '@open-mercato/shared/modules/widgets/injection'
|
|
2
|
+
|
|
3
|
+
export const injectionTable: ModuleInjectionTable = {
|
|
4
|
+
'auth.login:form': [
|
|
5
|
+
{
|
|
6
|
+
widgetId: 'sso.injection.login-sso',
|
|
7
|
+
priority: 100,
|
|
8
|
+
},
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default injectionTable
|