@luminaryworks/auth-react 0.4.4 → 0.5.0

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/README.md CHANGED
@@ -43,6 +43,16 @@ Override layout via `className` / `style` on the root.
43
43
  // socialProviders: "auto" | ["google","github"] | []
44
44
  />
45
45
 
46
+ // Desktop / mobile native shell — Google/GitHub in the system browser (RFC 8252)
47
+ <HeadlessLoginPanel
48
+ config={idpConfig}
49
+ productName="VistaRemote"
50
+ mode="external"
51
+ openExternalUrl={(url) => window.nativeShell.openExternal(url)}
52
+ // Password Headless stays in-app; social/SSO open the OS browser.
53
+ // Register redirect_uri as http://127.0.0.1:<port>/auth/callback or app://…
54
+ />
55
+
46
56
  // Admin / internal console — hide Experience social connectors
47
57
  <HeadlessLoginPanel
48
58
  config={idpConfig}
@@ -54,11 +64,15 @@ Override layout via `className` / `style` on the root.
54
64
 
55
65
  | Prop | Default | Notes |
56
66
  |------|---------|--------|
67
+ | `mode` | `"popup"` | `"redirect"` SPA full-page; `"external"` system browser for social/SSO (needs `openExternalUrl`) |
68
+ | `openExternalUrl` | — | Required for `mode="external"`. Electron: `shell.openExternal`; RN: Custom Tabs / ASWebAuthenticationSession |
57
69
  | `showSocialConnectors` | `true` | `false` skips fetch and hides divider + social buttons |
58
70
  | `socialProviders` | `"auto"` | allowlist, or `[]` (same effect as `showSocialConnectors={false}`) |
59
71
  | `experienceAdapter` | catalog default | optional custom `LoginExperienceAdapter`; otherwise `config.iamProvider` |
60
72
  | `config.iamProvider` | `logto` | `logto` Headless; `oidc` / `zitadel` Hosted Redirect |
61
73
 
74
+ **Desktop callback:** Logto redirects the *system browser* to your loopback `redirect_uri`. The native shell must detect that request, focus the app window onto the same URL (so PKCE `localStorage` matches), and show Chrome a “you can close this tab” page. See VistaRemote Electron `serve-renderer-static` + Viewer preload.
75
+
62
76
  IdP hosted `/sign-in` social row layout: `node scripts/apply-branding.mjs` (customCss wrap). Enable connectors: `ensure-sign-in-experience.mjs` + `verify-social-direct-signin.mjs`.
63
77
 
64
78
  ### Login experience adapters
package/dist/index.css CHANGED
@@ -48,6 +48,55 @@
48
48
  display: grid;
49
49
  gap: 10px;
50
50
  }
