@imtbl/auth-nextjs 2.12.4-alpha.7 → 2.12.4-alpha.8

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
@@ -168,14 +168,15 @@ export const config = {
168
168
 
169
169
  The `ImmutableAuthConfig` object accepts the following properties:
170
170
 
171
- | Property | Type | Required | Default | Description |
172
- | ---------------------- | -------- | -------- | ------------------------------------------------ | ------------------------------ |
173
- | `clientId` | `string` | Yes | - | Immutable OAuth client ID |
174
- | `redirectUri` | `string` | Yes | - | OAuth callback redirect URI |
175
- | `logoutRedirectUri` | `string` | No | - | Where to redirect after logout |
176
- | `audience` | `string` | No | `"platform_api"` | OAuth audience |
177
- | `scope` | `string` | No | `"openid profile email offline_access transact"` | OAuth scopes |
178
- | `authenticationDomain` | `string` | No | `"https://auth.immutable.com"` | Authentication domain |
171
+ | Property | Type | Required | Default | Description |
172
+ | ---------------------- | -------- | -------- | ------------------------------------------------ | ----------------------------------------------- |
173
+ | `clientId` | `string` | Yes | - | Immutable OAuth client ID |
174
+ | `redirectUri` | `string` | Yes | - | OAuth callback redirect URI (for redirect flow) |
175
+ | `popupRedirectUri` | `string` | No | `redirectUri` | OAuth callback redirect URI for popup flow |
176
+ | `logoutRedirectUri` | `string` | No | - | Where to redirect after logout |
177
+ | `audience` | `string` | No | `"platform_api"` | OAuth audience |
178
+ | `scope` | `string` | No | `"openid profile email offline_access transact"` | OAuth scopes |
179
+ | `authenticationDomain` | `string` | No | `"https://auth.immutable.com"` | Authentication domain |
179
180
 
180
181
  ## Environment Variables
181
182
 
@@ -247,6 +247,9 @@ function createImmutableAuth(config, overrides) {
247
247
  if (overrides.callbacks.redirect) {
248
248
  composedCallbacks.redirect = overrides.callbacks.redirect;
249
249
  }
250
+ if (overrides.callbacks.authorized) {
251
+ composedCallbacks.authorized = overrides.callbacks.authorized;
252
+ }
250
253
  }
251
254
  const mergedConfig = {
252
255
  ...authConfig,
@@ -76,22 +76,24 @@ function ImmutableAuthInner({
76
76
  const [isAuthReady, setIsAuthReady] = (0, import_react.useState)(false);
77
77
  const { data: session, update: updateSession } = (0, import_react2.useSession)();
78
78
  (0, import_react.useEffect)(() => {
79
- if (typeof window === "undefined") return;
79
+ if (typeof window === "undefined") return void 0;
80
80
  const configKey = [
81
81
  config.clientId,
82
82
  config.redirectUri,
83
+ config.popupRedirectUri || "",
83
84
  config.logoutRedirectUri || "",
84
85
  config.audience || DEFAULT_AUDIENCE,
85
86
  config.scope || DEFAULT_SCOPE,
86
87
  config.authenticationDomain || DEFAULT_AUTH_DOMAIN
87
88
  ].join(":");
88
89
  if (prevConfigRef.current === configKey) {
89
- return;
90
+ return void 0;
90
91
  }
91
92
  prevConfigRef.current = configKey;
92
93
  const newAuth = new import_auth2.Auth({
93
94
  clientId: config.clientId,
94
95
  redirectUri: config.redirectUri,
96
+ popupRedirectUri: config.popupRedirectUri,
95
97
  logoutRedirectUri: config.logoutRedirectUri,
96
98
  audience: config.audience || DEFAULT_AUDIENCE,
97
99
  scope: config.scope || DEFAULT_SCOPE,
@@ -99,6 +101,11 @@ function ImmutableAuthInner({
99
101
  });
100
102
  setAuth(newAuth);
101
103
  setIsAuthReady(true);
104
+ return () => {
105
+ setAuth(null);
106
+ setIsAuthReady(false);
107
+ prevConfigRef.current = null;
108
+ };
102
109
  }, [config]);
103
110
  (0, import_react.useEffect)(() => {
104
111
  if (!auth || !isAuthReady) return;
@@ -332,30 +339,43 @@ function CallbackPage({
332
339
  throw new Error("Authentication failed: no user data received from login callback");
333
340
  }
334
341
  } catch (err) {
335
- const errorMessage = err instanceof Error ? err.message : "Authentication failed";
342
+ const errorMessage2 = err instanceof Error ? err.message : "Authentication failed";
336
343
  if (onError) {
337
- onError(errorMessage);
344
+ onError(errorMessage2);
338
345
  }
339
- setError(errorMessage);
346
+ setError(errorMessage2);
340
347
  }
341
348
  };
342
349
  const handleOAuthError = () => {
343
350
  const errorCode = searchParams.get("error");
344
351
  const errorDescription = searchParams.get("error_description");
345
- const errorMessage = errorDescription || errorCode || "Authentication failed";
352
+ const errorMessage2 = errorDescription || errorCode || "Authentication failed";
346
353
  if (onError) {
347
- onError(errorMessage);
354
+ onError(errorMessage2);
348
355
  }
349
- setError(errorMessage);
356
+ setError(errorMessage2);
350
357
  };
351
- if (searchParams.get("error")) {
358
+ if (callbackProcessedRef.current) {
359
+ return;
360
+ }
361
+ const hasError = searchParams.get("error");
362
+ const hasCode = searchParams.get("code");
363
+ if (hasError) {
364
+ callbackProcessedRef.current = true;
352
365
  handleOAuthError();
353
366
  return;
354
367
  }
355
- if (searchParams.get("code") && !callbackProcessedRef.current) {
368
+ if (hasCode) {
356
369
  callbackProcessedRef.current = true;
357
370
  handleCallback();
371
+ return;
372
+ }
373
+ callbackProcessedRef.current = true;
374
+ const errorMessage = "Invalid callback: missing OAuth parameters. Please try logging in again.";
375
+ if (onError) {
376
+ onError(errorMessage);
358
377
  }
378
+ setError(errorMessage);
359
379
  }, [searchParams, router, config, redirectTo, onSuccess, onError]);
360
380
  if (error) {
361
381
  if (errorComponent) {
@@ -62,22 +62,24 @@ function ImmutableAuthInner({
62
62
  const [isAuthReady, setIsAuthReady] = useState(false);
63
63
  const { data: session, update: updateSession } = useSession();
64
64
  useEffect(() => {
65
- if (typeof window === "undefined") return;
65
+ if (typeof window === "undefined") return void 0;
66
66
  const configKey = [
67
67
  config.clientId,
68
68
  config.redirectUri,
69
+ config.popupRedirectUri || "",
69
70
  config.logoutRedirectUri || "",
70
71
  config.audience || DEFAULT_AUDIENCE,
71
72
  config.scope || DEFAULT_SCOPE,
72
73
  config.authenticationDomain || DEFAULT_AUTH_DOMAIN
73
74
  ].join(":");
74
75
  if (prevConfigRef.current === configKey) {
75
- return;
76
+ return void 0;
76
77
  }
77
78
  prevConfigRef.current = configKey;
78
79
  const newAuth = new Auth({
79
80
  clientId: config.clientId,
80
81
  redirectUri: config.redirectUri,
82
+ popupRedirectUri: config.popupRedirectUri,
81
83
  logoutRedirectUri: config.logoutRedirectUri,
82
84
  audience: config.audience || DEFAULT_AUDIENCE,
83
85
  scope: config.scope || DEFAULT_SCOPE,
@@ -85,6 +87,11 @@ function ImmutableAuthInner({
85
87
  });
86
88
  setAuth(newAuth);
87
89
  setIsAuthReady(true);
90
+ return () => {
91
+ setAuth(null);
92
+ setIsAuthReady(false);
93
+ prevConfigRef.current = null;
94
+ };
88
95
  }, [config]);
89
96
  useEffect(() => {
90
97
  if (!auth || !isAuthReady) return;
@@ -318,30 +325,43 @@ function CallbackPage({
318
325
  throw new Error("Authentication failed: no user data received from login callback");
319
326
  }
320
327
  } catch (err) {
321
- const errorMessage = err instanceof Error ? err.message : "Authentication failed";
328
+ const errorMessage2 = err instanceof Error ? err.message : "Authentication failed";
322
329
  if (onError) {
323
- onError(errorMessage);
330
+ onError(errorMessage2);
324
331
  }
325
- setError(errorMessage);
332
+ setError(errorMessage2);
326
333
  }
327
334
  };
328
335
  const handleOAuthError = () => {
329
336
  const errorCode = searchParams.get("error");
330
337
  const errorDescription = searchParams.get("error_description");
331
- const errorMessage = errorDescription || errorCode || "Authentication failed";
338
+ const errorMessage2 = errorDescription || errorCode || "Authentication failed";
332
339
  if (onError) {
333
- onError(errorMessage);
340
+ onError(errorMessage2);
334
341
  }
335
- setError(errorMessage);
342
+ setError(errorMessage2);
336
343
  };
337
- if (searchParams.get("error")) {
344
+ if (callbackProcessedRef.current) {
345
+ return;
346
+ }
347
+ const hasError = searchParams.get("error");
348
+ const hasCode = searchParams.get("code");
349
+ if (hasError) {
350
+ callbackProcessedRef.current = true;
338
351
  handleOAuthError();
339
352
  return;
340
353
  }
341
- if (searchParams.get("code") && !callbackProcessedRef.current) {
354
+ if (hasCode) {
342
355
  callbackProcessedRef.current = true;
343
356
  handleCallback();
357
+ return;
358
+ }
359
+ callbackProcessedRef.current = true;
360
+ const errorMessage = "Invalid callback: missing OAuth parameters. Please try logging in again.";
361
+ if (onError) {
362
+ onError(errorMessage);
344
363
  }
364
+ setError(errorMessage);
345
365
  }, [searchParams, router, config, redirectTo, onSuccess, onError]);
346
366
  if (error) {
347
367
  if (errorComponent) {
@@ -290,6 +290,9 @@ function createImmutableAuth(config, overrides) {
290
290
  if (overrides.callbacks.redirect) {
291
291
  composedCallbacks.redirect = overrides.callbacks.redirect;
292
292
  }
293
+ if (overrides.callbacks.authorized) {
294
+ composedCallbacks.authorized = overrides.callbacks.authorized;
295
+ }
293
296
  }
294
297
  const mergedConfig = {
295
298
  ...authConfig,
@@ -9,7 +9,7 @@ import {
9
9
  createImmutableAuth,
10
10
  isTokenExpired,
11
11
  refreshAccessToken
12
- } from "./chunk-BRDI4KXS.js";
12
+ } from "./chunk-BLU3AV4X.js";
13
13
  export {
14
14
  DEFAULT_AUDIENCE,
15
15
  DEFAULT_AUTH_DOMAIN,
@@ -284,6 +284,9 @@ function createImmutableAuth(config, overrides) {
284
284
  if (overrides.callbacks.redirect) {
285
285
  composedCallbacks.redirect = overrides.callbacks.redirect;
286
286
  }
287
+ if (overrides.callbacks.authorized) {
288
+ composedCallbacks.authorized = overrides.callbacks.authorized;
289
+ }
287
290
  }
288
291
  const mergedConfig = {
289
292
  ...authConfig,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createAuthConfig,
3
3
  createImmutableAuth
4
- } from "../chunk-BRDI4KXS.js";
4
+ } from "../chunk-BLU3AV4X.js";
5
5
 
6
6
  // src/server/index.ts
7
7
  import { NextResponse } from "next/server";
@@ -9,9 +9,14 @@ export interface ImmutableAuthConfig {
9
9
  */
10
10
  clientId: string;
11
11
  /**
12
- * OAuth callback redirect URI
12
+ * OAuth callback redirect URI (used for redirect flow)
13
13
  */
14
14
  redirectUri: string;
15
+ /**
16
+ * OAuth callback redirect URI for popup flow
17
+ * If not provided, falls back to redirectUri
18
+ */
19
+ popupRedirectUri?: string;
15
20
  /**
16
21
  * Where to redirect after logout
17
22
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imtbl/auth-nextjs",
3
- "version": "2.12.4-alpha.7",
3
+ "version": "2.12.4-alpha.8",
4
4
  "description": "Next.js App Router authentication integration for Immutable SDK using Auth.js v5",
5
5
  "author": "Immutable",
6
6
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",
@@ -51,7 +51,7 @@
51
51
  "dist"
52
52
  ],
53
53
  "dependencies": {
54
- "@imtbl/auth": "2.12.4-alpha.7"
54
+ "@imtbl/auth": "2.12.4-alpha.8"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "next": "14.2.25",