@atlasauth/embed 0.1.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.
Files changed (59) hide show
  1. package/dist/appearance.d.ts +293 -0
  2. package/dist/appearance.js +206 -0
  3. package/dist/appearance.js.map +1 -0
  4. package/dist/client.d.ts +12 -0
  5. package/dist/client.js +49 -0
  6. package/dist/client.js.map +1 -0
  7. package/dist/config.d.ts +27 -0
  8. package/dist/config.js +61 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/element.d.ts +23 -0
  11. package/dist/element.js +51 -0
  12. package/dist/element.js.map +1 -0
  13. package/dist/embed.js +361 -0
  14. package/dist/icons.d.ts +17 -0
  15. package/dist/icons.js +53 -0
  16. package/dist/icons.js.map +1 -0
  17. package/dist/index.d.ts +19 -0
  18. package/dist/index.js +39 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/mount.d.ts +7 -0
  21. package/dist/mount.js +33 -0
  22. package/dist/mount.js.map +1 -0
  23. package/dist/redirect.d.ts +17 -0
  24. package/dist/redirect.js +51 -0
  25. package/dist/redirect.js.map +1 -0
  26. package/dist/standalone.d.ts +25 -0
  27. package/dist/standalone.js +34 -0
  28. package/dist/standalone.js.map +1 -0
  29. package/dist/styles.d.ts +17 -0
  30. package/dist/styles.js +389 -0
  31. package/dist/styles.js.map +1 -0
  32. package/dist/widget/captcha.d.ts +21 -0
  33. package/dist/widget/captcha.js +197 -0
  34. package/dist/widget/captcha.js.map +1 -0
  35. package/dist/widget/constants.d.ts +16 -0
  36. package/dist/widget/constants.js +14 -0
  37. package/dist/widget/constants.js.map +1 -0
  38. package/dist/widget/dom.d.ts +18 -0
  39. package/dist/widget/dom.js +71 -0
  40. package/dist/widget/dom.js.map +1 -0
  41. package/dist/widget/flow.d.ts +41 -0
  42. package/dist/widget/flow.js +424 -0
  43. package/dist/widget/flow.js.map +1 -0
  44. package/dist/widget/forms.d.ts +35 -0
  45. package/dist/widget/forms.js +499 -0
  46. package/dist/widget/forms.js.map +1 -0
  47. package/dist/widget/passkey.d.ts +18 -0
  48. package/dist/widget/passkey.js +88 -0
  49. package/dist/widget/passkey.js.map +1 -0
  50. package/dist/widget/render.d.ts +21 -0
  51. package/dist/widget/render.js +210 -0
  52. package/dist/widget/render.js.map +1 -0
  53. package/dist/widget/social.d.ts +44 -0
  54. package/dist/widget/social.js +331 -0
  55. package/dist/widget/social.js.map +1 -0
  56. package/dist/widget.d.ts +124 -0
  57. package/dist/widget.js +182 -0
  58. package/dist/widget.js.map +1 -0
  59. package/package.json +27 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/widget/constants.ts"],"names":[],"mappings":";;;AAAA;yDACyD;AAC5C,QAAA,gBAAgB,GAAG,IAAI,GAAG,CAAS,CAAC,SAAS,CAAC,CAAC,CAAC;AAE7D,oEAAoE;AACvD,QAAA,YAAY,GACvB,mLAAmL,CAAC;AACzK,QAAA,aAAa,GACxB,iLAAiL,CAAC;AAEvK,QAAA,IAAI,GAAG;IAClB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE;IACnD,SAAS,EAAE,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,UAAU,EAAE;CACvD,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { classFor } from '../appearance';