51
+ .HeadlessLoginPanel_module_channelTabs {
52
+ display: grid;
53
+ grid-template-columns: 1fr 1fr;
54
+ gap: 6px;
55
+ margin-bottom: 2px;
56
+ }
57
+ .HeadlessLoginPanel_module_channelTab {
58
+ border: 1px solid #c9d5de;
59
+ border-radius: 10px;
60
+ padding: 8px 10px;
61
+ font-size: 13px;
62
+ font-weight: 650;
63
+ cursor: pointer;
64
+ color: #4b5c68;
65
+ background: #f7fafc;
66
+ }
67
+ .HeadlessLoginPanel_module_channelTab:disabled {
68
+ opacity: 0.65;
69
+ cursor: not-allowed;
70
+ }
71
+ .HeadlessLoginPanel_module_channelTabActive {
72
+ color: var(--lw-auth-theme-deep);
73
+ border-color: var(--lw-auth-theme);
74
+ background: color-mix(in srgb, var(--lw-auth-theme) 10%, #fff);
75
+ }
76
+ .HeadlessLoginPanel_module_codeRow {
77
+ display: grid;
78
+ grid-template-columns: 1fr auto;
79
+ gap: 8px;
80
+ align-items: stretch;
81
+ }
82
+ .HeadlessLoginPanel_module_codeInput {
83
+ min-width: 0;
84
+ }
85
+ .HeadlessLoginPanel_module_secondaryBtn {
86
+ border: 1px solid #b7c9d4;
87
+ border-radius: 10px;
88
+ padding: 0 12px;
89
+ font-size: 13px;
90
+ font-weight: 650;
91
+ cursor: pointer;
92
+ color: #14212b;
93
+ background: #fff;
94
+ white-space: nowrap;
95
+ }
96
+ .HeadlessLoginPanel_module_secondaryBtn:disabled {
97
+ opacity: 0.65;
98
+ cursor: not-allowed;
99
+ }
51
100
  .HeadlessLoginPanel_module_socialStack {
52
101
  display: flex;
53
102
  flex-wrap: wrap;
@@ -201,6 +250,32 @@
201
250
  color: #6b7c87;
202
251
  line-height: 1.45;
203
252
  }
253
+ .HeadlessLoginPanel_module_domainsHint {
254
+ margin: -2px 0 0;
255
+ font-size: 12px;
256
+ line-height: 1.45;
257
+ color: #4b5c68;
258
+ word-break: break-word;
259
+ }
260
+ .HeadlessLoginPanel_module_switchMode {
261
+ margin: 12px 0 0;
262
+ text-align: center;
263
+ }
264
+ .HeadlessLoginPanel_module_switchModeBtn {
265
+ border: none;
266
+ background: transparent;
267
+ color: var(--lw-auth-theme);
268
+ font-size: 13px;
269
+ font-weight: 650;
270
+ cursor: pointer;
271
+ padding: 4px 8px;
272
+ text-decoration: underline;
273
+ text-underline-offset: 3px;
274
+ }
275
+ .HeadlessLoginPanel_module_switchModeBtn:disabled {
276
+ opacity: 0.65;
277
+ cursor: not-allowed;
278
+ }
204
279
  .HeadlessLoginPanel_module_error {
205
280
  margin: 12px 0 0;
206
281
  font-size: 13px;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.panel {\n --lw-auth-theme: #1677ff;\n --lw-auth-theme-deep: color-mix(in srgb, var(--lw-auth-theme) 72%, #000);\n width: min(100%, 400px);\n padding: 28px 28px 22px;\n border-radius: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.product {\n margin: 0;\n font-size: 13px;\n font-weight: 650;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--lw-auth-theme);\n}\n\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.passwordToggle {\n position: absolute;\n right: 4px;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialBtn {\n flex: 1 1 calc(50% - 5px);\n min-width: min(140px, 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: 1px solid $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\n background: color-mix(in srgb, var(--lw-auth-theme) 14%, #fff);\n color: var(--lw-auth-theme-deep);\n font-size: 11px;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.cancelBtn {\n margin-top: 10px;\n width: 100%;\n border: none;\n background: transparent;\n color: #5a6b76;\n font-size: 13px;\n cursor: pointer;\n padding: 8px;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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","names":["panel","brand","logo","product","title","subtitle","form","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","error","footer"]}
1
+ {"version":3,"sources":["../src/HeadlessLoginPanel.module.scss"],"sourcesContent":["$ink: #14212b;\n$muted: #4b5c68;\n$hint: #6b7c87;\n$brand: #3d6f8f;\n$brand-deep: #15485c;\n$brand-mid: #1f6f8b;\n$border: #c9d5de;\n$border-soft: #b7c9d4;\n$line: #d5e0e7;\n$divider: #90a0ab;\n$surface: #f7fafc;\n$fallback-bg: #e8eef2;\n$danger: #b42318;\n$footer-line: #e4ebf0;\n$radius-lg: 16px;\n$radius-md: 10px;\n$radius-sm: 4px;\n\n.panel {\n --lw-auth-theme: #1677ff;\n --lw-auth-theme-deep: color-mix(in srgb, var(--lw-auth-theme) 72%, #000);\n width: min(100%, 400px);\n padding: 28px 28px 22px;\n border-radius: $radius-lg;\n background: rgba(255, 255, 255, 0.96);\n color: $ink;\n box-shadow: 0 24px 64px rgba(15, 23, 42, 0.28);\n font-family: \"Segoe UI\", \"PingFang SC\", \"Noto Sans SC\", sans-serif;\n}\n\n.brand {\n display: flex;\n gap: 14px;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.logo {\n border-radius: 12px;\n display: block;\n}\n\n.product {\n margin: 0;\n font-size: 13px;\n font-weight: 650;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--lw-auth-theme);\n}\n\n.title {\n margin: 2px 0 0;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.subtitle {\n margin: 0 0 18px;\n font-size: 14px;\n line-height: 1.5;\n color: $muted;\n}\n\n.form {\n display: grid;\n gap: 10px;\n}\n\n.channelTabs {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n margin-bottom: 2px;\n}\n\n.channelTab {\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 8px 10px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: $muted;\n background: $surface;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.channelTabActive {\n color: var(--lw-auth-theme-deep);\n border-color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 10%, #fff);\n}\n\n.codeRow {\n display: grid;\n grid-template-columns: 1fr auto;\n gap: 8px;\n align-items: stretch;\n}\n\n.codeInput {\n min-width: 0;\n}\n\n.secondaryBtn {\n border: 1px solid $border-soft;\n border-radius: $radius-md;\n padding: 0 12px;\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n white-space: nowrap;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialStack {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n font-size: 12px;\n}\n\n.input {\n width: 100%;\n box-sizing: border-box;\n border: 1px solid $border;\n border-radius: $radius-md;\n padding: 10px 12px;\n font-size: 14px;\n outline: none;\n background: $surface;\n\n &:focus {\n border-color: var(--lw-auth-theme);\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.passwordField {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.passwordInput {\n padding-right: 42px;\n}\n\n.passwordToggle {\n position: absolute;\n right: 4px;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: $radius-sm;\n padding: 0;\n color: #5a6b76;\n background: transparent;\n cursor: pointer;\n\n &:hover:not(:disabled) {\n color: var(--lw-auth-theme);\n background: color-mix(in srgb, var(--lw-auth-theme) 12%, transparent);\n }\n\n &:focus-visible {\n outline: 2px solid var(--lw-auth-theme);\n outline-offset: 1px;\n }\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.primaryBtn {\n border: none;\n border-radius: $radius-md;\n padding: 11px 14px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: #fff;\n background: linear-gradient(135deg, var(--lw-auth-theme) 0%, var(--lw-auth-theme-deep) 100%);\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialBtn {\n flex: 1 1 calc(50% - 5px);\n min-width: min(140px, 100%);\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n border: 1px solid $border-soft;\n border-radius: $radius-md;\n padding: 11px 10px;\n font-size: 14px;\n font-weight: 650;\n cursor: pointer;\n color: $ink;\n background: #fff;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.socialLogo {\n flex-shrink: 0;\n display: block;\n}\n\n.logoFallback {\n width: 18px;\n height: 18px;\n border-radius: $radius-sm;\n background: color-mix(in srgb, var(--lw-auth-theme) 14%, #fff);\n color: var(--lw-auth-theme-deep);\n font-size: 11px;\n font-weight: 700;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.cancelBtn {\n margin-top: 10px;\n width: 100%;\n border: none;\n background: transparent;\n color: #5a6b76;\n font-size: 13px;\n cursor: pointer;\n padding: 8px;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.divider {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 14px 0;\n color: $divider;\n}\n\n.dividerLine {\n flex: 1;\n height: 1px;\n background: $line;\n}\n\n.dividerText {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n}\n\n.hint {\n margin: 10px 0 0;\n font-size: 12px;\n color: $hint;\n line-height: 1.45;\n}\n\n.domainsHint {\n margin: -2px 0 0;\n font-size: 12px;\n line-height: 1.45;\n color: $muted;\n word-break: break-word;\n}\n\n.switchMode {\n margin: 12px 0 0;\n text-align: center;\n}\n\n.switchModeBtn {\n border: none;\n background: transparent;\n color: var(--lw-auth-theme);\n font-size: 13px;\n font-weight: 650;\n cursor: pointer;\n padding: 4px 8px;\n text-decoration: underline;\n text-underline-offset: 3px;\n\n &:disabled {\n opacity: 0.65;\n cursor: not-allowed;\n }\n}\n\n.error {\n margin: 12px 0 0;\n font-size: 13px;\n color: $danger;\n line-height: 1.4;\n}\n\n.footer {\n margin-top: 18px;\n padding-top: 12px;\n border-top: 1px solid $footer-line;\n font-size: 12px;\n color: $hint;\n display: flex;\n gap: 8px;\n justify-content: center;\n}\n"],"mappings":"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","names":["panel","brand","logo","product","title","subtitle","form","channelTabs","channelTab","channelTabActive","codeRow","codeInput","secondaryBtn","socialStack","input","passwordField","passwordInput","passwordToggle","primaryBtn","socialBtn","socialLogo","logoFallback","cancelBtn","divider","dividerLine","dividerText","hint","domainsHint","switchMode","switchModeBtn","error","footer"]}
package/dist/index.d.ts CHANGED
@@ -100,6 +100,8 @@ declare const LOGIN_EXPERIENCE_CAPABILITIES: {
100
100
  readonly passwordSignIn: "password-sign-in";
101
101
  /** Username + password self-register via Experience (Logto NewPasswordIdentity). */
102
102
  readonly passwordSignUp: "password-sign-up";
103
+ /** Email + verification code + password self-register. */
104
+ readonly emailCodeSignUp: "email-code-sign-up";
103
105
  readonly socialConnectors: "social-connectors";
104
106
  readonly socialDirectSignIn: "social-direct-sign-in";
105
107
  };
@@ -126,8 +128,42 @@ interface ExperiencePasswordSignInResult {
126
128
  raw?: unknown;
127
129
  }
128
130
  /** Same OIDC bootstrap fields as sign-in; username must match Logto username rules. */
129
- type ExperiencePasswordSignUpInput = ExperiencePasswordSignInInput;
131
+ type ExperiencePasswordSignUpInput = ExperiencePasswordSignInInput & {
132
+ /** Optional CAPTCHA token for Logto bot protection (Turnstile / reCAPTCHA). */
133
+ captchaToken?: string;
134
+ };
130
135
  type ExperiencePasswordSignUpResult = ExperiencePasswordSignInResult;
136
+ interface ExperienceEmailSignUpSendCodeInput {
137
+ apiBase: string;
138
+ email: string;
139
+ /** @deprecated alias of email */
140
+ identifier?: string;
141
+ captchaToken?: string;
142
+ issuer?: string;
143
+ clientId?: string;
144
+ redirectUri?: string;
145
+ audience?: string;
146
+ scopes?: string;
147
+ returnUrl?: string;
148
+ }
149
+ interface ExperienceEmailSignUpSendCodeResult {
150
+ verificationId: string;
151
+ }
152
+ interface ExperienceEmailSignUpCompleteInput {
153
+ apiBase: string;
154
+ email: string;
155
+ password: string;
156
+ code: string;
157
+ verificationId: string;
158
+ identifier?: string;
159
+ captchaToken?: string;
160
+ issuer?: string;
161
+ clientId?: string;
162
+ redirectUri?: string;
163
+ audience?: string;
164
+ scopes?: string;
165
+ returnUrl?: string;
166
+ }
131
167
  interface ExperienceSocialConnector {
132
168
  id: string;
133
169
  target: string;
@@ -158,6 +194,8 @@ interface LoginExperienceAdapter {
158
194
  * Email/phone sign-up needs verification codes — not covered by this method.
159
195
  */
160
196
  experiencePasswordSignUp?(input: ExperiencePasswordSignUpInput): Promise<ExperiencePasswordSignUpResult>;
197
+ sendRegisterEmailCode?(input: ExperienceEmailSignUpSendCodeInput): Promise<ExperienceEmailSignUpSendCodeResult>;
198
+ experienceEmailPasswordSignUp?(input: ExperienceEmailSignUpCompleteInput): Promise<ExperiencePasswordSignUpResult>;
161
199
  fetchSocialConnectors?(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
162
200
  createSocialSignInRequest?(target: string): SocialSignInRequest;
163
201
  }
@@ -180,6 +218,76 @@ declare function resolveLoginExperienceAdapter(adapter?: LoginExperienceAdapter
180
218
  /** `VITE_IAM_PROVIDER` / `IAM_PROVIDER` / older `IDP_MODE`. */
181
219
  declare function resolveLoginExperienceProviderFromEnv(env?: Record<string, string | undefined>): LoginExperienceProvider;
182
220
 
221
+ /**
222
+ * Self-register email policy for early ToC / hosted SaaS.
223
+ *
224
+ * Why allowlist: disposable / game / temporary mailboxes drive bot farms and
225
+ * verification-email cost. Early stage: only well-known consumer providers.
226
+ * Enterprise / private: set mode `off` or extend allowlist with corporate domains.
227
+ */
228
+ /** Popular consumer inboxes (CN + global). Lowercase host only. */
229
+ declare const DEFAULT_REGISTER_EMAIL_ALLOWLIST: readonly string[];
230
+ /** Common disposable / throwaway hosts (used when mode is blocklist or as extra deny). */
231
+ declare const DEFAULT_DISPOSABLE_EMAIL_BLOCKLIST: readonly string[];
232
+ type RegisterEmailMode = "allowlist" | "blocklist" | "off";
233
+ interface RegisterEmailPolicy {
234
+ mode: RegisterEmailMode;
235
+ allowlist: readonly string[];
236
+ blocklist: readonly string[];
237
+ }
238
+ interface RegisterEmailPolicyInput {
239
+ mode?: string | null;
240
+ allowlist?: string | readonly string[] | null;
241
+ blocklist?: string | readonly string[] | null;
242
+ }
243
+ declare function normalizeRegisterEmailMode(raw: string | null | undefined): RegisterEmailMode;
244
+ declare function resolveRegisterEmailPolicy(input?: RegisterEmailPolicyInput): RegisterEmailPolicy;
245
+ /** Read VITE_/PUBLIC_/AUTH_REGISTER_* from a static env map (bundler-safe). */
246
+ declare function readRegisterEmailPolicyFromEnv(env?: Record<string, string | undefined>): RegisterEmailPolicy;
247
+ declare function emailDomain(email: string): string | null;
248
+ declare function isValidEmailShape(email: string): boolean;
249
+ type RegisterEmailDecision = {
250
+ ok: true;
251
+ domain: string;
252
+ } | {
253
+ ok: false;
254
+ reason: "invalid" | "not_allowed" | "disposable";
255
+ domain?: string;
256
+ };
257
+ /**
258
+ * Enforce register email policy. `off` still rejects disposable hosts when
259
+ * `blocklist` is non-empty (defense in depth); pass `blocklist: []` to disable.
260
+ */
261
+ declare function evaluateRegisterEmail(email: string, policy?: RegisterEmailPolicy): RegisterEmailDecision;
262
+ declare function registerEmailRejectionMessage(decision: RegisterEmailDecision): string;
263
+ /**
264
+ * Human-readable domain list for the register form (allowlist mode only).
265
+ * Returns null when domains are not restricted to an allowlist.
266
+ */
267
+ declare function formatAllowedEmailDomains(policy: RegisterEmailPolicy, options?: {
268
+ max?: number;
269
+ }): string | null;
270
+ /** Short policy note under the email field on the register form. */
271
+ declare function registerEmailDomainsHint(policy: RegisterEmailPolicy, labels?: {
272
+ allowedDomainsPrefix?: string;
273
+ allowedDomainsOpen?: string;
274
+ allowedDomainsBlocklist?: string;
275
+ }): string | null;
276
+ /** Public policy document from Auth Gateway `GET /api/register-policy`. */
277
+ interface PublicRegisterPolicyResponse {
278
+ mode?: string;
279
+ allowlist?: string[];
280
+ blocklist?: string[];
281
+ ipDailyLimit?: number;
282
+ codeHourlyLimit?: number;
283
+ enabled?: boolean;
284
+ }
285
+ /**
286
+ * Fetch live register policy from Auth Gateway (or any host that serves `/api/register-policy`).
287
+ * Falls back to built-in defaults when the endpoint is missing.
288
+ */
289
+ declare function fetchRegisterEmailPolicy(apiBase: string, init?: RequestInit): Promise<RegisterEmailPolicy>;
290
+
183
291
  /**
184
292
  * Logto Experience API (Headless) adapter.
185
293
  * Prefer same-origin Experience base (SPA proxies /api/experience) so cookies
@@ -198,12 +306,15 @@ declare function createLogtoDirectSignInRequest(directSignIn: string): SocialSig
198
306
  declare class LogtoExperienceAdapter implements LoginExperienceAdapter {
199
307
  readonly provider = "logto";
200
308
  readonly capabilities: readonly LoginExperienceCapability[];
309
+ emailPolicy: RegisterEmailPolicy;
201
310
  experiencePasswordSignIn(input: ExperiencePasswordSignInInput): Promise<ExperiencePasswordSignInResult>;
202
311
  /**
203
312
  * Register with username + password via NewPasswordIdentity.
204
313
  * Email/phone self-register requires verification codes — use social or invite instead.
205
314
  */
206
315
  experiencePasswordSignUp(input: ExperiencePasswordSignUpInput): Promise<ExperiencePasswordSignUpResult>;
316
+ sendRegisterEmailCode(input: ExperienceEmailSignUpSendCodeInput): Promise<ExperienceEmailSignUpSendCodeResult>;
317
+ experienceEmailPasswordSignUp(input: ExperienceEmailSignUpCompleteInput): Promise<ExperiencePasswordSignUpResult>;
207
318
  fetchSocialConnectors(input: FetchSocialConnectorsInput): Promise<ExperienceSocialConnector[]>;
208
319
  createSocialSignInRequest(target: string): SocialSignInRequest;
209
320
  }
@@ -338,6 +449,25 @@ interface HeadlessLoginLabels {
338
449
  /** Switch link when on register: "Already have an account? Sign in" */
339
450
  loginLink?: string;
340
451
  passwordMismatch?: string;
452
+ registerTitle?: string;
453
+ registerSubtitle?: string;
454
+ registerWithEmail?: string;
455
+ registerWithUsername?: string;
456
+ emailPlaceholder?: string;
457
+ verificationCodePlaceholder?: string;
458
+ sendCode?: string;
459
+ resendCode?: string;
460
+ /** Prefix before the allowlisted domain list, e.g. "Allowed email domains". */
461
+ allowedDomainsPrefix?: string;
462
+ /** Shown when mode is off / unrestricted (aside from disposable blocklist). */
463
+ allowedDomainsOpen?: string;
464
+ /** Shown when only disposable domains are blocked. */
465
+ allowedDomainsBlocklist?: string;
466
+ /**
467
+ * Desktop/mobile system-browser social login: tell the user to finish in the browser
468
+ * and return to the app (loopback / deep link callback).
469
+ */
470
+ waitingExternalBrowser?: string;
341
471
  }
342
472
  interface HeadlessLoginPanelProps {
343
473
  config: Partial<LuminaryIdpConfig>;
@@ -348,8 +478,13 @@ interface HeadlessLoginPanelProps {
348
478
  logoSrc?: string;
349
479
  labels?: HeadlessLoginLabels;
350
480
  returnUrl?: string;
351
- /** Prefer popup (default) for reauth; use redirect for full-page login. */
352
- mode?: "popup" | "redirect";
481
+ /** Prefer popup (default) for reauth; redirect for full-page SPA; external for desktop/mobile system browser (RFC 8252). */
482
+ mode?: "popup" | "redirect" | "external";
483
+ /**
484
+ * Open an authorize URL in the OS browser / Custom Tabs / ASWebAuthenticationSession.
485
+ * Required when `mode="external"` (Google / GitHub / hosted SSO). Password Headless stays in-app.
486
+ */
487
+ openExternalUrl?: (url: string) => void | Promise<void>;
353
488
  /**
354
489
  * Show Experience social connectors (Google / GitHub / …).
355
490
  * Default `true`. Set `false` for admin / internal consoles that only allow
@@ -359,11 +494,26 @@ interface HeadlessLoginPanelProps {
359
494
  */
360
495
  showSocialConnectors?: boolean;
361
496
  /**
362
- * Show self-register switch + register form (username + password via Experience).
497
+ * Show self-register switch + register form.
363
498
  * Default `true` for end-user product logins. Set `false` for admin / ops consoles.
364
- * Hosted OIDC adapters without passwordSignUp hide register automatically.
365
499
  */
366
500
  showRegister?: boolean;
501
+ /**
502
+ * Email domain policy for self-register.
503
+ * If omitted, the panel loads `GET {experienceApiBase}/api/register-policy` when available,
504
+ * otherwise uses built-in consumer allowlist defaults.
505
+ */
506
+ registerEmailPolicy?: RegisterEmailPolicy;
507
+ /**
508
+ * When true (default), fetch live policy from Auth Gateway `/api/register-policy`.
509
+ * Set false to use only `registerEmailPolicy` / built-in defaults (e.g. local auth-dev-proxy).
510
+ */
511
+ fetchRegisterPolicy?: boolean;
512
+ /**
513
+ * Optional CAPTCHA token provider (Cloudflare Turnstile / reCAPTCHA).
514
+ * Token is sent as `captchaToken` on Experience Register init when Logto bot protection is on.
515
+ */
516
+ getCaptchaToken?: () => Promise<string | undefined>;
367
517
  /**
368
518
  * Social providers (when `showSocialConnectors` is not `false`):
369
519
  * - omit / `"auto"` — load enabled connectors from IdP (google, github, x, …)
@@ -391,7 +541,7 @@ interface HeadlessLoginPanelProps {
391
541
  }
392
542
  /** Shared default accent for product login panels (shared/brand --lw-primary). */
393
543
  declare const DEFAULT_LOGIN_THEME_COLOR = "#1677ff";
394
- declare function HeadlessLoginPanel({ config, experienceAdapter: experienceAdapterProp, productName, logoSrc, labels: labelsProp, returnUrl, mode, showSocialConnectors, showRegister, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
544
+ declare function HeadlessLoginPanel({ config, experienceAdapter: experienceAdapterProp, productName, logoSrc, labels: labelsProp, returnUrl, mode, openExternalUrl, showSocialConnectors, showRegister, registerEmailPolicy: registerEmailPolicyProp, fetchRegisterPolicy, getCaptchaToken, socialProviders, showCancel, onCancel, onOidcSession, onExperienceRedirect, footer, className, style, themeColor, }: HeadlessLoginPanelProps): react.JSX.Element;
395
545
 
396
546
  interface ReauthOverlayProps {
397
547
  config: Partial<LuminaryIdpConfig>;
@@ -454,4 +604,4 @@ declare function createPostLoginPathHelpers(options: PostLoginPathOptions): {
454
604
  isUnsafeReturnPath: (path: string) => boolean;
455
605
  };
456
606
 
457
- export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_LOGIN_THEME_COLOR, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperiencePasswordSignUpInput, type ExperiencePasswordSignUpResult, type ExperienceSocialConnector, type FetchSocialConnectorsInput, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, HostedOidcExperienceAdapter, LOGIN_EXPERIENCE_CAPABILITIES, type LoginExperienceAdapter, type LoginExperienceCapability, type LoginExperienceProvider, LogtoExperienceAdapter, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, ReauthOverlay, type ReauthOverlayProps, type SignInOptions, type SocialProviderTarget, type SocialSignInRequest, type UnauthorizedDisposition, authGate, clearStoredSession, createLoginExperienceAdapter, createLogtoDirectSignInRequest, createPostLoginPathHelpers, createUserManager, experiencePasswordSignIn, fetchSocialConnectors, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isLogtoRegisterUsername, isOidcPopupWindow, prepareSignInRequestUrl, readIdpConfigFromEnv, resetUserManager, resolveExperienceApiBase, resolveIssuer, resolveLoginExperienceAdapter, resolveLoginExperienceProviderFromEnv, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };
607
+ export { type AuthGateConfig, type AuthGatePhase, AuthGateProvider, type AuthGateProviderProps, type AuthGateSnapshot, DEFAULT_DISPOSABLE_EMAIL_BLOCKLIST, DEFAULT_LOGIN_THEME_COLOR, DEFAULT_REGISTER_EMAIL_ALLOWLIST, type ExperienceEmailSignUpCompleteInput, type ExperienceEmailSignUpSendCodeInput, type ExperienceEmailSignUpSendCodeResult, type ExperienceIdentifierType, type ExperiencePasswordSignInInput, type ExperiencePasswordSignInResult, type ExperiencePasswordSignUpInput, type ExperiencePasswordSignUpResult, type ExperienceSocialConnector, type FetchSocialConnectorsInput, type HeadlessLoginLabels, HeadlessLoginPanel, type HeadlessLoginPanelProps, HostedOidcExperienceAdapter, LOGIN_EXPERIENCE_CAPABILITIES, type LoginExperienceAdapter, type LoginExperienceCapability, type LoginExperienceProvider, LogtoExperienceAdapter, LuminaryAuthProvider, type LuminaryAuthProviderProps, type LuminaryAuthSession, type LuminaryIdpConfig, type PostLoginPathOptions, type PublicRegisterPolicyResponse, ReauthOverlay, type ReauthOverlayProps, type RegisterEmailDecision, type RegisterEmailMode, type RegisterEmailPolicy, type RegisterEmailPolicyInput, type SignInOptions, type SocialProviderTarget, type SocialSignInRequest, type UnauthorizedDisposition, authGate, clearStoredSession, createLoginExperienceAdapter, createLogtoDirectSignInRequest, createPostLoginPathHelpers, createUserManager, emailDomain, evaluateRegisterEmail, experiencePasswordSignIn, fetchRegisterEmailPolicy, fetchSocialConnectors, formatAllowedEmailDomains, getCurrentUser, getStoredAccessToken, handleSignInCallback, handleSignInPopupCallback, isIdpConfigured, isLogtoRegisterUsername, isOidcPopupWindow, isValidEmailShape, normalizeRegisterEmailMode, prepareSignInRequestUrl, readIdpConfigFromEnv, readRegisterEmailPolicyFromEnv, registerEmailDomainsHint, registerEmailRejectionMessage, resetUserManager, resolveExperienceApiBase, resolveIssuer, resolveLoginExperienceAdapter, resolveLoginExperienceProviderFromEnv, resolveRegisterEmailPolicy, sameOriginAuthorizeUrl, signInPopup, signInRedirect, signOutRedirect, useAuthGate, useAuthGateOptional, useLuminaryAuth, withAuthGateRetry };