@atlasauth/js 0.6.0 → 0.8.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.
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ /**
3
+ * §oauth popup mode — the same-origin hand-back for a popup whose
4
+ * `window.opener` was severed.
5
+ *
6
+ * When the page that opens the sign-in popup sends a restrictive
7
+ * Cross-Origin-Opener-Policy (`same-origin`), the browser puts the cross-origin
8
+ * popup in another browsing-context group: `popup.closed` reads `true` to the
9
+ * opener almost at once and `window.opener` is `null` inside the popup, so the
10
+ * Frontend API's `postMessage` can never arrive. The Frontend API then sends the
11
+ * popup back to the OPENER's own page with the result in the URL fragment
12
+ * (`#atlas_popup_result=…`, never the query). That page runs the SDK, which:
13
+ *
14
+ * 1. reads and scrubs the fragment ({@link completeOAuthPopupLanding}),
15
+ * 2. relays the result to the opener over
16
+ * `BroadcastChannel('atlas:oauth:<nonce>')` (a `localStorage` `storage`
17
+ * event where BroadcastChannel is missing) — both are same-origin, so
18
+ * they connect where `window.opener` cannot,
19
+ * 3. closes the popup once the opener acknowledges.
20
+ *
21
+ * Nothing here carries a token: the result is the same one-time ticket (or
22
+ * continuation) the redirect flow puts in its URL, and the opener exchanges it.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.POPUP_SIGNAL_CHANNEL = exports.POPUP_RESULT_FRAGMENT = exports.OAUTH_POPUP_WINDOW_NAME = void 0;
26
+ exports.popupChannelName = popupChannelName;
27
+ exports.createPopupNonce = createPopupNonce;
28
+ exports.listenForPopupResult = listenForPopupResult;
29
+ exports.readPopupLanding = readPopupLanding;
30
+ exports.completeOAuthPopupLanding = completeOAuthPopupLanding;
31
+ exports.closeOAuthPopupAfterSignIn = closeOAuthPopupAfterSignIn;
32
+ const tab_election_1 = require("./tab-election");
33
+ /** The window name {@link startOauthPopup} opens the popup with. */
34
+ exports.OAUTH_POPUP_WINDOW_NAME = 'atlas:oauth';
35
+ /** The fragment key the Frontend API lands the popup result in. */
36
+ exports.POPUP_RESULT_FRAGMENT = 'atlas_popup_result';
37
+ /** The channel a page that finished sign-in inside the popup announces on. */
38
+ exports.POPUP_SIGNAL_CHANNEL = 'atlas:oauth';
39
+ /** The per-flow channel: `atlas:oauth:<nonce>`. */
40
+ function popupChannelName(nonce) {
41
+ return `${exports.POPUP_SIGNAL_CHANNEL}:${nonce}`;
42
+ }
43
+ /** A fresh base64url channel nonce (22 characters). */
44
+ function createPopupNonce() {
45
+ const bytes = new Uint8Array(16);
46
+ const c = globalThis.crypto;
47
+ if (c?.getRandomValues)
48
+ c.getRandomValues(bytes);
49
+ else
50
+ for (let i = 0; i < bytes.length; i++)
51
+ bytes[i] = Math.floor(Math.random() * 256);
52
+ let bin = '';
53
+ for (const b of bytes)
54
+ bin += String.fromCharCode(b);
55
+ return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
56
+ }
57
+ function isRelayMessage(value) {
58
+ if (!value || typeof value !== 'object')
59
+ return false;
60
+ const m = value;
61
+ if (typeof m.id !== 'string')
62
+ return false;
63
+ if (m.type === 'atlas:oauth:result')
64
+ return !!m.result && typeof m.result === 'object';
65
+ return m.type === 'atlas:oauth:signed_in' || m.type === 'atlas:oauth:ack';
66
+ }
67
+ function openChannel(name) {
68
+ try {
69
+ return (0, tab_election_1.broadcastChannel)(name) ?? (0, tab_election_1.storageChannel)(name);
70
+ }
71
+ catch {
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * Post `message` on `name` and resolve whether anyone acknowledged it within
77
+ * `timeoutMs`.
78
+ */
79
+ function relay(name, message, timeoutMs) {
80
+ const channel = openChannel(name);
81
+ if (!channel)
82
+ return Promise.resolve(false);
83
+ const id = createPopupNonce();
84
+ return new Promise((resolve) => {
85
+ let done = false;
86
+ const finish = (acked) => {
87
+ if (done)
88
+ return;
89
+ done = true;
90
+ clearTimeout(timer);
91
+ unsubscribe();
92
+ channel.close();
93
+ resolve(acked);
94
+ };
95
+ const unsubscribe = channel.subscribe((m) => {
96
+ if (isRelayMessage(m) && m.type === 'atlas:oauth:ack' && m.id === id)
97
+ finish(true);
98
+ });
99
+ const timer = setTimeout(() => finish(false), timeoutMs);
100
+ try {
101
+ channel.post({ ...message, id });
102
+ }
103
+ catch {
104
+ finish(false);
105
+ }
106
+ });
107
+ }
108
+ /**
109
+ * Opener side: listen on the flow's channel (and the shared signal channel) for
110
+ * the popup's result. Every message is acknowledged so the popup can close.
111
+ * Returns the stop function.
112
+ */
113
+ function listenForPopupResult(nonce, handlers) {
114
+ const flow = openChannel(popupChannelName(nonce));
115
+ const signal = handlers.onSignedIn ? openChannel(exports.POPUP_SIGNAL_CHANNEL) : null;
116
+ const unsubscribers = [];
117
+ if (flow) {
118
+ unsubscribers.push(flow.subscribe((m) => {
119
+ if (!isRelayMessage(m) || m.type !== 'atlas:oauth:result')
120
+ return;
121
+ flow.post({ type: 'atlas:oauth:ack', id: m.id });
122
+ handlers.onResult(m.result);
123
+ }));
124
+ }
125
+ if (signal) {
126
+ unsubscribers.push(signal.subscribe((m) => {
127
+ if (!isRelayMessage(m) || m.type !== 'atlas:oauth:signed_in')
128
+ return;
129
+ signal.post({ type: 'atlas:oauth:ack', id: m.id });
130
+ handlers.onSignedIn?.();
131
+ }));
132
+ }
133
+ return () => {
134
+ for (const u of unsubscribers)
135
+ u();
136
+ flow?.close();
137
+ signal?.close();
138
+ };
139
+ }
140
+ /** The popup result the Frontend API put in a URL fragment, or null. */
141
+ function readPopupLanding(hash) {
142
+ if (!hash || hash.length < 2)
143
+ return null;
144
+ const raw = new URLSearchParams(hash.replace(/^#/, '')).get(exports.POPUP_RESULT_FRAGMENT);
145
+ if (!raw)
146
+ return null;
147
+ try {
148
+ const b64 = raw.replace(/-/g, '+').replace(/_/g, '/');
149
+ const bin = atob(b64 + '='.repeat((4 - (b64.length % 4)) % 4));
150
+ const bytes = Uint8Array.from(bin, (ch) => ch.charCodeAt(0));
151
+ const payload = JSON.parse(new TextDecoder().decode(bytes));
152
+ if (!payload || typeof payload !== 'object')
153
+ return null;
154
+ const p = payload;
155
+ if (p.v !== 1 || typeof p.n !== 'string' || !p.n)
156
+ return null;
157
+ if (typeof p.type !== 'string' || !p.type.startsWith('atlas:oauth:'))
158
+ return null;
159
+ return { nonce: p.n, payload: p };
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ }
165
+ /**
166
+ * Popup side, run on startup: if this page is the landing of a severed popup
167
+ * (`#atlas_popup_result=…` in the URL — normally with `window.name ===
168
+ * 'atlas:oauth'`, though a browser may clear the name when the opener's COOP
169
+ * switched browsing-context groups, so the fragment alone is decisive), scrub
170
+ * the fragment, relay the result to the opener and close this window once the
171
+ * opener acknowledges. Returns null when this is not such a landing.
172
+ */
173
+ async function completeOAuthPopupLanding(options = {}) {
174
+ const win = options.win ?? (typeof window !== 'undefined' ? window : undefined);
175
+ if (!win)
176
+ return null;
177
+ const landing = readPopupLanding(win.location.hash);
178
+ if (!landing)
179
+ return null;
180
+ // Scrub first: a reload, the back button or a copied URL must never replay it.
181
+ try {
182
+ win.history.replaceState(win.history.state, '', win.location.href.split('#')[0]);
183
+ }
184
+ catch {
185
+ /* a sandboxed history; the ticket is single-use regardless */
186
+ }
187
+ // We ARE the Atlas popup, whatever the browser did to the name.
188
+ try {
189
+ win.name = exports.OAUTH_POPUP_WINDOW_NAME;
190
+ }
191
+ catch {
192
+ /* ignore */
193
+ }
194
+ const delivered = await relay(popupChannelName(landing.nonce), { type: 'atlas:oauth:result', result: landing.payload }, options.ackTimeoutMs ?? 1_500);
195
+ if (delivered)
196
+ closeWindow(win);
197
+ return { payload: landing.payload, delivered };
198
+ }
199
+ /**
200
+ * Popup side, after a sign-in completed ON this page (the redirect flow ran in
201
+ * the popup — e.g. an SDK or provider path without the channel): when this is
202
+ * the Atlas popup window, tell the waiting opener and close. It closes only when
203
+ * an opener is there to take over (it acknowledged, or `window.opener` is live),
204
+ * never stranding a user whose opener tab is gone. Resolves whether it closed.
205
+ */
206
+ async function closeOAuthPopupAfterSignIn(options = {}) {
207
+ const win = options.win ?? (typeof window !== 'undefined' ? window : undefined);
208
+ if (!win || win.name !== exports.OAUTH_POPUP_WINDOW_NAME)
209
+ return false;
210
+ const acked = await relay(exports.POPUP_SIGNAL_CHANNEL, { type: 'atlas:oauth:signed_in' }, options.ackTimeoutMs ?? 1_500);
211
+ let hasOpener = false;
212
+ try {
213
+ hasOpener = !!win.opener && !win.opener.closed;
214
+ }
215
+ catch {
216
+ hasOpener = false;
217
+ }
218
+ if (!acked && !hasOpener)
219
+ return false;
220
+ closeWindow(win);
221
+ return true;
222
+ }
223
+ function closeWindow(win) {
224
+ try {
225
+ win.close();
226
+ }
227
+ catch {
228
+ /* the browser refused; nothing else to do */
229
+ }
230
+ }
231
+ //# sourceMappingURL=popup-channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popup-channel.js","sourceRoot":"","sources":["../src/popup-channel.ts"],"names":[],"mappings":"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"}
@@ -59,6 +59,12 @@ export interface PopupOutcome {
59
59
  * `postMessage` on the page can never drive the flow.
60
60
  */
61
61
  export declare function parseOAuthPopupMessage(eventOrigin: string, expectedOrigin: string, data: unknown): PopupOutcome | null;
62
+ /**
63
+ * Pure: map one of the Frontend API's `atlas:oauth:*` result payloads (from a
64
+ * `postMessage`, or relayed from a severed popup's landing page) to an outcome,
65
+ * or null when it is not one.
66
+ */
67
+ export declare function mapOAuthPopupPayload(data: unknown): PopupOutcome | null;
62
68
  export interface OAuthPopupHandlers {
63
69
  onOpen?: () => void;
64
70
  onComplete?: (r: {
@@ -68,6 +74,14 @@ export interface OAuthPopupHandlers {
68
74
  onError?: (code: string) => void;
69
75
  /** Fired when the popup couldn't open; the caller should navigate to the URL. */
70
76
  onBlockedFallback?: (authorizationUrl: string) => void;
77
+ /**
78
+ * Fired when the popup's link to this page was severed right after opening
79
+ * (this page, or the provider, sends a Cross-Origin-Opener-Policy): the popup
80
+ * still works, but closing it can no longer be noticed, so the flow keeps
81
+ * waiting — up to 5 minutes — for its result. A good moment to show "Finish
82
+ * signing in in the popup window" with a cancel button that aborts `signal`.
83
+ */
84
+ onSevered?: () => void;
71
85
  }
72
86
  export interface PopupStartResult extends PopupOutcome {
73
87
  /** True when the popup was blocked — the caller falls back to a full redirect. */
@@ -81,18 +95,45 @@ export interface PopupStartResult extends PopupOutcome {
81
95
  * cancel.
82
96
  */
83
97
  sessionDetected?: boolean;
98
+ /** True when the popup's opener link was severed (see `onSevered`). */
99
+ severed?: boolean;
100
+ }
101
+ /** Input to {@link startOauthPopup}. */
102
+ export interface OAuthPopupInput {
103
+ provider: string;
104
+ /**
105
+ * Where the redirect flow would return to — normally the current page. A
106
+ * popup whose opener link is severed lands back here (result in the
107
+ * fragment), so it should be a page on THIS origin that runs the SDK.
108
+ */
109
+ redirectUrl: string;
110
+ /** Abort to give up on the popup (settles as `popup_closed`). */
111
+ signal?: AbortSignal;
84
112
  }
113
+ /** `popup.closed` this soon after opening means the opener link was severed, not a user close. */
114
+ export declare const POPUP_SEVERED_WINDOW_MS = 1500;
115
+ /** How long a severed popup is waited for before it counts as cancelled. */
116
+ export declare const POPUP_SEVERED_TIMEOUT_MS: number;
85
117
  /**
86
118
  * Start a POPUP OAuth sign-in (GSI-style). Opens the provider authorize URL in a
87
119
  * popup and resolves when the callback posts back the one-time ticket (complete),
88
120
  * an error, or a continuation. Falls back to a full redirect when the popup is
89
121
  * blocked — resolves `{ blocked:true, authorizationUrl }` and the caller
90
122
  * navigates there, so it is always safe to enable. Browser-only.
123
+ *
124
+ * The result arrives by `postMessage` from the Frontend API, or — when a
125
+ * Cross-Origin-Opener-Policy severed the popup from this page — relayed over
126
+ * `BroadcastChannel('atlas:oauth:<nonce>')` by the SDK on the page the popup
127
+ * lands on (see ./popup-channel). Cancel semantics:
128
+ * - the popup closes after the first {@link POPUP_SEVERED_WINDOW_MS}: the user
129
+ * closed it — one final session probe, then `popup_closed`;
130
+ * - `popup.closed` reads true within that window: the link was severed (the
131
+ * popup is very much open). Keep waiting for the relayed result, probing
132
+ * the session with back-off, and settle as `popup_closed` only after
133
+ * {@link POPUP_SEVERED_TIMEOUT_MS}, an explicit error/cancel result,
134
+ * `input.signal` aborting, or a newer popup flow starting.
91
135
  */
92
- export declare function startOauthPopup(client: FapiClient, input: {
93
- provider: string;
94
- redirectUrl: string;
95
- }, handlers?: OAuthPopupHandlers): Promise<PopupStartResult>;
136
+ export declare function startOauthPopup(client: FapiClient, input: OAuthPopupInput, handlers?: OAuthPopupHandlers): Promise<PopupStartResult>;
96
137
  /**
97
138
  * Read Atlas's redirect params from a query string (`window.location.search`).
98
139
  *
package/dist/redirect.js CHANGED
@@ -15,12 +15,14 @@
15
15
  * the React provider and any custom integration read the exact same contract.
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.REDIRECT_PARAMS = void 0;
18
+ exports.POPUP_SEVERED_TIMEOUT_MS = exports.POPUP_SEVERED_WINDOW_MS = exports.REDIRECT_PARAMS = void 0;
19
19
  exports.startOauthRedirect = startOauthRedirect;
20
20
  exports.parseOAuthPopupMessage = parseOAuthPopupMessage;
21
+ exports.mapOAuthPopupPayload = mapOAuthPopupPayload;
21
22
  exports.startOauthPopup = startOauthPopup;
22
23
  exports.readRedirectResult = readRedirectResult;
23
24
  exports.stripRedirectParams = stripRedirectParams;
25
+ const popup_channel_1 = require("./popup-channel");
24
26
  exports.REDIRECT_PARAMS = ['__atlas_attempt', '__atlas_ticket', '__atlas_status'];
25
27
  /**
26
28
  * Start a redirect-based OAuth sign-in for a provider that has no in-page native
@@ -48,6 +50,14 @@ async function startOauthRedirect(client, input) {
48
50
  function parseOAuthPopupMessage(eventOrigin, expectedOrigin, data) {
49
51
  if (eventOrigin !== expectedOrigin)
50
52
  return null;
53
+ return mapOAuthPopupPayload(data);
54
+ }
55
+ /**
56
+ * Pure: map one of the Frontend API's `atlas:oauth:*` result payloads (from a
57
+ * `postMessage`, or relayed from a severed popup's landing page) to an outcome,
58
+ * or null when it is not one.
59
+ */
60
+ function mapOAuthPopupPayload(data) {
51
61
  if (!data || typeof data !== 'object')
52
62
  return null;
53
63
  const d = data;
@@ -67,6 +77,12 @@ function parseOAuthPopupMessage(eventOrigin, expectedOrigin, data) {
67
77
  return null;
68
78
  }
69
79
  }
80
+ /** `popup.closed` this soon after opening means the opener link was severed, not a user close. */
81
+ exports.POPUP_SEVERED_WINDOW_MS = 1_500;
82
+ /** How long a severed popup is waited for before it counts as cancelled. */
83
+ exports.POPUP_SEVERED_TIMEOUT_MS = 5 * 60_000;
84
+ /** Back-off between session probes while a severed popup is pending. */
85
+ const SEVERED_PROBE_DELAYS_MS = [2_000, 3_000, 5_000, 8_000, 13_000, 21_000, 30_000];
70
86
  function centeredPopupFeatures(w, h) {
71
87
  const dualLeft = (window.screenLeft ?? window.screenX ?? 0);
72
88
  const dualTop = (window.screenTop ?? window.screenY ?? 0);
@@ -76,18 +92,35 @@ function centeredPopupFeatures(w, h) {
76
92
  const top = Math.max(0, dualTop + (vh - h) / 2);
77
93
  return `popup,width=${w},height=${h},left=${Math.round(left)},top=${Math.round(top)}`;
78
94
  }
95
+ /** The popup flow currently waiting in this page; a new one supersedes it. */
96
+ let cancelActivePopup = null;
79
97
  /**
80
98
  * Start a POPUP OAuth sign-in (GSI-style). Opens the provider authorize URL in a
81
99
  * popup and resolves when the callback posts back the one-time ticket (complete),
82
100
  * an error, or a continuation. Falls back to a full redirect when the popup is
83
101
  * blocked — resolves `{ blocked:true, authorizationUrl }` and the caller
84
102
  * navigates there, so it is always safe to enable. Browser-only.
103
+ *
104
+ * The result arrives by `postMessage` from the Frontend API, or — when a
105
+ * Cross-Origin-Opener-Policy severed the popup from this page — relayed over
106
+ * `BroadcastChannel('atlas:oauth:<nonce>')` by the SDK on the page the popup
107
+ * lands on (see ./popup-channel). Cancel semantics:
108
+ * - the popup closes after the first {@link POPUP_SEVERED_WINDOW_MS}: the user
109
+ * closed it — one final session probe, then `popup_closed`;
110
+ * - `popup.closed` reads true within that window: the link was severed (the
111
+ * popup is very much open). Keep waiting for the relayed result, probing
112
+ * the session with back-off, and settle as `popup_closed` only after
113
+ * {@link POPUP_SEVERED_TIMEOUT_MS}, an explicit error/cancel result,
114
+ * `input.signal` aborting, or a newer popup flow starting.
85
115
  */
86
116
  async function startOauthPopup(client, input, handlers = {}) {
117
+ const nonce = (0, popup_channel_1.createPopupNonce)();
87
118
  const res = await client.post('/v1/client/sign_ins/oauth', {
88
119
  provider: input.provider,
89
120
  redirect_url: input.redirectUrl,
90
121
  mode: 'popup',
122
+ popup_nonce: nonce,
123
+ opener_origin: window.location.origin,
91
124
  });
92
125
  const authorizationUrl = res.ok ? res.data?.authorization_url : undefined;
93
126
  if (!authorizationUrl)
@@ -95,7 +128,7 @@ async function startOauthPopup(client, input, handlers = {}) {
95
128
  const expectedOrigin = client.frontendApiOrigin || window.location.origin;
96
129
  let popup = null;
97
130
  try {
98
- popup = window.open(authorizationUrl, 'atlas:oauth', centeredPopupFeatures(500, 650));
131
+ popup = window.open(authorizationUrl, popup_channel_1.OAUTH_POPUP_WINDOW_NAME, centeredPopupFeatures(500, 650));
99
132
  }
100
133
  catch {
101
134
  popup = null;
@@ -104,15 +137,28 @@ async function startOauthPopup(client, input, handlers = {}) {
104
137
  handlers.onBlockedFallback?.(authorizationUrl);
105
138
  return { blocked: true, authorizationUrl };
106
139
  }
140
+ const openedAt = Date.now();
107
141
  handlers.onOpen?.();
142
+ // Only one popup flow at a time: starting another cancels the one waiting.
143
+ cancelActivePopup?.();
108
144
  return await new Promise((resolve) => {
109
145
  let done = false;
146
+ let severed = false;
147
+ let probeTimer;
148
+ let deadline;
149
+ const cancel = () => settle({ error: 'popup_closed' });
110
150
  const settle = (r) => {
111
151
  if (done)
112
152
  return;
113
153
  done = true;
114
154
  window.removeEventListener('message', onMessage);
115
155
  clearInterval(timer);
156
+ clearTimeout(probeTimer);
157
+ clearTimeout(deadline);
158
+ stopListening();
159
+ input.signal?.removeEventListener('abort', cancel);
160
+ if (cancelActivePopup === cancel)
161
+ cancelActivePopup = null;
116
162
  try {
117
163
  if (popup && !popup.closed)
118
164
  popup.close();
@@ -120,11 +166,10 @@ async function startOauthPopup(client, input, handlers = {}) {
120
166
  catch {
121
167
  /* cross-origin close can throw; ignore */
122
168
  }
123
- resolve(r);
169
+ resolve(severed ? { ...r, severed: true } : r);
124
170
  };
125
- const onMessage = (ev) => {
126
- const outcome = parseOAuthPopupMessage(ev.origin, expectedOrigin, ev.data);
127
- if (!outcome)
171
+ const deliver = (outcome) => {
172
+ if (done)
128
173
  return;
129
174
  if (outcome.ticket)
130
175
  handlers.onComplete?.({ ticket: outcome.ticket, attemptId: outcome.attemptId });
@@ -132,21 +177,62 @@ async function startOauthPopup(client, input, handlers = {}) {
132
177
  handlers.onError?.(outcome.error);
133
178
  settle(outcome);
134
179
  };
180
+ const onMessage = (ev) => {
181
+ const outcome = parseOAuthPopupMessage(ev.origin, expectedOrigin, ev.data);
182
+ if (outcome)
183
+ deliver(outcome);
184
+ };
185
+ // A probe that finds a session settles; otherwise `onMiss` decides.
186
+ const probe = (onMiss) => {
187
+ if (done)
188
+ return;
189
+ void probeSession(client).then((signedIn) => {
190
+ if (done)
191
+ return;
192
+ if (signedIn)
193
+ settle({ error: 'popup_closed', sessionDetected: true });
194
+ else
195
+ onMiss();
196
+ });
197
+ };
198
+ const scheduleProbe = (attempt) => {
199
+ const delay = SEVERED_PROBE_DELAYS_MS[Math.min(attempt, SEVERED_PROBE_DELAYS_MS.length - 1)];
200
+ probeTimer = setTimeout(() => probe(() => scheduleProbe(attempt + 1)), delay);
201
+ };
202
+ const stopListening = (0, popup_channel_1.listenForPopupResult)(nonce, {
203
+ onResult: (payload) => {
204
+ const outcome = mapOAuthPopupPayload(payload);
205
+ if (outcome)
206
+ deliver(outcome);
207
+ },
208
+ // A page in the popup finished the sign-in itself: check now.
209
+ onSignedIn: () => probe(() => undefined),
210
+ });
135
211
  // The user closing the popup without finishing is a cancellation, not a hang.
136
- // But a popup can also close (or look closed to us) after completing the
137
- // sign-in itself: when a browser severs `window.opener` (a Cross-Origin-
138
- // Opener-Policy on some hop, a privacy feature), the callback page cannot
139
- // post back and finishes via the ordinary redirect instead, which sets the
140
- // session cookies. So check the session once before calling it a cancel.
141
- let probing = false;
212
+ // But `popup.closed` turning true right after opening is not a close: the
213
+ // opener link was severed (Cross-Origin-Opener-Policy) and the popup is
214
+ // still on screen. Then wait for the relayed result instead.
142
215
  const timer = setInterval(() => {
143
- if (!popup || !popup.closed || probing || done)
216
+ if (!popup || !popup.closed || done)
144
217
  return;
145
- probing = true;
146
218
  clearInterval(timer);
147
- void probeSession(client).then((signedIn) => settle(signedIn ? { error: 'popup_closed', sessionDetected: true } : { error: 'popup_closed' }));
148
- }, 500);
219
+ if (Date.now() - openedAt <= exports.POPUP_SEVERED_WINDOW_MS) {
220
+ severed = true;
221
+ handlers.onSevered?.();
222
+ deadline = setTimeout(cancel, exports.POPUP_SEVERED_TIMEOUT_MS);
223
+ scheduleProbe(0);
224
+ return;
225
+ }
226
+ // A real close. It can still follow a sign-in the popup finished on its
227
+ // own (an opener the browser severed later, mid-flow), so check the
228
+ // session once before calling it a cancel.
229
+ probe(cancel);
230
+ }, 250);
149
231
  window.addEventListener('message', onMessage);
232
+ input.signal?.addEventListener('abort', cancel);
233
+ if (input.signal?.aborted)
234
+ cancel();
235
+ cancelActivePopup = cancel;
150
236
  });
151
237
  }
152
238
  /** One `GET /v1/client`: is there a signed-in session on this browser now? */
@@ -1 +1 @@
1
- {"version":3,"file":"redirect.js","sourceRoot":"","sources":["../src/redirect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"redirect.js","sourceRoot":"","sources":["../src/redirect.ts"],"names":[],"mappings":"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"}