@authon/js 0.3.1 → 0.3.3
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.cjs +102 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +102 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -149,10 +149,16 @@ var ModalRenderer = class {
|
|
|
149
149
|
selectedWallet = "";
|
|
150
150
|
overlayEmail = "";
|
|
151
151
|
overlayError = "";
|
|
152
|
+
// Turnstile CAPTCHA
|
|
153
|
+
captchaSiteKey = "";
|
|
154
|
+
turnstileWidgetId = null;
|
|
155
|
+
turnstileToken = "";
|
|
156
|
+
turnstileWrapper = null;
|
|
152
157
|
constructor(options) {
|
|
153
158
|
this.mode = options.mode;
|
|
154
159
|
this.theme = options.theme || "auto";
|
|
155
160
|
this.branding = { ...DEFAULT_BRANDING, ...options.branding };
|
|
161
|
+
this.captchaSiteKey = options.captchaSiteKey || "";
|
|
156
162
|
this.onProviderClick = options.onProviderClick;
|
|
157
163
|
this.onEmailSubmit = options.onEmailSubmit;
|
|
158
164
|
this.onClose = options.onClose;
|
|
@@ -190,6 +196,15 @@ var ModalRenderer = class {
|
|
|
190
196
|
document.removeEventListener("keydown", this.escHandler);
|
|
191
197
|
this.escHandler = null;
|
|
192
198
|
}
|
|
199
|
+
if (this.turnstileWidgetId !== null) {
|
|
200
|
+
window.turnstile?.remove(this.turnstileWidgetId);
|
|
201
|
+
this.turnstileWidgetId = null;
|
|
202
|
+
this.turnstileToken = "";
|
|
203
|
+
}
|
|
204
|
+
if (this.turnstileWrapper) {
|
|
205
|
+
this.turnstileWrapper.remove();
|
|
206
|
+
this.turnstileWrapper = null;
|
|
207
|
+
}
|
|
193
208
|
if (this.hostElement) {
|
|
194
209
|
this.hostElement.remove();
|
|
195
210
|
this.hostElement = null;
|
|
@@ -200,6 +215,15 @@ var ModalRenderer = class {
|
|
|
200
215
|
}
|
|
201
216
|
this.currentOverlay = "none";
|
|
202
217
|
}
|
|
218
|
+
getTurnstileToken() {
|
|
219
|
+
return this.turnstileToken;
|
|
220
|
+
}
|
|
221
|
+
resetTurnstile() {
|
|
222
|
+
if (this.turnstileWidgetId !== null) {
|
|
223
|
+
window.turnstile?.reset(this.turnstileWidgetId);
|
|
224
|
+
this.turnstileToken = "";
|
|
225
|
+
}
|
|
226
|
+
}
|
|
203
227
|
/** Update theme at runtime without destroying form state */
|
|
204
228
|
setTheme(theme) {
|
|
205
229
|
this.theme = theme;
|
|
@@ -398,10 +422,12 @@ var ModalRenderer = class {
|
|
|
398
422
|
</button>`;
|
|
399
423
|
}).join("") : "";
|
|
400
424
|
const divider = showProviders && b.showDivider !== false && b.showEmailPassword !== false ? `<div class="divider"><span>or</span></div>` : "";
|
|
425
|
+
const captchaContainer = this.captchaSiteKey ? '<div id="turnstile-container" style="display:flex;justify-content:center;margin:4px 0"></div>' : "";
|
|
401
426
|
const emailForm = b.showEmailPassword !== false ? `<form class="email-form" id="email-form">
|
|
402
427
|
<input type="email" placeholder="Email address" name="email" required class="input" autocomplete="email" />
|
|
403
428
|
<input type="password" placeholder="Password" name="password" required class="input" autocomplete="${isSignUp ? "new-password" : "current-password"}" />
|
|
404
429
|
${isSignUp ? '<p class="password-hint">Must contain uppercase, lowercase, and a number (min 8 chars)</p>' : ""}
|
|
430
|
+
${captchaContainer}
|
|
405
431
|
<button type="submit" class="submit-btn">${isSignUp ? "Sign up" : "Sign in"}</button>
|
|
406
432
|
</form>` : "";
|
|
407
433
|
const hasMethodAbove = showProviders && this.enabledProviders.length > 0 || b.showEmailPassword !== false;
|
|
@@ -458,6 +484,58 @@ var ModalRenderer = class {
|
|
|
458
484
|
${b.showSecuredBy !== false ? `<div class="secured-by">Secured by <a href="https://authon.dev" target="_blank" rel="noopener noreferrer" class="secured-link">Authon</a></div>` : ""}
|
|
459
485
|
`;
|
|
460
486
|
}
|
|
487
|
+
renderTurnstile() {
|
|
488
|
+
if (!this.captchaSiteKey || !this.shadowRoot) return;
|
|
489
|
+
const anchor = this.shadowRoot.getElementById("turnstile-container");
|
|
490
|
+
if (!anchor) return;
|
|
491
|
+
const w = window;
|
|
492
|
+
const positionWrapper = () => {
|
|
493
|
+
if (!this.turnstileWrapper || !anchor.isConnected) return;
|
|
494
|
+
const rect = anchor.getBoundingClientRect();
|
|
495
|
+
Object.assign(this.turnstileWrapper.style, {
|
|
496
|
+
position: "fixed",
|
|
497
|
+
top: `${rect.top}px`,
|
|
498
|
+
left: `${rect.left}px`,
|
|
499
|
+
width: `${rect.width}px`,
|
|
500
|
+
zIndex: "2147483647",
|
|
501
|
+
display: "flex",
|
|
502
|
+
justifyContent: "center"
|
|
503
|
+
});
|
|
504
|
+
};
|
|
505
|
+
const tryRender = () => {
|
|
506
|
+
if (!w.turnstile || !anchor.isConnected) return;
|
|
507
|
+
this.turnstileWrapper = document.createElement("div");
|
|
508
|
+
document.body.appendChild(this.turnstileWrapper);
|
|
509
|
+
positionWrapper();
|
|
510
|
+
this.turnstileWidgetId = w.turnstile.render(this.turnstileWrapper, {
|
|
511
|
+
sitekey: this.captchaSiteKey,
|
|
512
|
+
callback: (token) => {
|
|
513
|
+
this.turnstileToken = token;
|
|
514
|
+
},
|
|
515
|
+
"expired-callback": () => {
|
|
516
|
+
this.turnstileToken = "";
|
|
517
|
+
},
|
|
518
|
+
"error-callback": () => {
|
|
519
|
+
this.turnstileToken = "";
|
|
520
|
+
},
|
|
521
|
+
theme: this.isDark() ? "dark" : "light",
|
|
522
|
+
size: "flexible"
|
|
523
|
+
});
|
|
524
|
+
window.addEventListener("scroll", positionWrapper, { passive: true });
|
|
525
|
+
window.addEventListener("resize", positionWrapper, { passive: true });
|
|
526
|
+
};
|
|
527
|
+
if (w.turnstile) {
|
|
528
|
+
tryRender();
|
|
529
|
+
} else {
|
|
530
|
+
const interval = setInterval(() => {
|
|
531
|
+
if (w.turnstile) {
|
|
532
|
+
clearInterval(interval);
|
|
533
|
+
tryRender();
|
|
534
|
+
}
|
|
535
|
+
}, 200);
|
|
536
|
+
setTimeout(() => clearInterval(interval), 1e4);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
461
539
|
isDark() {
|
|
462
540
|
if (this.theme === "dark") return true;
|
|
463
541
|
if (this.theme === "light") return false;
|
|
@@ -1040,6 +1118,7 @@ var ModalRenderer = class {
|
|
|
1040
1118
|
);
|
|
1041
1119
|
});
|
|
1042
1120
|
}
|
|
1121
|
+
this.renderTurnstile();
|
|
1043
1122
|
const backBtn = this.shadowRoot.getElementById("back-btn");
|
|
1044
1123
|
if (backBtn) {
|
|
1045
1124
|
backBtn.addEventListener("click", () => {
|
|
@@ -1567,6 +1646,8 @@ var Authon = class {
|
|
|
1567
1646
|
providers = [];
|
|
1568
1647
|
providerFlowModes = {};
|
|
1569
1648
|
initialized = false;
|
|
1649
|
+
captchaEnabled = false;
|
|
1650
|
+
turnstileSiteKey = "";
|
|
1570
1651
|
constructor(publishableKey, config) {
|
|
1571
1652
|
this.publishableKey = publishableKey;
|
|
1572
1653
|
this.config = {
|
|
@@ -1601,10 +1682,12 @@ var Authon = class {
|
|
|
1601
1682
|
await this.ensureInitialized();
|
|
1602
1683
|
await this.startOAuthFlow(provider, options);
|
|
1603
1684
|
}
|
|
1604
|
-
async signInWithEmail(email, password) {
|
|
1685
|
+
async signInWithEmail(email, password, turnstileToken) {
|
|
1686
|
+
const body = { email, password };
|
|
1687
|
+
if (turnstileToken) body.turnstileToken = turnstileToken;
|
|
1605
1688
|
const res = await this.apiPost(
|
|
1606
1689
|
"/v1/auth/signin",
|
|
1607
|
-
|
|
1690
|
+
body
|
|
1608
1691
|
);
|
|
1609
1692
|
if (res.mfaRequired && res.mfaToken) {
|
|
1610
1693
|
this.emit("mfaRequired", res.mfaToken);
|
|
@@ -1898,6 +1981,14 @@ var Authon = class {
|
|
|
1898
1981
|
this.listeners.clear();
|
|
1899
1982
|
}
|
|
1900
1983
|
// ── Internal ──
|
|
1984
|
+
loadTurnstileScript() {
|
|
1985
|
+
if (typeof document === "undefined") return;
|
|
1986
|
+
if (document.querySelector('script[src*="challenges.cloudflare.com/turnstile"]')) return;
|
|
1987
|
+
const script = document.createElement("script");
|
|
1988
|
+
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
|
|
1989
|
+
script.async = true;
|
|
1990
|
+
document.head.appendChild(script);
|
|
1991
|
+
}
|
|
1901
1992
|
emit(event, ...args) {
|
|
1902
1993
|
this.listeners.get(event)?.forEach((fn) => fn(...args));
|
|
1903
1994
|
}
|
|
@@ -1909,6 +2000,11 @@ var Authon = class {
|
|
|
1909
2000
|
this.apiGet("/v1/auth/providers")
|
|
1910
2001
|
]);
|
|
1911
2002
|
this.branding = { ...branding, ...this.config.appearance };
|
|
2003
|
+
this.captchaEnabled = !!branding.captchaEnabled;
|
|
2004
|
+
this.turnstileSiteKey = branding.turnstileSiteKey || "";
|
|
2005
|
+
if (this.captchaEnabled && this.turnstileSiteKey) {
|
|
2006
|
+
this.loadTurnstileScript();
|
|
2007
|
+
}
|
|
1912
2008
|
this.providers = providersRes.providers;
|
|
1913
2009
|
this.providerFlowModes = {};
|
|
1914
2010
|
for (const provider of this.providers) {
|
|
@@ -1929,11 +2025,14 @@ var Authon = class {
|
|
|
1929
2025
|
theme: this.config.theme,
|
|
1930
2026
|
containerId: this.config.containerId,
|
|
1931
2027
|
branding: this.branding || void 0,
|
|
2028
|
+
captchaSiteKey: this.captchaEnabled ? this.turnstileSiteKey : void 0,
|
|
1932
2029
|
onProviderClick: (provider) => this.startOAuthFlow(provider),
|
|
1933
2030
|
onEmailSubmit: (email, password, isSignUp) => {
|
|
1934
2031
|
this.modal?.clearError();
|
|
1935
|
-
const
|
|
2032
|
+
const turnstileToken = this.modal?.getTurnstileToken?.() || void 0;
|
|
2033
|
+
const promise = isSignUp ? this.signUpWithEmail(email, password, { turnstileToken }) : this.signInWithEmail(email, password, turnstileToken);
|
|
1936
2034
|
promise.then(() => this.modal?.close()).catch((err) => {
|
|
2035
|
+
this.modal?.resetTurnstile?.();
|
|
1937
2036
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1938
2037
|
this.modal?.showError(msg || "Authentication failed");
|
|
1939
2038
|
this.emit("error", err instanceof Error ? err : new Error(msg));
|