@burdenoff/microfe-auth 2026.830.1 → 2026.830.2
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/auth/AuthRoot.js +43 -41
- package/dist/auth/AuthRoot.js.map +1 -1
- package/dist/auth/components/AuthLayout.js +65 -67
- package/dist/auth/components/AuthLayout.js.map +1 -1
- package/dist/auth/components/CaptchaV2.js +21 -24
- package/dist/auth/components/CaptchaV2.js.map +1 -1
- package/dist/auth/components/ConfirmActionDialog.js +33 -32
- package/dist/auth/components/ConfirmActionDialog.js.map +1 -1
- package/dist/auth/components/profile/UserProfileMenu.js +44 -46
- package/dist/auth/components/profile/UserProfileMenu.js.map +1 -1
- package/dist/auth/components/workspace/WorkspaceSelector.js +62 -68
- package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -1
- package/dist/auth/pages/AuditLogPage.js +65 -68
- package/dist/auth/pages/AuditLogPage.js.map +1 -1
- package/dist/auth/pages/EmailVerifyPage.js +51 -54
- package/dist/auth/pages/EmailVerifyPage.js.map +1 -1
- package/dist/auth/pages/LoginPage.js +223 -225
- package/dist/auth/pages/LoginPage.js.map +1 -1
- package/dist/auth/pages/MagicLinkPage.js +67 -69
- package/dist/auth/pages/MagicLinkPage.js.map +1 -1
- package/dist/auth/pages/MfaSetupPage.js +85 -88
- package/dist/auth/pages/MfaSetupPage.js.map +1 -1
- package/dist/auth/pages/MfaVerifyPage.js +60 -63
- package/dist/auth/pages/MfaVerifyPage.js.map +1 -1
- package/dist/auth/pages/OAuthCallbackPage.js +37 -40
- package/dist/auth/pages/OAuthCallbackPage.js.map +1 -1
- package/dist/auth/pages/PasswordResetPage.js +102 -105
- package/dist/auth/pages/PasswordResetPage.js.map +1 -1
- package/dist/auth/pages/ReactivatePage.js +54 -57
- package/dist/auth/pages/ReactivatePage.js.map +1 -1
- package/dist/auth/pages/RegisterPage.js +171 -174
- package/dist/auth/pages/RegisterPage.js.map +1 -1
- package/dist/auth/pages/SSOClearPage.js +21 -20
- package/dist/auth/pages/SSOClearPage.js.map +1 -1
- package/dist/auth/pages/SSODepositPage.js +27 -26
- package/dist/auth/pages/SSODepositPage.js.map +1 -1
- package/dist/auth/pages/SSORelayCallbackPage.js +19 -18
- package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -1
- package/dist/auth/pages/SecurityPage.js +247 -250
- package/dist/auth/pages/SecurityPage.js.map +1 -1
- package/dist/auth/pages/SessionsPage.js +95 -98
- package/dist/auth/pages/SessionsPage.js.map +1 -1
- package/dist/auth/pages/SsoCallbackPage.js +53 -56
- package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
- package/dist/auth/pages/SsoConfigPage.js +296 -299
- package/dist/auth/pages/SsoConfigPage.js.map +1 -1
- package/dist/auth/pages/SsoLoginPage.js +65 -68
- package/dist/auth/pages/SsoLoginPage.js.map +1 -1
- package/dist/auth/pages/UserDetailsPage.js +124 -127
- package/dist/auth/pages/UserDetailsPage.js.map +1 -1
- package/dist/auth/pages/UserProfilePage.js +171 -174
- package/dist/auth/pages/UserProfilePage.js.map +1 -1
- package/dist/auth/pages/UsersPage.js +322 -325
- package/dist/auth/pages/UsersPage.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/shared/hooks/index.d.ts +1 -6
- package/dist/shared/hooks/useTr.d.ts +16 -0
- package/dist/shared/hooks/useTr.js +14 -0
- package/dist/shared/hooks/useTr.js.map +1 -0
- package/dist/translations/en.d.ts +806 -248
- package/dist/translations/en.js +870 -0
- package/dist/translations/en.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,59 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
|
+
import { AuthLayout as t } from "../components/AuthLayout.js";
|
|
3
|
+
import { AlertIcon as n, EmailIcon as r, SpinnerIcon as i } from "../components/AuthIcons.js";
|
|
4
|
+
import { useSsoOperations as a } from "../hooks/useSsoOperations.js";
|
|
5
|
+
import { useEffect as o, useState as s } from "react";
|
|
6
|
+
import { useNavigate as c, useSearchParams as l } from "react-router";
|
|
7
7
|
import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
8
8
|
import { Button as p } from "@burdenoff/fe-libs/button";
|
|
9
9
|
import { PagePurpose as m } from "@burdenoff/fe-libs/ui";
|
|
10
10
|
//#region src/auth/pages/SsoLoginPage.tsx
|
|
11
11
|
function h() {
|
|
12
|
-
let {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
(
|
|
18
|
-
}, [b]);
|
|
19
|
-
let F = async (e) => {
|
|
20
|
-
e.preventDefault(), O(null), P(!1), M(!0);
|
|
12
|
+
let h = e(), g = c(), [_] = l(), v = _.get("tenant"), y = _.get("method"), { initiateSsoLogin: b, initiateExternalOidcLogin: x, isGeneratingRequest: S, isGeneratingOidcUrl: C } = a(v ?? void 0), [w, T] = s(""), [E, D] = s(null), [O, k] = s("oidc"), [A, j] = s(!1), [M, N] = s(!1);
|
|
13
|
+
o(() => {
|
|
14
|
+
(y === "saml" || y === "oidc") && k(y);
|
|
15
|
+
}, [y]);
|
|
16
|
+
let P = async (e) => {
|
|
17
|
+
e.preventDefault(), D(null), N(!1), j(!0);
|
|
21
18
|
try {
|
|
22
|
-
let e =
|
|
19
|
+
let e = w.split("@")[1];
|
|
23
20
|
if (!e) {
|
|
24
|
-
|
|
21
|
+
D(h("auth.ssoLogin.invalidEmailDomain", "Please enter a valid email address with your company domain")), j(!1);
|
|
25
22
|
return;
|
|
26
23
|
}
|
|
27
|
-
let t =
|
|
28
|
-
sessionStorage.setItem("sso_email",
|
|
24
|
+
let t = v || e;
|
|
25
|
+
sessionStorage.setItem("sso_email", w), O === "oidc" ? await x(t, "/dashboard") : await b(t, "/dashboard");
|
|
29
26
|
} catch (e) {
|
|
30
27
|
console.error("SSO login failed:", e);
|
|
31
28
|
let t = e instanceof Error ? e.message : "Failed to initiate SSO login. Please check your configuration.";
|
|
32
|
-
t.toLowerCase().includes("sso") && (t.toLowerCase().includes("not configured") || t.toLowerCase().includes("not set up")) ? (
|
|
29
|
+
t.toLowerCase().includes("sso") && (t.toLowerCase().includes("not configured") || t.toLowerCase().includes("not set up")) ? (N(!0), D(h("auth.ssoLogin.ssoNotConfigured", "SSO is not configured for your organization. Please use regular email/password login or contact your administrator to set up SSO."))) : D(t), j(!1);
|
|
33
30
|
}
|
|
34
|
-
},
|
|
35
|
-
return /* @__PURE__ */ f(
|
|
36
|
-
title:
|
|
37
|
-
subtitle:
|
|
31
|
+
}, F = S || C || A;
|
|
32
|
+
return /* @__PURE__ */ f(t, {
|
|
33
|
+
title: h("auth.ssoLogin.title", "Enterprise SSO"),
|
|
34
|
+
subtitle: h("auth.ssoLogin.subtitle", "Sign in with your company's identity provider"),
|
|
38
35
|
children: [
|
|
39
36
|
/* @__PURE__ */ d(m, {
|
|
40
37
|
className: "mb-5",
|
|
41
|
-
children:
|
|
38
|
+
children: h("auth.ssoLogin.purpose", "Sign in through your company's identity provider (Okta, Azure AD, Google, and more). Enter your work email and we'll route you to your organization's OIDC or SAML login.")
|
|
42
39
|
}),
|
|
43
40
|
/* @__PURE__ */ f("form", {
|
|
44
|
-
onSubmit:
|
|
41
|
+
onSubmit: P,
|
|
45
42
|
className: "space-y-5",
|
|
46
43
|
children: [
|
|
47
|
-
|
|
48
|
-
className: `flex items-start gap-3 p-4 rounded-xl border ${
|
|
49
|
-
children: [/* @__PURE__ */ d(
|
|
44
|
+
E && /* @__PURE__ */ f("div", {
|
|
45
|
+
className: `flex items-start gap-3 p-4 rounded-xl border ${M ? "bg-status-warning-bg-subtle border-status-warning-border" : "bg-status-error-bg-subtle border-status-error-border"}`,
|
|
46
|
+
children: [/* @__PURE__ */ d(n, { className: `size-5 flex-shrink-0 mt-0.5 ${M ? "text-status-warning-text" : "text-status-error-text"}` }), /* @__PURE__ */ f("div", {
|
|
50
47
|
className: "flex-1",
|
|
51
48
|
children: [/* @__PURE__ */ d("p", {
|
|
52
|
-
className: `text-sm ${
|
|
53
|
-
children:
|
|
54
|
-
}),
|
|
49
|
+
className: `text-sm ${M ? "text-status-warning-text" : "text-status-error-text"}`,
|
|
50
|
+
children: E
|
|
51
|
+
}), M && /* @__PURE__ */ f("button", {
|
|
55
52
|
type: "button",
|
|
56
|
-
onClick: () =>
|
|
53
|
+
onClick: () => g("/auth/login", { state: { email: w } }),
|
|
57
54
|
className: "mt-3 inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-status-warning-bg-subtle hover:bg-status-warning-bg-subtle text-status-warning-text text-sm font-semibold transition-all",
|
|
58
55
|
children: [/* @__PURE__ */ d("svg", {
|
|
59
56
|
className: "size-4",
|
|
@@ -66,7 +63,7 @@ function h() {
|
|
|
66
63
|
strokeWidth: 2,
|
|
67
64
|
d: "M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"
|
|
68
65
|
})
|
|
69
|
-
}),
|
|
66
|
+
}), h("auth.ssoLogin.useEmailLogin", "Use Email/Password Login Instead")]
|
|
70
67
|
})]
|
|
71
68
|
})]
|
|
72
69
|
}),
|
|
@@ -74,19 +71,19 @@ function h() {
|
|
|
74
71
|
className: "space-y-2",
|
|
75
72
|
children: [/* @__PURE__ */ d("label", {
|
|
76
73
|
className: "block text-sm font-medium text-[var(--color-text-primary)]",
|
|
77
|
-
children:
|
|
74
|
+
children: h("auth.ssoLogin.authMethod", "Authentication Method")
|
|
78
75
|
}), /* @__PURE__ */ f("div", {
|
|
79
76
|
className: "grid grid-cols-2 gap-3",
|
|
80
77
|
children: [/* @__PURE__ */ d("button", {
|
|
81
78
|
type: "button",
|
|
82
|
-
onClick: () =>
|
|
83
|
-
className: `p-4 rounded-xl border-2 transition-all ${
|
|
79
|
+
onClick: () => k("oidc"),
|
|
80
|
+
className: `p-4 rounded-xl border-2 transition-all ${O === "oidc" ? "border-action-primary-bg bg-status-info-bg-subtle" : "border-border-subtle hover:border-border-default"}`,
|
|
84
81
|
children: /* @__PURE__ */ f("div", {
|
|
85
82
|
className: "flex items-center gap-3",
|
|
86
83
|
children: [/* @__PURE__ */ d("div", {
|
|
87
|
-
className: `size-10 rounded-lg flex items-center justify-center ${
|
|
84
|
+
className: `size-10 rounded-lg flex items-center justify-center ${O === "oidc" ? "bg-status-info-bg-subtle0" : "bg-bg-sunken"}`,
|
|
88
85
|
children: /* @__PURE__ */ d("svg", {
|
|
89
|
-
className: `size-5 ${
|
|
86
|
+
className: `size-5 ${O === "oidc" ? "text-white" : "text-text-secondary"}`,
|
|
90
87
|
fill: "none",
|
|
91
88
|
viewBox: "0 0 24 24",
|
|
92
89
|
stroke: "currentColor",
|
|
@@ -100,24 +97,24 @@ function h() {
|
|
|
100
97
|
}), /* @__PURE__ */ f("div", {
|
|
101
98
|
className: "text-left",
|
|
102
99
|
children: [/* @__PURE__ */ d("div", {
|
|
103
|
-
className: `font-medium ${
|
|
100
|
+
className: `font-medium ${O === "oidc" ? "text-text-linkHover" : "text-text-primary"}`,
|
|
104
101
|
children: "OpenID Connect"
|
|
105
102
|
}), /* @__PURE__ */ d("div", {
|
|
106
103
|
className: "text-xs text-text-secondary",
|
|
107
|
-
children:
|
|
104
|
+
children: h("auth.ssoLogin.modernRecommended", "Modern & Recommended")
|
|
108
105
|
})]
|
|
109
106
|
})]
|
|
110
107
|
})
|
|
111
108
|
}), /* @__PURE__ */ d("button", {
|
|
112
109
|
type: "button",
|
|
113
|
-
onClick: () =>
|
|
114
|
-
className: `p-4 rounded-xl border-2 transition-all ${
|
|
110
|
+
onClick: () => k("saml"),
|
|
111
|
+
className: `p-4 rounded-xl border-2 transition-all ${O === "saml" ? "border-accent-purple bg-accent-purple-subtle" : "border-border-subtle hover:border-border-default"}`,
|
|
115
112
|
children: /* @__PURE__ */ f("div", {
|
|
116
113
|
className: "flex items-center gap-3",
|
|
117
114
|
children: [/* @__PURE__ */ d("div", {
|
|
118
|
-
className: `size-10 rounded-lg flex items-center justify-center ${
|
|
115
|
+
className: `size-10 rounded-lg flex items-center justify-center ${O === "saml" ? "bg-accent-purple-subtle0" : "bg-bg-sunken"}`,
|
|
119
116
|
children: /* @__PURE__ */ d("svg", {
|
|
120
|
-
className: `size-5 ${
|
|
117
|
+
className: `size-5 ${O === "saml" ? "text-white" : "text-text-secondary"}`,
|
|
121
118
|
fill: "none",
|
|
122
119
|
viewBox: "0 0 24 24",
|
|
123
120
|
stroke: "currentColor",
|
|
@@ -131,11 +128,11 @@ function h() {
|
|
|
131
128
|
}), /* @__PURE__ */ f("div", {
|
|
132
129
|
className: "text-left",
|
|
133
130
|
children: [/* @__PURE__ */ d("div", {
|
|
134
|
-
className: `font-medium ${
|
|
131
|
+
className: `font-medium ${O === "saml" ? "text-accent-purple" : "text-text-primary"}`,
|
|
135
132
|
children: "SAML 2.0"
|
|
136
133
|
}), /* @__PURE__ */ d("div", {
|
|
137
134
|
className: "text-xs text-text-secondary",
|
|
138
|
-
children:
|
|
135
|
+
children: h("auth.ssoLogin.enterpriseLegacy", "Enterprise Legacy")
|
|
139
136
|
})]
|
|
140
137
|
})]
|
|
141
138
|
})
|
|
@@ -143,10 +140,10 @@ function h() {
|
|
|
143
140
|
})]
|
|
144
141
|
}),
|
|
145
142
|
/* @__PURE__ */ d("div", {
|
|
146
|
-
className: `p-4 rounded-xl border ${
|
|
143
|
+
className: `p-4 rounded-xl border ${O === "oidc" ? "bg-status-info-bg-subtle border-status-info-border" : "bg-accent-purple-subtle border-accent-purple-subtle"}`,
|
|
147
144
|
children: /* @__PURE__ */ d("p", {
|
|
148
|
-
className: `text-sm ${
|
|
149
|
-
children:
|
|
145
|
+
className: `text-sm ${O === "oidc" ? "text-status-info-text" : "text-accent-purple"}`,
|
|
146
|
+
children: O === "oidc" ? h("auth.sso.oidcInfoBannerPkce", "Sign in using OpenID Connect with your identity provider. Supports modern SSO with PKCE security.") : h("auth.sso.samlInfoBanner", "Sign in using SAML 2.0 with your enterprise identity provider (Okta, Azure AD, etc.).")
|
|
150
147
|
})
|
|
151
148
|
}),
|
|
152
149
|
/* @__PURE__ */ f("div", {
|
|
@@ -155,39 +152,39 @@ function h() {
|
|
|
155
152
|
/* @__PURE__ */ d("label", {
|
|
156
153
|
htmlFor: "email",
|
|
157
154
|
className: "block text-sm font-medium text-[var(--color-text-primary)]",
|
|
158
|
-
children:
|
|
155
|
+
children: h("auth.ssoLogin.workEmail", "Work Email Address")
|
|
159
156
|
}),
|
|
160
157
|
/* @__PURE__ */ f("div", {
|
|
161
158
|
className: "relative",
|
|
162
159
|
children: [/* @__PURE__ */ d("div", {
|
|
163
160
|
className: "absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none",
|
|
164
|
-
children: /* @__PURE__ */ d(
|
|
161
|
+
children: /* @__PURE__ */ d(r, { className: "size-5 text-[var(--color-text-tertiary)]" })
|
|
165
162
|
}), /* @__PURE__ */ d("input", {
|
|
166
163
|
id: "email",
|
|
167
164
|
type: "email",
|
|
168
165
|
required: !0,
|
|
169
166
|
"aria-required": "true",
|
|
170
|
-
"aria-label":
|
|
171
|
-
value:
|
|
172
|
-
onChange: (e) =>
|
|
167
|
+
"aria-label": h("auth.ssoLogin.workEmail", "Work Email Address"),
|
|
168
|
+
value: w,
|
|
169
|
+
onChange: (e) => T(e.target.value),
|
|
173
170
|
autoComplete: "email",
|
|
174
171
|
className: "block w-full pl-[3.5rem] pr-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] placeholder:text-[var(--color-text-tertiary)] focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all",
|
|
175
|
-
placeholder: "you@company.com"
|
|
172
|
+
placeholder: h("auth.ssoLogin.emailPlaceholder", "you@company.com")
|
|
176
173
|
})]
|
|
177
174
|
}),
|
|
178
175
|
/* @__PURE__ */ d("p", {
|
|
179
176
|
className: "text-xs text-[var(--color-text-tertiary)]",
|
|
180
|
-
children:
|
|
177
|
+
children: h("auth.ssoLogin.useCompanyEmail", "Use your company email (e.g., @yourcompany.com)")
|
|
181
178
|
})
|
|
182
179
|
]
|
|
183
180
|
}),
|
|
184
181
|
/* @__PURE__ */ d(p, {
|
|
185
182
|
type: "submit",
|
|
186
|
-
disabled:
|
|
183
|
+
disabled: F || !w,
|
|
187
184
|
variant: "default",
|
|
188
185
|
size: "lg",
|
|
189
|
-
className: `w-full font-semibold ${
|
|
190
|
-
children:
|
|
186
|
+
className: `w-full font-semibold ${O === "saml" ? "bg-accent-purple text-white hover:bg-accent-purple hover:opacity-90" : ""}`,
|
|
187
|
+
children: F ? /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d(i, { className: "size-5 animate-spin" }), /* @__PURE__ */ d("span", { children: h("auth.sso.redirecting", "Redirecting...") })] }) : /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("svg", {
|
|
191
188
|
className: "size-5",
|
|
192
189
|
fill: "none",
|
|
193
190
|
viewBox: "0 0 24 24",
|
|
@@ -199,7 +196,7 @@ function h() {
|
|
|
199
196
|
strokeWidth: 2,
|
|
200
197
|
d: "M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"
|
|
201
198
|
})
|
|
202
|
-
}), /* @__PURE__ */ d("span", { children:
|
|
199
|
+
}), /* @__PURE__ */ d("span", { children: O === "oidc" ? h("auth.sso.continueWithOidc", "Continue with OIDC") : h("auth.sso.continueWithSaml", "Continue with SAML") })] })
|
|
203
200
|
})
|
|
204
201
|
]
|
|
205
202
|
}),
|
|
@@ -207,11 +204,11 @@ function h() {
|
|
|
207
204
|
className: "mt-6 text-center",
|
|
208
205
|
children: /* @__PURE__ */ d("button", {
|
|
209
206
|
type: "button",
|
|
210
|
-
onClick: () =>
|
|
207
|
+
onClick: () => g("/auth/login"),
|
|
211
208
|
className: "text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors",
|
|
212
209
|
children: /* @__PURE__ */ d("span", {
|
|
213
210
|
className: "font-semibold text-text-link hover:text-text-linkHover",
|
|
214
|
-
children:
|
|
211
|
+
children: h("auth.ssoLogin.backToLogin", "Back to regular login")
|
|
215
212
|
})
|
|
216
213
|
})
|
|
217
214
|
}),
|
|
@@ -219,14 +216,14 @@ function h() {
|
|
|
219
216
|
className: "mt-4 text-center",
|
|
220
217
|
children: /* @__PURE__ */ f("button", {
|
|
221
218
|
type: "button",
|
|
222
|
-
onClick: () =>
|
|
219
|
+
onClick: () => g("/auth/reactivate"),
|
|
223
220
|
className: "text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors",
|
|
224
221
|
children: [
|
|
225
|
-
|
|
222
|
+
h("auth.ssoLogin.deactivatedAccount", "Have a deactivated account?"),
|
|
226
223
|
" ",
|
|
227
224
|
/* @__PURE__ */ d("span", {
|
|
228
225
|
className: "font-semibold text-status-success-text hover:text-status-success-text",
|
|
229
|
-
children:
|
|
226
|
+
children: h("auth.ssoLogin.reactivateIt", "Reactivate it")
|
|
230
227
|
})
|
|
231
228
|
]
|
|
232
229
|
})
|
|
@@ -235,10 +232,10 @@ function h() {
|
|
|
235
232
|
className: "mt-6 p-4 rounded-xl bg-bg-canvas/50 border border-border-subtle",
|
|
236
233
|
children: [/* @__PURE__ */ d("h4", {
|
|
237
234
|
className: "text-sm font-medium text-[var(--color-text-primary)] mb-2",
|
|
238
|
-
children:
|
|
235
|
+
children: h("auth.ssoLogin.noSso", "Don't see your company's SSO?")
|
|
239
236
|
}), /* @__PURE__ */ d("p", {
|
|
240
237
|
className: "text-xs text-[var(--color-text-secondary)]",
|
|
241
|
-
children:
|
|
238
|
+
children: h("auth.ssoLogin.contactIT", "Contact your IT administrator to set up SSO for your organization. They'll need to configure your identity provider with our service.")
|
|
242
239
|
})]
|
|
243
240
|
})
|
|
244
241
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SsoLoginPage.js","names":[],"sources":["../../../src/auth/pages/SsoLoginPage.tsx"],"sourcesContent":["import { useState, useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { useNavigate, useSearchParams } from \"react-router\";\nimport { useSsoOperations } from \"../hooks/useSsoOperations\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { PagePurpose } from \"@burdenoff/fe-libs/ui\";\nimport { EmailIcon, SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\n\ntype SsoMethod = \"saml\" | \"oidc\";\n\n/**\n * SSO Login Page\n * Allows users to enter their email/company domain to initiate SSO login\n * Supports both SAML 2.0 and OIDC authentication methods\n */\nexport function SsoLoginPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const tenantFromUrl = searchParams.get(\"tenant\");\n const methodFromUrl = searchParams.get(\"method\") as SsoMethod | null;\n const {\n initiateSsoLogin,\n initiateExternalOidcLogin,\n isGeneratingRequest,\n isGeneratingOidcUrl,\n } = useSsoOperations(tenantFromUrl ?? undefined);\n\n const [email, setEmail] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [ssoMethod, setSsoMethod] = useState<SsoMethod>(\"oidc\");\n const [isInitiating, setIsInitiating] = useState(false);\n const [isSsoNotConfigured, setIsSsoNotConfigured] = useState(false);\n\n // Set method from URL if provided\n useEffect(() => {\n if (methodFromUrl === \"saml\" || methodFromUrl === \"oidc\") {\n setSsoMethod(methodFromUrl);\n }\n }, [methodFromUrl]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setIsSsoNotConfigured(false);\n setIsInitiating(true);\n\n try {\n // Extract domain from email\n const domain = email.split(\"@\")[1];\n if (!domain) {\n setError(\n tr(\n \"auth.ssoLogin.invalidEmailDomain\",\n \"Please enter a valid email address with your company domain\",\n ),\n );\n setIsInitiating(false);\n return;\n }\n\n // In a real app, you would look up the tenant by domain\n // For now, we'll use the tenant from URL or the domain itself\n const tenantId = tenantFromUrl || domain;\n\n // Store email for post-login\n sessionStorage.setItem(\"sso_email\", email);\n\n if (ssoMethod === \"oidc\") {\n // External OIDC flow (Azure AD, Google, etc.)\n await initiateExternalOidcLogin(tenantId, \"/dashboard\");\n } else {\n await initiateSsoLogin(tenantId, \"/dashboard\");\n }\n } catch (err) {\n console.error(\"SSO login failed:\", err);\n const errorMessage =\n err instanceof Error\n ? err.message\n : \"Failed to initiate SSO login. Please check your configuration.\";\n\n // Check if error is about SSO not being configured\n if (\n errorMessage.toLowerCase().includes(\"sso\") &&\n (errorMessage.toLowerCase().includes(\"not configured\") ||\n errorMessage.toLowerCase().includes(\"not set up\"))\n ) {\n setIsSsoNotConfigured(true);\n setError(\n tr(\n \"auth.ssoLogin.ssoNotConfigured\",\n \"SSO is not configured for your organization. Please use regular email/password login or contact your administrator to set up SSO.\",\n ),\n );\n } else {\n setError(errorMessage);\n }\n\n setIsInitiating(false);\n }\n };\n\n const isSubmitting =\n isGeneratingRequest || isGeneratingOidcUrl || isInitiating;\n\n return (\n <AuthLayout\n title={tr(\"auth.ssoLogin.title\", \"Enterprise SSO\")}\n subtitle={tr(\n \"auth.ssoLogin.subtitle\",\n \"Sign in with your company's identity provider\",\n )}\n >\n <PagePurpose className=\"mb-5\">\n {tr(\n \"auth.ssoLogin.purpose\",\n \"Sign in through your company's identity provider (Okta, Azure AD, Google, and more). Enter your work email and we'll route you to your organization's OIDC or SAML login.\",\n )}\n </PagePurpose>\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && (\n <div\n className={`flex items-start gap-3 p-4 rounded-xl border ${\n isSsoNotConfigured\n ? \"bg-status-warning-bg-subtle border-status-warning-border\"\n : \"bg-status-error-bg-subtle border-status-error-border\"\n }`}\n >\n <AlertIcon\n className={`size-5 flex-shrink-0 mt-0.5 ${\n isSsoNotConfigured\n ? \"text-status-warning-text\"\n : \"text-status-error-text\"\n }`}\n />\n <div className=\"flex-1\">\n <p\n className={`text-sm ${\n isSsoNotConfigured\n ? \"text-status-warning-text\"\n : \"text-status-error-text\"\n }`}\n >\n {error}\n </p>\n {isSsoNotConfigured && (\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/login\", { state: { email } })}\n className=\"mt-3 inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-status-warning-bg-subtle hover:bg-status-warning-bg-subtle text-status-warning-text text-sm font-semibold transition-all\"\n >\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1\"\n />\n </svg>\n {tr(\n \"auth.ssoLogin.useEmailLogin\",\n \"Use Email/Password Login Instead\",\n )}\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* SSO Method Toggle */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-[var(--color-text-primary)]\">\n {tr(\"auth.ssoLogin.authMethod\", \"Authentication Method\")}\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n <button\n type=\"button\"\n onClick={() => setSsoMethod(\"oidc\")}\n className={`p-4 rounded-xl border-2 transition-all ${\n ssoMethod === \"oidc\"\n ? \"border-action-primary-bg bg-status-info-bg-subtle\"\n : \"border-border-subtle hover:border-border-default\"\n }`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`size-10 rounded-lg flex items-center justify-center ${\n ssoMethod === \"oidc\"\n ? \"bg-status-info-bg-subtle0\"\n : \"bg-bg-sunken\"\n }`}\n >\n <svg\n className={`size-5 ${ssoMethod === \"oidc\" ? \"text-white\" : \"text-text-secondary\"}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9\"\n />\n </svg>\n </div>\n <div className=\"text-left\">\n <div\n className={`font-medium ${ssoMethod === \"oidc\" ? \"text-text-linkHover\" : \"text-text-primary\"}`}\n >\n OpenID Connect\n </div>\n <div className=\"text-xs text-text-secondary\">\n {tr(\n \"auth.ssoLogin.modernRecommended\",\n \"Modern & Recommended\",\n )}\n </div>\n </div>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => setSsoMethod(\"saml\")}\n className={`p-4 rounded-xl border-2 transition-all ${\n ssoMethod === \"saml\"\n ? \"border-accent-purple bg-accent-purple-subtle\"\n : \"border-border-subtle hover:border-border-default\"\n }`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`size-10 rounded-lg flex items-center justify-center ${\n ssoMethod === \"saml\"\n ? \"bg-accent-purple-subtle0\"\n : \"bg-bg-sunken\"\n }`}\n >\n <svg\n className={`size-5 ${ssoMethod === \"saml\" ? \"text-white\" : \"text-text-secondary\"}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div className=\"text-left\">\n <div\n className={`font-medium ${ssoMethod === \"saml\" ? \"text-accent-purple\" : \"text-text-primary\"}`}\n >\n SAML 2.0\n </div>\n <div className=\"text-xs text-text-secondary\">\n {tr(\"auth.ssoLogin.enterpriseLegacy\", \"Enterprise Legacy\")}\n </div>\n </div>\n </div>\n </button>\n </div>\n </div>\n\n {/* Info Banner */}\n <div\n className={`p-4 rounded-xl border ${\n ssoMethod === \"oidc\"\n ? \"bg-status-info-bg-subtle border-status-info-border\"\n : \"bg-accent-purple-subtle border-accent-purple-subtle\"\n }`}\n >\n <p\n className={`text-sm ${\n ssoMethod === \"oidc\"\n ? \"text-status-info-text\"\n : \"text-accent-purple\"\n }`}\n >\n {ssoMethod === \"oidc\"\n ? tr(\n \"auth.sso.oidcInfoBannerPkce\",\n \"Sign in using OpenID Connect with your identity provider. Supports modern SSO with PKCE security.\",\n )\n : tr(\n \"auth.sso.samlInfoBanner\",\n \"Sign in using SAML 2.0 with your enterprise identity provider (Okta, Azure AD, etc.).\",\n )}\n </p>\n </div>\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"email\"\n className=\"block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr(\"auth.ssoLogin.workEmail\", \"Work Email Address\")}\n </label>\n <div className=\"relative\">\n <div className=\"absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none\">\n <EmailIcon className=\"size-5 text-[var(--color-text-tertiary)]\" />\n </div>\n <input\n id=\"email\"\n type=\"email\"\n required\n aria-required=\"true\"\n aria-label={tr(\"auth.ssoLogin.workEmail\", \"Work Email Address\")}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n autoComplete=\"email\"\n className=\"block w-full pl-[3.5rem] pr-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] placeholder:text-[var(--color-text-tertiary)] focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all\"\n placeholder=\"you@company.com\"\n />\n </div>\n <p className=\"text-xs text-[var(--color-text-tertiary)]\">\n {tr(\n \"auth.ssoLogin.useCompanyEmail\",\n \"Use your company email (e.g., @yourcompany.com)\",\n )}\n </p>\n </div>\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n disabled={isSubmitting || !email}\n variant=\"default\"\n size=\"lg\"\n className={`w-full font-semibold ${\n ssoMethod === \"saml\"\n ? \"bg-accent-purple text-white hover:bg-accent-purple hover:opacity-90\"\n : \"\"\n }`}\n >\n {isSubmitting ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.sso.redirecting\", \"Redirecting...\")}</span>\n </>\n ) : (\n <>\n <svg\n className=\"size-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1\"\n />\n </svg>\n <span>\n {ssoMethod === \"oidc\"\n ? tr(\"auth.sso.continueWithOidc\", \"Continue with OIDC\")\n : tr(\"auth.sso.continueWithSaml\", \"Continue with SAML\")}\n </span>\n </>\n )}\n </Button>\n </form>\n\n {/* Back to Regular Login */}\n <div className=\"mt-6 text-center\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/login\")}\n className=\"text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors\"\n >\n <span className=\"font-semibold text-text-link hover:text-text-linkHover\">\n {tr(\"auth.ssoLogin.backToLogin\", \"Back to regular login\")}\n </span>\n </button>\n </div>\n\n {/* Reactivate Account Link */}\n <div className=\"mt-4 text-center\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/reactivate\")}\n className=\"text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors\"\n >\n {tr(\n \"auth.ssoLogin.deactivatedAccount\",\n \"Have a deactivated account?\",\n )}{\" \"}\n <span className=\"font-semibold text-status-success-text hover:text-status-success-text\">\n {tr(\"auth.ssoLogin.reactivateIt\", \"Reactivate it\")}\n </span>\n </button>\n </div>\n\n {/* Help Text */}\n <div className=\"mt-6 p-4 rounded-xl bg-bg-canvas/50 border border-border-subtle\">\n <h4 className=\"text-sm font-medium text-[var(--color-text-primary)] mb-2\">\n {tr(\"auth.ssoLogin.noSso\", \"Don't see your company's SSO?\")}\n </h4>\n <p className=\"text-xs text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.ssoLogin.contactIT\",\n \"Contact your IT administrator to set up SSO for your organization. They'll need to configure your identity provider with our service.\",\n )}\n </p>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SsoLoginPage.js","names":[],"sources":["../../../src/auth/pages/SsoLoginPage.tsx"],"sourcesContent":["import { useState, useEffect } from \"react\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { useNavigate, useSearchParams } from \"react-router\";\nimport { useSsoOperations } from \"../hooks/useSsoOperations\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { PagePurpose } from \"@burdenoff/fe-libs/ui\";\nimport { EmailIcon, SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\n\ntype SsoMethod = \"saml\" | \"oidc\";\n\n/**\n * SSO Login Page\n * Allows users to enter their email/company domain to initiate SSO login\n * Supports both SAML 2.0 and OIDC authentication methods\n */\nexport function SsoLoginPage() {\n const tr = useTr();\n\n const navigate = useNavigate();\n const [searchParams] = useSearchParams();\n const tenantFromUrl = searchParams.get(\"tenant\");\n const methodFromUrl = searchParams.get(\"method\") as SsoMethod | null;\n const {\n initiateSsoLogin,\n initiateExternalOidcLogin,\n isGeneratingRequest,\n isGeneratingOidcUrl,\n } = useSsoOperations(tenantFromUrl ?? undefined);\n\n const [email, setEmail] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [ssoMethod, setSsoMethod] = useState<SsoMethod>(\"oidc\");\n const [isInitiating, setIsInitiating] = useState(false);\n const [isSsoNotConfigured, setIsSsoNotConfigured] = useState(false);\n\n // Set method from URL if provided\n useEffect(() => {\n if (methodFromUrl === \"saml\" || methodFromUrl === \"oidc\") {\n setSsoMethod(methodFromUrl);\n }\n }, [methodFromUrl]);\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setIsSsoNotConfigured(false);\n setIsInitiating(true);\n\n try {\n // Extract domain from email\n const domain = email.split(\"@\")[1];\n if (!domain) {\n setError(\n tr(\n \"auth.ssoLogin.invalidEmailDomain\",\n \"Please enter a valid email address with your company domain\",\n ),\n );\n setIsInitiating(false);\n return;\n }\n\n // In a real app, you would look up the tenant by domain\n // For now, we'll use the tenant from URL or the domain itself\n const tenantId = tenantFromUrl || domain;\n\n // Store email for post-login\n sessionStorage.setItem(\"sso_email\", email);\n\n if (ssoMethod === \"oidc\") {\n // External OIDC flow (Azure AD, Google, etc.)\n await initiateExternalOidcLogin(tenantId, \"/dashboard\");\n } else {\n await initiateSsoLogin(tenantId, \"/dashboard\");\n }\n } catch (err) {\n console.error(\"SSO login failed:\", err);\n const errorMessage =\n err instanceof Error\n ? err.message\n : \"Failed to initiate SSO login. Please check your configuration.\";\n\n // Check if error is about SSO not being configured\n if (\n errorMessage.toLowerCase().includes(\"sso\") &&\n (errorMessage.toLowerCase().includes(\"not configured\") ||\n errorMessage.toLowerCase().includes(\"not set up\"))\n ) {\n setIsSsoNotConfigured(true);\n setError(\n tr(\n \"auth.ssoLogin.ssoNotConfigured\",\n \"SSO is not configured for your organization. Please use regular email/password login or contact your administrator to set up SSO.\",\n ),\n );\n } else {\n setError(errorMessage);\n }\n\n setIsInitiating(false);\n }\n };\n\n const isSubmitting =\n isGeneratingRequest || isGeneratingOidcUrl || isInitiating;\n\n return (\n <AuthLayout\n title={tr(\"auth.ssoLogin.title\", \"Enterprise SSO\")}\n subtitle={tr(\n \"auth.ssoLogin.subtitle\",\n \"Sign in with your company's identity provider\",\n )}\n >\n <PagePurpose className=\"mb-5\">\n {tr(\n \"auth.ssoLogin.purpose\",\n \"Sign in through your company's identity provider (Okta, Azure AD, Google, and more). Enter your work email and we'll route you to your organization's OIDC or SAML login.\",\n )}\n </PagePurpose>\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Error Alert */}\n {error && (\n <div\n className={`flex items-start gap-3 p-4 rounded-xl border ${\n isSsoNotConfigured\n ? \"bg-status-warning-bg-subtle border-status-warning-border\"\n : \"bg-status-error-bg-subtle border-status-error-border\"\n }`}\n >\n <AlertIcon\n className={`size-5 flex-shrink-0 mt-0.5 ${\n isSsoNotConfigured\n ? \"text-status-warning-text\"\n : \"text-status-error-text\"\n }`}\n />\n <div className=\"flex-1\">\n <p\n className={`text-sm ${\n isSsoNotConfigured\n ? \"text-status-warning-text\"\n : \"text-status-error-text\"\n }`}\n >\n {error}\n </p>\n {isSsoNotConfigured && (\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/login\", { state: { email } })}\n className=\"mt-3 inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-status-warning-bg-subtle hover:bg-status-warning-bg-subtle text-status-warning-text text-sm font-semibold transition-all\"\n >\n <svg\n className=\"size-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1\"\n />\n </svg>\n {tr(\n \"auth.ssoLogin.useEmailLogin\",\n \"Use Email/Password Login Instead\",\n )}\n </button>\n )}\n </div>\n </div>\n )}\n\n {/* SSO Method Toggle */}\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-[var(--color-text-primary)]\">\n {tr(\"auth.ssoLogin.authMethod\", \"Authentication Method\")}\n </label>\n <div className=\"grid grid-cols-2 gap-3\">\n <button\n type=\"button\"\n onClick={() => setSsoMethod(\"oidc\")}\n className={`p-4 rounded-xl border-2 transition-all ${\n ssoMethod === \"oidc\"\n ? \"border-action-primary-bg bg-status-info-bg-subtle\"\n : \"border-border-subtle hover:border-border-default\"\n }`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`size-10 rounded-lg flex items-center justify-center ${\n ssoMethod === \"oidc\"\n ? \"bg-status-info-bg-subtle0\"\n : \"bg-bg-sunken\"\n }`}\n >\n <svg\n className={`size-5 ${ssoMethod === \"oidc\" ? \"text-white\" : \"text-text-secondary\"}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9\"\n />\n </svg>\n </div>\n <div className=\"text-left\">\n <div\n className={`font-medium ${ssoMethod === \"oidc\" ? \"text-text-linkHover\" : \"text-text-primary\"}`}\n >\n OpenID Connect\n </div>\n <div className=\"text-xs text-text-secondary\">\n {tr(\n \"auth.ssoLogin.modernRecommended\",\n \"Modern & Recommended\",\n )}\n </div>\n </div>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => setSsoMethod(\"saml\")}\n className={`p-4 rounded-xl border-2 transition-all ${\n ssoMethod === \"saml\"\n ? \"border-accent-purple bg-accent-purple-subtle\"\n : \"border-border-subtle hover:border-border-default\"\n }`}\n >\n <div className=\"flex items-center gap-3\">\n <div\n className={`size-10 rounded-lg flex items-center justify-center ${\n ssoMethod === \"saml\"\n ? \"bg-accent-purple-subtle0\"\n : \"bg-bg-sunken\"\n }`}\n >\n <svg\n className={`size-5 ${ssoMethod === \"saml\" ? \"text-white\" : \"text-text-secondary\"}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div className=\"text-left\">\n <div\n className={`font-medium ${ssoMethod === \"saml\" ? \"text-accent-purple\" : \"text-text-primary\"}`}\n >\n SAML 2.0\n </div>\n <div className=\"text-xs text-text-secondary\">\n {tr(\"auth.ssoLogin.enterpriseLegacy\", \"Enterprise Legacy\")}\n </div>\n </div>\n </div>\n </button>\n </div>\n </div>\n\n {/* Info Banner */}\n <div\n className={`p-4 rounded-xl border ${\n ssoMethod === \"oidc\"\n ? \"bg-status-info-bg-subtle border-status-info-border\"\n : \"bg-accent-purple-subtle border-accent-purple-subtle\"\n }`}\n >\n <p\n className={`text-sm ${\n ssoMethod === \"oidc\"\n ? \"text-status-info-text\"\n : \"text-accent-purple\"\n }`}\n >\n {ssoMethod === \"oidc\"\n ? tr(\n \"auth.sso.oidcInfoBannerPkce\",\n \"Sign in using OpenID Connect with your identity provider. Supports modern SSO with PKCE security.\",\n )\n : tr(\n \"auth.sso.samlInfoBanner\",\n \"Sign in using SAML 2.0 with your enterprise identity provider (Okta, Azure AD, etc.).\",\n )}\n </p>\n </div>\n\n {/* Email Input */}\n <div className=\"space-y-2\">\n <label\n htmlFor=\"email\"\n className=\"block text-sm font-medium text-[var(--color-text-primary)]\"\n >\n {tr(\"auth.ssoLogin.workEmail\", \"Work Email Address\")}\n </label>\n <div className=\"relative\">\n <div className=\"absolute inset-y-0 left-0 pl-3.5 flex items-center pointer-events-none\">\n <EmailIcon className=\"size-5 text-[var(--color-text-tertiary)]\" />\n </div>\n <input\n id=\"email\"\n type=\"email\"\n required\n aria-required=\"true\"\n aria-label={tr(\"auth.ssoLogin.workEmail\", \"Work Email Address\")}\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n autoComplete=\"email\"\n className=\"block w-full pl-[3.5rem] pr-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] placeholder:text-[var(--color-text-tertiary)] focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all\"\n placeholder={tr(\n \"auth.ssoLogin.emailPlaceholder\",\n \"you@company.com\",\n )}\n />\n </div>\n <p className=\"text-xs text-[var(--color-text-tertiary)]\">\n {tr(\n \"auth.ssoLogin.useCompanyEmail\",\n \"Use your company email (e.g., @yourcompany.com)\",\n )}\n </p>\n </div>\n\n {/* Submit Button */}\n <Button\n type=\"submit\"\n disabled={isSubmitting || !email}\n variant=\"default\"\n size=\"lg\"\n className={`w-full font-semibold ${\n ssoMethod === \"saml\"\n ? \"bg-accent-purple text-white hover:bg-accent-purple hover:opacity-90\"\n : \"\"\n }`}\n >\n {isSubmitting ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.sso.redirecting\", \"Redirecting...\")}</span>\n </>\n ) : (\n <>\n <svg\n className=\"size-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1\"\n />\n </svg>\n <span>\n {ssoMethod === \"oidc\"\n ? tr(\"auth.sso.continueWithOidc\", \"Continue with OIDC\")\n : tr(\"auth.sso.continueWithSaml\", \"Continue with SAML\")}\n </span>\n </>\n )}\n </Button>\n </form>\n\n {/* Back to Regular Login */}\n <div className=\"mt-6 text-center\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/login\")}\n className=\"text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors\"\n >\n <span className=\"font-semibold text-text-link hover:text-text-linkHover\">\n {tr(\"auth.ssoLogin.backToLogin\", \"Back to regular login\")}\n </span>\n </button>\n </div>\n\n {/* Reactivate Account Link */}\n <div className=\"mt-4 text-center\">\n <button\n type=\"button\"\n onClick={() => navigate(\"/auth/reactivate\")}\n className=\"text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)] transition-colors\"\n >\n {tr(\n \"auth.ssoLogin.deactivatedAccount\",\n \"Have a deactivated account?\",\n )}{\" \"}\n <span className=\"font-semibold text-status-success-text hover:text-status-success-text\">\n {tr(\"auth.ssoLogin.reactivateIt\", \"Reactivate it\")}\n </span>\n </button>\n </div>\n\n {/* Help Text */}\n <div className=\"mt-6 p-4 rounded-xl bg-bg-canvas/50 border border-border-subtle\">\n <h4 className=\"text-sm font-medium text-[var(--color-text-primary)] mb-2\">\n {tr(\"auth.ssoLogin.noSso\", \"Don't see your company's SSO?\")}\n </h4>\n <p className=\"text-xs text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.ssoLogin.contactIT\",\n \"Contact your IT administrator to set up SSO for your organization. They'll need to configure your identity provider with our service.\",\n )}\n </p>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|