@lovable.dev/cloud-auth-js 1.2.1 → 1.2.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 CHANGED
@@ -7,11 +7,26 @@ const DEFAULT_MOBILE_DEEP_LINK_REDIRECT_URI = "lovable://oauth-callback";
7
7
  const DEFAULT_DESKTOP_LOCALHOST_REDIRECT_URI = "http://127.0.0.1/iframe-oauth/callback";
8
8
  const POPUP_CHECK_INTERVAL_MS = 500;
9
9
  const IFRAME_FALLBACK_TIMEOUT_MS = 12e4;
10
+ const POPUP_RESULT_TIMEOUT_MS = 3e5;
10
11
  const MOBILE_APP_SCHEME_UA_TOKEN = /LovableAppScheme\/([a-z0-9.+-]+)/i;
11
12
  function mobileDeepLinkRedirectUri(ua) {
12
13
  const scheme = MOBILE_APP_SCHEME_UA_TOKEN.exec(ua)?.[1];
13
14
  return scheme ? `${scheme}://oauth-callback` : DEFAULT_MOBILE_DEEP_LINK_REDIRECT_URI;
14
15
  }
16
+ function sameOriginRedirectUri(redirectUri) {
17
+ const pageOrigin = window.location.origin;
18
+ if (pageOrigin === "null") return redirectUri;
19
+ let parsed;
20
+ try {
21
+ parsed = new URL(redirectUri, window.location.href);
22
+ } catch {
23
+ return redirectUri;
24
+ }
25
+ if (parsed.origin === pageOrigin) return redirectUri;
26
+ const rewritten = `${pageOrigin}${parsed.pathname}${parsed.search}${parsed.hash}`;
27
+ console.warn(`[cloud-auth-js] redirect_uri origin ${parsed.origin} differs from the page origin ${pageOrigin}; using ${rewritten} so the popup result can reach this window`);
28
+ return rewritten;
29
+ }
15
30
  function startWebMessageListener(supportedOrigins) {
16
31
  let resolvePromise;
17
32
  const promise = new Promise((resolve) => {
@@ -86,6 +101,8 @@ function createAuth(config = {}) {
86
101
  let redirectUri = opts.redirect_uri ?? window.location.origin;
87
102
  if (isMobileApp && isInIframe) redirectUri = mobileDeepLinkRedirectUri(ua);
88
103
  else if (isDesktopApp && isInIframe) redirectUri = DEFAULT_DESKTOP_LOCALHOST_REDIRECT_URI;
104
+ const useWebMessage = isInIframe && !isMobileApp && !isDesktopApp;
105
+ if (useWebMessage) redirectUri = sameOriginRedirectUri(redirectUri);
89
106
  const params = new URLSearchParams({
90
107
  ...opts.extraParams,
91
108
  provider,
@@ -99,7 +116,7 @@ function createAuth(config = {}) {
99
116
  redirected: true
100
117
  };
101
118
  }
102
- if (!isMobileApp && !isDesktopApp) params.set("response_mode", "web_message");
119
+ if (useWebMessage) params.set("response_mode", "web_message");
103
120
  const url = `${oauthBrokerUrl}?${params.toString()}`;
104
121
  const { messagePromise, cleanup } = startWebMessageListener(isDesktopApp ? [...supportedOAuthOrigins, window.location.origin] : supportedOAuthOrigins);
105
122
  let popup;
@@ -137,11 +154,22 @@ function createAuth(config = {}) {
137
154
  }
138
155
  }, POPUP_CHECK_INTERVAL_MS);
139
156
  });
157
+ let resultTimeoutId;
158
+ const resultTimeoutPromise = new Promise((_, reject) => {
159
+ resultTimeoutId = setTimeout(() => {
160
+ reject(/* @__PURE__ */ new Error("Sign-in timed out waiting for the sign-in window. If it is still open, finish there, or open the app in a new browser tab to sign in."));
161
+ }, POPUP_RESULT_TIMEOUT_MS);
162
+ });
140
163
  try {
141
- return processOAuthResponse(await Promise.race([messagePromise, popupClosedPromise]), state);
164
+ return processOAuthResponse(await Promise.race([
165
+ messagePromise,
166
+ popupClosedPromise,
167
+ resultTimeoutPromise
168
+ ]), state);
142
169
  } catch (error) {
143
170
  return { error: error instanceof Error ? error : new Error(String(error)) };
144
171
  } finally {
172
+ clearTimeout(resultTimeoutId);
145
173
  clearInterval(popupCheckInterval);
146
174
  cleanup();
147
175
  popup?.close();
package/dist/index.js CHANGED
@@ -6,11 +6,26 @@ const DEFAULT_MOBILE_DEEP_LINK_REDIRECT_URI = "lovable://oauth-callback";
6
6
  const DEFAULT_DESKTOP_LOCALHOST_REDIRECT_URI = "http://127.0.0.1/iframe-oauth/callback";
7
7
  const POPUP_CHECK_INTERVAL_MS = 500;
8
8
  const IFRAME_FALLBACK_TIMEOUT_MS = 12e4;
9
+ const POPUP_RESULT_TIMEOUT_MS = 3e5;
9
10
  const MOBILE_APP_SCHEME_UA_TOKEN = /LovableAppScheme\/([a-z0-9.+-]+)/i;
10
11
  function mobileDeepLinkRedirectUri(ua) {
11
12
  const scheme = MOBILE_APP_SCHEME_UA_TOKEN.exec(ua)?.[1];
12
13
  return scheme ? `${scheme}://oauth-callback` : DEFAULT_MOBILE_DEEP_LINK_REDIRECT_URI;
13
14
  }
15
+ function sameOriginRedirectUri(redirectUri) {
16
+ const pageOrigin = window.location.origin;
17
+ if (pageOrigin === "null") return redirectUri;
18
+ let parsed;
19
+ try {
20
+ parsed = new URL(redirectUri, window.location.href);
21
+ } catch {
22
+ return redirectUri;
23
+ }
24
+ if (parsed.origin === pageOrigin) return redirectUri;
25
+ const rewritten = `${pageOrigin}${parsed.pathname}${parsed.search}${parsed.hash}`;
26
+ console.warn(`[cloud-auth-js] redirect_uri origin ${parsed.origin} differs from the page origin ${pageOrigin}; using ${rewritten} so the popup result can reach this window`);
27
+ return rewritten;
28
+ }
14
29
  function startWebMessageListener(supportedOrigins) {
15
30
  let resolvePromise;
16
31
  const promise = new Promise((resolve) => {
@@ -85,6 +100,8 @@ function createAuth(config = {}) {
85
100
  let redirectUri = opts.redirect_uri ?? window.location.origin;
86
101
  if (isMobileApp && isInIframe) redirectUri = mobileDeepLinkRedirectUri(ua);
87
102
  else if (isDesktopApp && isInIframe) redirectUri = DEFAULT_DESKTOP_LOCALHOST_REDIRECT_URI;
103
+ const useWebMessage = isInIframe && !isMobileApp && !isDesktopApp;
104
+ if (useWebMessage) redirectUri = sameOriginRedirectUri(redirectUri);
88
105
  const params = new URLSearchParams({
89
106
  ...opts.extraParams,
90
107
  provider,
@@ -98,7 +115,7 @@ function createAuth(config = {}) {
98
115
  redirected: true
99
116
  };
100
117
  }
101
- if (!isMobileApp && !isDesktopApp) params.set("response_mode", "web_message");
118
+ if (useWebMessage) params.set("response_mode", "web_message");
102
119
  const url = `${oauthBrokerUrl}?${params.toString()}`;
103
120
  const { messagePromise, cleanup } = startWebMessageListener(isDesktopApp ? [...supportedOAuthOrigins, window.location.origin] : supportedOAuthOrigins);
104
121
  let popup;
@@ -136,11 +153,22 @@ function createAuth(config = {}) {
136
153
  }
137
154
  }, POPUP_CHECK_INTERVAL_MS);
138
155
  });
156
+ let resultTimeoutId;
157
+ const resultTimeoutPromise = new Promise((_, reject) => {
158
+ resultTimeoutId = setTimeout(() => {
159
+ reject(/* @__PURE__ */ new Error("Sign-in timed out waiting for the sign-in window. If it is still open, finish there, or open the app in a new browser tab to sign in."));
160
+ }, POPUP_RESULT_TIMEOUT_MS);
161
+ });
139
162
  try {
140
- return processOAuthResponse(await Promise.race([messagePromise, popupClosedPromise]), state);
163
+ return processOAuthResponse(await Promise.race([
164
+ messagePromise,
165
+ popupClosedPromise,
166
+ resultTimeoutPromise
167
+ ]), state);
141
168
  } catch (error) {
142
169
  return { error: error instanceof Error ? error : new Error(String(error)) };
143
170
  } finally {
171
+ clearTimeout(resultTimeoutId);
144
172
  clearInterval(popupCheckInterval);
145
173
  cleanup();
146
174
  popup?.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/cloud-auth-js",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Lovable legacy OAuth broker JS",
5
5
  "repository": {
6
6
  "type": "git",
@@ -55,7 +55,7 @@
55
55
  "check:package": "tmp=$(mktemp -d) && pnpm pack --out \"$tmp/pkg.tgz\" && tar -xzf \"$tmp/pkg.tgz\" -C \"$tmp\" && publint \"$tmp/package\" --strict && attw \"$tmp/pkg.tgz\"",
56
56
  "dev": "tsdown --watch",
57
57
  "test": "vitest run",
58
- "typecheck": "tsgo --noEmit",
58
+ "typecheck": "tsc --noEmit",
59
59
  "clean": "rimraf dist"
60
60
  }
61
61
  }
package/styles.css CHANGED
@@ -8,14 +8,14 @@
8
8
  }
9
9
 
10
10
  .lovable-auth-button {
11
- position: relative;
12
11
  display: inline-flex;
13
12
  min-width: 220px;
14
13
  min-height: 44px;
15
14
  align-items: center;
16
15
  justify-content: center;
16
+ gap: 8px;
17
17
  box-sizing: border-box;
18
- padding: 10px 40px;
18
+ padding: 10px 16px;
19
19
  border: 1px solid #c5cad3;
20
20
  border-radius: 8px;
21
21
  appearance: none;
@@ -31,8 +31,7 @@
31
31
  }
32
32
 
33
33
  .lovable-auth-button::before {
34
- position: absolute;
35
- inset-inline-start: 16px;
34
+ flex: none;
36
35
  width: 16px;
37
36
  height: 17px;
38
37
  background: url("./assets/lovable-mark.svg") center / contain no-repeat;