2
+ import type { AtlasWidget } from '../widget';
3
+ export declare function doc(w: AtlasWidget): Document;
4
+ export declare function el(w: AtlasWidget, tag: string, className?: string, text?: string): HTMLElement;
5
+ export declare function cls(w: AtlasWidget, element: Parameters<typeof classFor>[0], base: string): string;
6
+ /**
7
+ * A material tap ripple: spawn a scaled circle at the pointer, sized to cover
8
+ * the button, and remove it when its animation ends. No-op unless the ripple
9
+ * effect is active and motion is allowed — cheap enough to bind to every button.
10
+ */
11
+ export declare function bindRipple(w: AtlasWidget, button: HTMLElement): void;
12
+ /**
13
+ * The primary submit button, with a built-in busy state: while `busy` it shows
14
+ * a spinner in place of its label (and is disabled), so clicking "Continue"
15
+ * gives immediate progress feedback instead of a dead, unchanged button. Goes
16
+ * through `el()` so the ripple/interaction bindings still apply.
17
+ */
18
+ export declare function submitButton(w: AtlasWidget, label: string): HTMLButtonElement;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.doc = doc;
4
+ exports.el = el;
5
+ exports.cls = cls;
6
+ exports.bindRipple = bindRipple;
7
+ exports.submitButton = submitButton;
8
+ const appearance_1 = require("../appearance");
9
+ function doc(w) {
10
+ return w.root.ownerDocument ?? document;
11
+ }
12
+ function el(w, tag, className, text) {
13
+ const node = doc(w).createElement(tag);
14
+ if (className)
15
+ node.className = className;
16
+ if (text != null)
17
+ node.textContent = text;
18
+ // The two button classes the ripple stylesheet clips — bind the tap ripple
19
+ // here so every submit/social button gets it without touching each call site.
20
+ if (node.classList.contains('atlas-embed-button') ||
21
+ node.classList.contains('atlas-embed-social-button')) {
22
+ bindRipple(w, node);
23
+ }
24
+ return node;
25
+ }
26
+ function cls(w, element, base) {
27
+ return (0, appearance_1.classFor)(element, base, w.options.appearance);
28
+ }
29
+ /**
30
+ * A material tap ripple: spawn a scaled circle at the pointer, sized to cover
31
+ * the button, and remove it when its animation ends. No-op unless the ripple
32
+ * effect is active and motion is allowed — cheap enough to bind to every button.
33
+ */
34
+ function bindRipple(w, button) {
35
+ if (w.interaction.buttonEffect !== 'ripple' || !w.interaction.animations)
36
+ return;
37
+ button.addEventListener('pointerdown', (ev) => {
38
+ const rect = button.getBoundingClientRect();
39
+ const size = Math.max(rect.width, rect.height);
40
+ const span = doc(w).createElement('span');
41
+ span.className = 'atlas-embed-ripple';
42
+ span.style.width = span.style.height = `${size}px`;
43
+ span.style.left = `${ev.clientX - rect.left - size / 2}px`;
44
+ span.style.top = `${ev.clientY - rect.top - size / 2}px`;
45
+ span.addEventListener('animationend', () => span.remove());
46
+ button.appendChild(span);
47
+ });
48
+ }
49
+ /**
50
+ * The primary submit button, with a built-in busy state: while `busy` it shows
51
+ * a spinner in place of its label (and is disabled), so clicking "Continue"
52
+ * gives immediate progress feedback instead of a dead, unchanged button. Goes
53
+ * through `el()` so the ripple/interaction bindings still apply.
54
+ */
55
+ function submitButton(w, label) {
56
+ const btn = el(w, 'button', cls(w, 'buttonPrimary', 'atlas-embed-button'));
57
+ btn.type = 'submit';
58
+ btn.disabled = w.busy;
59
+ if (w.busy) {
60
+ btn.setAttribute('data-busy', '');
61
+ btn.setAttribute('aria-label', label);
62
+ const sp = el(w, 'span', 'atlas-embed-btn-spinner');
63
+ sp.setAttribute('aria-hidden', 'true');
64
+ btn.appendChild(sp);
65
+ }
66
+ else {
67
+ btn.textContent = label;
68
+ }
69
+ return btn;
70
+ }
71
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/widget/dom.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import type { AtlasWidget } from '../widget';
2
+ export declare function handleRedirectLanding(w: AtlasWidget): Promise<boolean>;
3
+ export declare function exchange(w: AtlasWidget, attemptId: string, ticket: string): Promise<void>;
4
+ /**
5
+ * Finish: navigate to a VALIDATED redirect, or — when none is supplied or it
6
+ * is rejected — emit `atlas:complete` so the embedding page decides. The event
7
+ * bubbles and is cancelable-free; its detail carries the attempt id.
8
+ */
9
+ export declare function complete(w: AtlasWidget, attemptId: string | null): Promise<void>;
10
+ /**
11
+ * §bot — fire the anti-bot signal beacon for this interaction. Fully
12
+ * best-effort and fire-and-forget: it never blocks or fails a sign-in.
13
+ */
14
+ export declare function beacon(w: AtlasWidget, attemptId?: string | null): void;
15
+ export declare function submit(w: AtlasWidget, values: Record<string, string>): Promise<void>;
16
+ export declare function startOAuth(w: AtlasWidget, provider: string, identifier?: string): Promise<void>;
17
+ /**
18
+ * Start a "Sign in with Atlas" (or any SSO connection) sign-in: POST the
19
+ * connection id, then navigate to the authorize URL the server returns. The OIDC
20
+ * callback returns to this page (an allowed origin) to exchange the ticket — the
21
+ * same completion path startOAuth uses.
22
+ *
23
+ * `opts.popup` runs the flow in a GSI-style popup window instead of a full-page
24
+ * redirect; the callback hands the ticket back via postMessage and this page
25
+ * exchanges it in place. A blocked popup falls back to the redirect flow.
26
+ */
27
+ export declare function startSso(w: AtlasWidget, connectionId: string, opts?: {
28
+ popup?: boolean;
29
+ }): Promise<void>;
30
+ /**
31
+ * Complete a native / One-Tap sign-in: POST the provider id_token, then either
32
+ * exchange the returned ticket for cookies (complete) or resume at the second
33
+ * factor the attempt still owes — the SAME completion paths the redirect flow
34
+ * uses, so GSI and the redirect flow finish identically.
35
+ */
36
+ export declare function completeIdToken(w: AtlasWidget, provider: string, idToken: string): Promise<void>;
37
+ /** §5.4 enter the "forgot password" sub-flow. */
38
+ export declare function startReset(w: AtlasWidget): void;
39
+ /** Drive the reset one step: start it, or advance it, then complete on success. */
40
+ export declare function submitReset(w: AtlasWidget, values: Record<string, string>): Promise<void>;
41
+ export declare function submitSignUp(w: AtlasWidget, values: Record<string, string>, consent?: boolean): Promise<void>;
@@ -0,0 +1,424 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleRedirectLanding = handleRedirectLanding;
4
+ exports.exchange = exchange;
5
+ exports.complete = complete;
6
+ exports.beacon = beacon;
7
+ exports.submit = submit;
8
+ exports.startOAuth = startOAuth;
9
+ exports.startSso = startSso;
10
+ exports.completeIdToken = completeIdToken;
11
+ exports.startReset = startReset;
12
+ exports.submitReset = submitReset;
13
+ exports.submitSignUp = submitSignUp;
14
+ const js_1 = require("@atlasauth/js");
15
+ const redirect_1 = require("../redirect");
16
+ const captcha_1 = require("./captcha");
17
+ const render_1 = require("./render");
18
+ /**
19
+ * §5 obtain a captcha token for a flow, mounting the challenge OUTSIDE `w.root`
20
+ * (render() wipes root on every paint, so a host inside it would vanish). The
21
+ * host is removed as soon as the token resolves. Returns null when no token is
22
+ * needed or the provider isn't one the widget renders — the server still fails
23
+ * closed if it required one, surfacing the normal CAPTCHA_REQUIRED error.
24
+ *
25
+ * `always` renders even when the flow's always-on flag is off — used for a
26
+ * risk-triggered sign-in challenge, where the server demands a token mid-flow
27
+ * regardless of the per-flow toggle.
28
+ */
29
+ async function captchaToken(w, key, always = false) {
30
+ const flow = w.captchaFlows[key];
31
+ const wanted = always ? !!flow && (0, captcha_1.isRenderable)(flow.provider) : (0, captcha_1.flowNeedsCaptcha)(flow);
32
+ if (!wanted || !flow)
33
+ return null;
34
+ const doc = w.root.ownerDocument ?? document;
35
+ const host = doc.createElement('div');
36
+ host.className = 'atlas-embed-captcha';
37
+ (w.root.parentElement ?? doc.body ?? doc.documentElement).appendChild(host);
38
+ try {
39
+ return await (0, captcha_1.getCaptchaToken)(flow, host);
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ finally {
45
+ host.remove();
46
+ }
47
+ }
48
+ // ---- redirect landing (OAuth / hosted completion) ------------------------
49
+ async function handleRedirectLanding(w) {
50
+ const win = w.root.ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : null);
51
+ if (!win)
52
+ return false;
53
+ const result = (0, js_1.readRedirectResult)(win.location.search);
54
+ if (!result)
55
+ return false;
56
+ if (result.ticket) {
57
+ await exchange(w, result.attemptId, result.ticket);
58
+ scrubUrl(w, win);
59
+ await complete(w, result.attemptId);
60
+ return true;
61
+ }
62
+ // A redirect that carries a status but no ticket owes a second factor:
63
+ // resume the flow AT that step, bound to the same attempt.
64
+ if (result.status) {
65
+ w.state = (0, js_1.flowFromPending)({ id: result.attemptId, status: result.status });
66
+ scrubUrl(w, win);
67
+ }
68
+ return false;
69
+ }
70
+ function scrubUrl(w, win) {
71
+ try {
72
+ win.history.replaceState({}, win.document.title, (0, js_1.stripRedirectParams)(win.location.href));
73
+ }
74
+ catch {
75
+ // A sandboxed history is not fatal — the flow still works.
76
+ }
77
+ }
78
+ // ---- completion ----------------------------------------------------------
79
+ async function exchange(w, attemptId, ticket) {
80
+ // Preview: the flow ran end-to-end, but we deliberately do NOT redeem the
81
+ // ticket — no session cookie is set, so the host page's session is untouched.
82
+ if (w.options.preview)
83
+ return;
84
+ // §7.5 carry the Remember-me choice so the server can make the refresh cookie
85
+ // persistent (default) or a session cookie (unticked).
86
+ await w.client.post('/v1/client/tickets/exchange', {
87
+ attempt_id: attemptId,
88
+ ticket,
89
+ remember: w.remember,
90
+ });
91
+ }
92
+ /**
93
+ * Finish: navigate to a VALIDATED redirect, or — when none is supplied or it
94
+ * is rejected — emit `atlas:complete` so the embedding page decides. The event
95
+ * bubbles and is cancelable-free; its detail carries the attempt id.
96
+ */
97
+ async function complete(w, attemptId) {
98
+ const win = w.root.ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : null);
99
+ const target = (0, redirect_1.validateRedirect)(w.options.redirect, win ? win.location.origin : undefined);
100
+ w.root.dispatchEvent(new CustomEvent('atlas:complete', {
101
+ bubbles: true,
102
+ detail: { attemptId, redirected: Boolean(target) },
103
+ }));
104
+ // Preview never navigates and never claims a session — it confirms the flow.
105
+ if (w.options.preview) {
106
+ (0, render_1.renderNote)(w, 'Sign-in works — this is a preview, so no session was created.');
107
+ return;
108
+ }
109
+ if (target && win) {
110
+ win.location.assign(target);
111
+ return;
112
+ }
113
+ (0, render_1.renderNote)(w, 'You are signed in.');
114
+ }
115
+ // ---- flow submit ---------------------------------------------------------
116
+ /**
117
+ * §bot — fire the anti-bot signal beacon for this interaction. Fully
118
+ * best-effort and fire-and-forget: it never blocks or fails a sign-in.
119
+ */
120
+ function beacon(w, attemptId) {
121
+ void (0, js_1.sendTelemetry)({
122
+ api: w.options.frontendApi,
123
+ publishableKey: w.options.publishableKey,
124
+ attemptId: attemptId ?? undefined,
125
+ kind: w.mode === 'sign-up' ? 'sign_up' : 'sign_in',
126
+ recorder: w.recorder,
127
+ fetchImpl: w.options.fetchImpl,
128
+ });
129
+ }
130
+ async function submit(w, values) {
131
+ if (w.busy)
132
+ return;
133
+ // The user is signing in by other means — stand down the background passkey
134
+ // autofill ceremony so it cannot resolve underneath them.
135
+ w.conditionalAbort?.abort();
136
+ w.flash = null; // the confirmation banner clears once the user acts
137
+ // Remember the identifier so the code/password steps can show it as context.
138
+ if (typeof values.identifier === 'string' && values.identifier.trim()) {
139
+ w.enteredIdentifier = values.identifier.trim();
140
+ }
141
+ w.busy = true;
142
+ // Beacon at the moment of submit — behaviour is richest here.
143
+ beacon(w, w.state.attempt?.id);
144
+ (0, render_1.render)(w);
145
+ w.state = await (0, js_1.advance)(w.client, w.state, values);
146
+ // §5 the server withheld the attempt pending a captcha (an always-on sign-in
147
+ // gate, or a risk-triggered challenge): render the provider's widget and
148
+ // resubmit the identifier with the token. `always` so a risk challenge renders
149
+ // even when the sign-in flow's always-on toggle is off.
150
+ if (w.state.attempt && (0, js_1.nextStep)(w.state.attempt).kind === 'collect_captcha') {
151
+ const token = await captchaToken(w, 'signIn', true);
152
+ if (token) {
153
+ w.state = await (0, js_1.advance)(w.client, w.state, {
154
+ identifier: w.enteredIdentifier ?? values.identifier ?? '',
155
+ captcha_token: token,
156
+ });
157
+ }
158
+ }
159
+ // Single-screen sign-in: the identifier POST just landed on the first-factor
160
+ // step and the user already typed their password on the same form — send it
161
+ // now so it's one click, not two screens. Only when the server actually
162
+ // asked for the first factor and the identifier step raised no error.
163
+ const step = w.state.attempt ? (0, js_1.nextStep)(w.state.attempt) : null;
164
+ if (step?.kind === 'collect_first_factor' && values.password && w.state.errors.length === 0) {
165
+ w.state = await (0, js_1.advance)(w.client, w.state, { password: values.password });
166
+ }
167
+ w.busy = false;
168
+ // §single-screen: a sign-in box that shows email + password TOGETHER must not
169
+ // collapse to a password-only screen after a wrong password — that reads as
170
+ // "the email field just vanished". Return to the combined box (email prefilled
171
+ // from what they typed) carrying any error, so a wrong credential reads as "try
172
+ // again" in the same box. The next submit starts a fresh attempt — cheaper than
173
+ // stranding the user on a field-less screen.
174
+ const endStep = w.state.attempt ? (0, js_1.nextStep)(w.state.attempt) : null;
175
+ if (w.mode === 'sign-in' && w.passwordEnabled && endStep?.kind === 'collect_first_factor') {
176
+ w.state = { ...js_1.initialFlow, errors: w.state.errors };
177
+ }
178
+ const attempt = w.state.attempt;
179
+ if (attempt?.status === 'complete') {
180
+ const attemptId = attempt.id ?? null;
181
+ if (w.state.ticket && attemptId)
182
+ await exchange(w, attemptId, w.state.ticket);
183
+ await complete(w, attemptId);
184
+ return;
185
+ }
186
+ (0, render_1.render)(w);
187
+ }
188
+ async function startOAuth(w, provider, identifier) {
189
+ // §bot — beacon before we navigate away to the provider.
190
+ beacon(w);
191
+ const win = w.root.ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : null);
192
+ // The OAuth callback must return to a page that runs the widget so it can
193
+ // exchange the ticket — this page. The server additionally requires this
194
+ // URL to be one of the instance's allowedOrigins.
195
+ const redirectUrl = win ? (0, js_1.stripRedirectParams)(win.location.href) : w.options.frontendApi;
196
+ const response = await w.client.post('/v1/client/sign_ins/oauth',
197
+ // Bluesky (AT-Proto) resolves the user's PDS from their handle, so it is
198
+ // sent up front; every other provider ignores `identifier`.
199
+ { provider, redirect_url: redirectUrl, ...(identifier ? { identifier } : {}) });
200
+ const url = response.data?.authorization_url;
201
+ if (url && win)
202
+ win.location.assign(url);
203
+ else {
204
+ w.handlePrompt = null;
205
+ (0, render_1.renderErrors)(w, response.errors);
206
+ }
207
+ }
208
+ /**
209
+ * Start a "Sign in with Atlas" (or any SSO connection) sign-in: POST the
210
+ * connection id, then navigate to the authorize URL the server returns. The OIDC
211
+ * callback returns to this page (an allowed origin) to exchange the ticket — the
212
+ * same completion path startOAuth uses.
213
+ *
214
+ * `opts.popup` runs the flow in a GSI-style popup window instead of a full-page
215
+ * redirect; the callback hands the ticket back via postMessage and this page
216
+ * exchanges it in place. A blocked popup falls back to the redirect flow.
217
+ */
218
+ async function startSso(w, connectionId, opts = {}) {
219
+ beacon(w);
220
+ const win = w.root.ownerDocument?.defaultView ?? (typeof window !== 'undefined' ? window : null);
221
+ const baseRedirect = win ? (0, js_1.stripRedirectParams)(win.location.href) : w.options.frontendApi;
222
+ if (opts.popup && win) {
223
+ await startSsoPopup(w, connectionId, win, baseRedirect);
224
+ return;
225
+ }
226
+ const response = await w.client.post('/v1/client/sign_ins/sso', { connection_id: connectionId, redirect_url: baseRedirect });
227
+ const url = response.data?.authorization_url;
228
+ if (url && win)
229
+ win.location.assign(url);
230
+ else
231
+ (0, render_1.renderErrors)(w, response.errors);
232
+ }
233
+ /** The origin the popup handoff posts from — the widget's own FAPI origin. */
234
+ function fapiOrigin(w) {
235
+ const fa = w.options.frontendApi;
236
+ try {
237
+ return new URL(/^https?:\/\//.test(fa) ? fa : `https://${fa}`).origin;
238
+ }
239
+ catch {
240
+ return fa;
241
+ }
242
+ }
243
+ /**
244
+ * The GSI-style popup variant. The popup is opened SYNCHRONOUSLY (before the
245
+ * async POST) so the browser treats it as user-initiated and does not block it;
246
+ * a blocked popup falls back to the full-page redirect. The callback lands in
247
+ * the popup, posts the ticket to this window (origin-checked), and we finish the
248
+ * sign-in here — the same exchange→complete path the redirect landing uses.
249
+ */
250
+ async function startSsoPopup(w, connectionId, win, baseRedirect) {
251
+ const popup = win.open('about:blank', 'atlas-sso', 'width=480,height=640,menubar=no,toolbar=no,location=no,status=no');
252
+ if (!popup) {
253
+ // Popup blocked — fall back to the reliable redirect flow.
254
+ await startSso(w, connectionId);
255
+ return;
256
+ }
257
+ const sep = baseRedirect.includes('?') ? '&' : '?';
258
+ const redirectUrl = `${baseRedirect}${sep}__atlas_display=popup`;
259
+ const expectedOrigin = fapiOrigin(w);
260
+ const onMessage = (event) => {
261
+ if (event.origin !== expectedOrigin)
262
+ return;
263
+ const data = event.data;
264
+ if (!data || data.type !== 'atlas-sso')
265
+ return;
266
+ win.removeEventListener('message', onMessage);
267
+ try {
268
+ popup.close();
269
+ }
270
+ catch {
271
+ /* a cross-origin popup may already be gone */
272
+ }
273
+ if (data.error) {
274
+ (0, render_1.renderErrors)(w, [{ code: 'sso_popup_cancelled', message: 'Sign-in was cancelled.' }]);
275
+ return;
276
+ }
277
+ if (data.status === 'complete' && data.ticket && data.attempt_id) {
278
+ const attemptId = data.attempt_id;
279
+ const ticket = data.ticket;
280
+ void (async () => {
281
+ await exchange(w, attemptId, ticket);
282
+ await complete(w, attemptId);
283
+ })();
284
+ return;
285
+ }
286
+ // Owes a second factor — resume the flow in THIS window at that step.
287
+ if (data.attempt_id && data.status) {
288
+ w.state = (0, js_1.flowFromPending)({ id: data.attempt_id, status: data.status });
289
+ (0, render_1.render)(w);
290
+ }
291
+ };
292
+ win.addEventListener('message', onMessage);
293
+ const response = await w.client.post('/v1/client/sign_ins/sso', { connection_id: connectionId, redirect_url: redirectUrl });
294
+ const url = response.data?.authorization_url;
295
+ if (url) {
296
+ try {
297
+ popup.location.assign(url);
298
+ }
299
+ catch {
300
+ // Some browsers disallow scripting a popup we just navigated cross-origin;
301
+ // fall back to navigating this window instead.
302
+ try {
303
+ popup.close();
304
+ }
305
+ catch {
306
+ /* ignore */
307
+ }
308
+ win.removeEventListener('message', onMessage);
309
+ win.location.assign(url);
310
+ }
311
+ }
312
+ else {
313
+ win.removeEventListener('message', onMessage);
314
+ try {
315
+ popup.close();
316
+ }
317
+ catch {
318
+ /* ignore */
319
+ }
320
+ (0, render_1.renderErrors)(w, response.errors);
321
+ }
322
+ }
323
+ /**
324
+ * Complete a native / One-Tap sign-in: POST the provider id_token, then either
325
+ * exchange the returned ticket for cookies (complete) or resume at the second
326
+ * factor the attempt still owes — the SAME completion paths the redirect flow
327
+ * uses, so GSI and the redirect flow finish identically.
328
+ */
329
+ async function completeIdToken(w, provider, idToken) {
330
+ const res = await w.client.post('/v1/client/sign_ins/id_token', (0, js_1.nativeSignInBody)({ provider, idToken }));
331
+ const parsed = (0, js_1.parseNativeSignInResponse)(res.data);
332
+ if (!parsed) {
333
+ (0, render_1.renderErrors)(w, res.errors);
334
+ return;
335
+ }
336
+ if (parsed.status === 'complete' && parsed.ticket) {
337
+ await exchange(w, parsed.attemptId, parsed.ticket);
338
+ await complete(w, parsed.attemptId);
339
+ return;
340
+ }
341
+ // Owes a second factor — resume at that step, bound to the same attempt.
342
+ w.state = (0, js_1.flowFromPending)({ id: parsed.attemptId, status: parsed.status });
343
+ (0, render_1.render)(w);
344
+ }
345
+ /** §5.4 enter the "forgot password" sub-flow. */
346
+ function startReset(w) {
347
+ w.resetFlow = { ...js_1.initialResetFlow };
348
+ (0, render_1.render)(w);
349
+ }
350
+ /** Drive the reset one step: start it, or advance it, then complete on success. */
351
+ async function submitReset(w, values) {
352
+ if (w.busy || !w.resetFlow)
353
+ return;
354
+ w.busy = true;
355
+ beacon(w);
356
+ (0, render_1.render)(w);
357
+ if ((0, js_1.resetStep)(w.resetFlow) === 'request') {
358
+ if (typeof values.email === 'string' && values.email.trim()) {
359
+ w.enteredIdentifier = values.email.trim();
360
+ }
361
+ const token = await captchaToken(w, 'passwordReset');
362
+ w.resetFlow = await (0, js_1.startPasswordReset)(w.client, values.email ?? '', token ?? undefined);
363
+ }
364
+ else {
365
+ w.resetFlow = await (0, js_1.advancePasswordReset)(w.client, w.resetFlow, {
366
+ code: values.code,
367
+ password: values.password,
368
+ });
369
+ }
370
+ w.busy = false;
371
+ const done = w.resetFlow;
372
+ if (done?.attempt?.status === 'complete') {
373
+ const attemptId = done.attempt.id;
374
+ w.resetFlow = null;
375
+ if (done.ticket) {
376
+ // Auto sign-in: exchange the ticket for a session, exactly like a normal
377
+ // sign-in completion.
378
+ await exchange(w, attemptId, done.ticket);
379
+ await complete(w, attemptId);
380
+ }
381
+ else {
382
+ // Force-login: no session was issued. Return to the sign-in box (email
383
+ // already prefilled) with a confirmation, so the user signs in with the
384
+ // new password.
385
+ w.flash = 'Password updated. Sign in with your new password.';
386
+ w.state = js_1.initialFlow;
387
+ (0, render_1.render)(w);
388
+ }
389
+ return;
390
+ }
391
+ (0, render_1.render)(w);
392
+ }
393
+ async function submitSignUp(w, values, consent = true) {
394
+ if (w.busy)
395
+ return;
396
+ w.busy = true;
397
+ beacon(w);
398
+ (0, render_1.render)(w);
399
+ const { identifier, password, ...rest } = values;
400
+ // Drop blank optional fields so we never send empty strings to the server.
401
+ const fields = {};
402
+ for (const [key, value] of Object.entries(rest))
403
+ if (value)
404
+ fields[key] = value;
405
+ const token = await captchaToken(w, 'signUp');
406
+ w.state = await (0, js_1.startSignUp)(w.client, {
407
+ email: identifier ?? '',
408
+ password: password ?? '',
409
+ fields,
410
+ consent,
411
+ captchaToken: token ?? undefined,
412
+ });
413
+ w.busy = false;
414
+ const attempt = w.state.attempt;
415
+ if (attempt?.status === 'complete') {
416
+ const attemptId = attempt.id ?? null;
417
+ if (w.state.ticket && attemptId)
418
+ await exchange(w, attemptId, w.state.ticket);
419
+ await complete(w, attemptId);
420
+ return;
421
+ }
422
+ (0, render_1.render)(w);
423
+ }
424
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/widget/flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type FieldError } from '@atlasauth/js';
2
+ import type { AtlasWidget } from '../widget';
3
+ /**
4
+ * §5.4 the reset sub-flow panel: email → emailed code → (2FA) → new password →
5
+ * signed in. Reuses the shared field builders + the segmented code input, and
6
+ * always offers a way back to sign in.
7
+ */
8
+ export declare function renderReset(w: AtlasWidget): HTMLElement;
9
+ /** A labelled text input, appended to `form` and registered in `inputs`. */
10
+ export declare function fieldInto(w: AtlasWidget, form: HTMLElement, inputs: Map<string, HTMLInputElement>, errors: readonly FieldError[], name: string, label: string, type: string, autocomplete: string): void;
11
+ /**
12
+ * A verification-code field. `boxes` (default) is a segmented one-box-per-digit
13
+ * input that auto-advances, accepts a paste, and auto-submits when full;
14
+ * `single` (or a non-6-digit code) is a plain field. Both feed the same `name`.
15
+ * Shared by the sign-in and the password-reset forms.
16
+ */
17
+ export declare function codeFieldInto(w: AtlasWidget, form: HTMLElement, inputs: Map<string, HTMLInputElement>, errors: readonly FieldError[], name: string, label: string, autofocus: boolean): void;
18
+ export declare function renderForm(w: AtlasWidget, stepKind: string): HTMLElement;
19
+ /**
20
+ * §5.1 legal consent on sign-up: a line linking the Terms of Service / Privacy
21
+ * Policy the tenant configured. When `required`, it carries a checkbox that gates
22
+ * account creation. Returns null when the tenant set no links. The URLs are
23
+ * https-sanitised server-side, so they are safe to render as anchors.
24
+ */
25
+ export declare function renderLegalConsent(w: AtlasWidget): {
26
+ row: HTMLElement;
27
+ checkbox: HTMLInputElement | null;
28
+ } | null;
29
+ /**
30
+ * §5 The create-account form: the tenant's configured fields (name, company,
31
+ * phone, custom…) followed by email + password. Submits to
32
+ * /v1/client/sign_ups; the server then emails a code and the shared flow drives
33
+ * verification to completion.
34
+ */
35
+ export declare function renderSignUpForm(w: AtlasWidget): HTMLElement;