@imtbl/auth-nextjs 2.12.4-alpha.6 → 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 +75 -9
- package/dist/node/{chunk-BRDI4KXS.js → chunk-BLU3AV4X.js} +3 -0
- package/dist/node/client/index.cjs +56 -10
- package/dist/node/client/index.js +56 -10
- package/dist/node/index.cjs +3 -0
- package/dist/node/index.js +1 -1
- package/dist/node/server/index.cjs +3 -0
- package/dist/node/server/index.js +1 -1
- package/dist/types/client/callback.d.ts +33 -4
- package/dist/types/types.d.ts +6 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -61,10 +61,12 @@ const config = {
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
export default function Callback() {
|
|
64
|
-
return <CallbackPage config={config} />;
|
|
64
|
+
return <CallbackPage config={config} redirectTo="/dashboard" />;
|
|
65
65
|
}
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
+
See [CallbackPage Props](#callbackpage-props) for all available options.
|
|
69
|
+
|
|
68
70
|
### 4. Add Provider to Layout
|
|
69
71
|
|
|
70
72
|
```typescript
|
|
@@ -166,14 +168,15 @@ export const config = {
|
|
|
166
168
|
|
|
167
169
|
The `ImmutableAuthConfig` object accepts the following properties:
|
|
168
170
|
|
|
169
|
-
| Property | Type | Required | Default | Description
|
|
170
|
-
| ---------------------- | -------- | -------- | ------------------------------------------------ |
|
|
171
|
-
| `clientId` | `string` | Yes | - | Immutable OAuth client ID
|
|
172
|
-
| `redirectUri` | `string` | Yes | - | OAuth callback redirect URI
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
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 |
|
|
177
180
|
|
|
178
181
|
## Environment Variables
|
|
179
182
|
|
|
@@ -223,6 +226,69 @@ openssl rand -base64 32
|
|
|
223
226
|
| `useAccessToken()` | Hook returning `getAccessToken` function |
|
|
224
227
|
| `CallbackPage` | Pre-built callback page component for OAuth redirects |
|
|
225
228
|
|
|
229
|
+
#### CallbackPage Props
|
|
230
|
+
|
|
231
|
+
| Prop | Type | Default | Description |
|
|
232
|
+
| ------------------ | ----------------------------------------------------- | ------- | ------------------------------------------------------------------ |
|
|
233
|
+
| `config` | `ImmutableAuthConfig` | - | Required. Immutable auth configuration |
|
|
234
|
+
| `redirectTo` | `string \| ((user: ImmutableUser) => string \| void)` | `"/"` | Where to redirect after successful auth (supports dynamic routing) |
|
|
235
|
+
| `loadingComponent` | `React.ReactElement \| null` | `null` | Custom loading UI while processing authentication |
|
|
236
|
+
| `errorComponent` | `(error: string) => React.ReactElement \| null` | - | Custom error UI component |
|
|
237
|
+
| `onSuccess` | `(user: ImmutableUser) => void \| Promise<void>` | - | Callback fired after successful authentication |
|
|
238
|
+
| `onError` | `(error: string) => void` | - | Callback fired when authentication fails |
|
|
239
|
+
|
|
240
|
+
**Example with all props:**
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
// app/callback/page.tsx
|
|
244
|
+
"use client";
|
|
245
|
+
|
|
246
|
+
import { CallbackPage } from "@imtbl/auth-nextjs/client";
|
|
247
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
248
|
+
|
|
249
|
+
const config = {
|
|
250
|
+
clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
|
|
251
|
+
redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export default function Callback() {
|
|
255
|
+
return (
|
|
256
|
+
<CallbackPage
|
|
257
|
+
config={config}
|
|
258
|
+
// Dynamic redirect based on user
|
|
259
|
+
redirectTo={(user) => {
|
|
260
|
+
if (user.email?.endsWith("@admin.com")) return "/admin";
|
|
261
|
+
return "/dashboard";
|
|
262
|
+
}}
|
|
263
|
+
// Custom loading UI
|
|
264
|
+
loadingComponent={
|
|
265
|
+
<div className="flex items-center justify-center min-h-screen">
|
|
266
|
+
<Spinner />
|
|
267
|
+
<span>Completing authentication...</span>
|
|
268
|
+
</div>
|
|
269
|
+
}
|
|
270
|
+
// Custom error UI
|
|
271
|
+
errorComponent={(error) => (
|
|
272
|
+
<div className="text-center p-8">
|
|
273
|
+
<h2 className="text-red-500">Authentication Error</h2>
|
|
274
|
+
<p>{error}</p>
|
|
275
|
+
<a href="/">Return Home</a>
|
|
276
|
+
</div>
|
|
277
|
+
)}
|
|
278
|
+
// Success callback for analytics
|
|
279
|
+
onSuccess={async (user) => {
|
|
280
|
+
await analytics.track("login_success", { userId: user.sub });
|
|
281
|
+
}}
|
|
282
|
+
// Error callback for logging
|
|
283
|
+
onError={(error) => {
|
|
284
|
+
console.error("Auth failed:", error);
|
|
285
|
+
Sentry.captureMessage(error);
|
|
286
|
+
}}
|
|
287
|
+
/>
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
226
292
|
**`useImmutableAuth()` Return Value:**
|
|
227
293
|
|
|
228
294
|
| Property | Type | Description |
|
|
@@ -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;
|
|
@@ -262,7 +269,9 @@ function CallbackPage({
|
|
|
262
269
|
config,
|
|
263
270
|
redirectTo = "/",
|
|
264
271
|
loadingComponent = null,
|
|
265
|
-
errorComponent
|
|
272
|
+
errorComponent,
|
|
273
|
+
onSuccess,
|
|
274
|
+
onError
|
|
266
275
|
}) {
|
|
267
276
|
const router = (0, import_navigation.useRouter)();
|
|
268
277
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
@@ -284,6 +293,14 @@ function CallbackPage({
|
|
|
284
293
|
if (!authUser) {
|
|
285
294
|
throw new Error("Authentication failed: no user data received from login callback");
|
|
286
295
|
}
|
|
296
|
+
const user = {
|
|
297
|
+
sub: authUser.profile.sub,
|
|
298
|
+
email: authUser.profile.email,
|
|
299
|
+
nickname: authUser.profile.nickname
|
|
300
|
+
};
|
|
301
|
+
if (onSuccess) {
|
|
302
|
+
await onSuccess(user);
|
|
303
|
+
}
|
|
287
304
|
window.close();
|
|
288
305
|
} else if (authUser) {
|
|
289
306
|
const tokenData = {
|
|
@@ -308,29 +325,58 @@ function CallbackPage({
|
|
|
308
325
|
if (!result?.ok) {
|
|
309
326
|
throw new Error("NextAuth sign-in failed: unknown error");
|
|
310
327
|
}
|
|
311
|
-
|
|
328
|
+
const user = {
|
|
329
|
+
sub: authUser.profile.sub,
|
|
330
|
+
email: authUser.profile.email,
|
|
331
|
+
nickname: authUser.profile.nickname
|
|
332
|
+
};
|
|
333
|
+
if (onSuccess) {
|
|
334
|
+
await onSuccess(user);
|
|
335
|
+
}
|
|
336
|
+
const resolvedRedirectTo = typeof redirectTo === "function" ? redirectTo(user) || "/" : redirectTo;
|
|
337
|
+
router.replace(resolvedRedirectTo);
|
|
312
338
|
} else {
|
|
313
339
|
throw new Error("Authentication failed: no user data received from login callback");
|
|
314
340
|
}
|
|
315
341
|
} catch (err) {
|
|
316
|
-
|
|
342
|
+
const errorMessage2 = err instanceof Error ? err.message : "Authentication failed";
|
|
343
|
+
if (onError) {
|
|
344
|
+
onError(errorMessage2);
|
|
345
|
+
}
|
|
346
|
+
setError(errorMessage2);
|
|
317
347
|
}
|
|
318
348
|
};
|
|
319
349
|
const handleOAuthError = () => {
|
|
320
350
|
const errorCode = searchParams.get("error");
|
|
321
351
|
const errorDescription = searchParams.get("error_description");
|
|
322
|
-
const
|
|
323
|
-
|
|
352
|
+
const errorMessage2 = errorDescription || errorCode || "Authentication failed";
|
|
353
|
+
if (onError) {
|
|
354
|
+
onError(errorMessage2);
|
|
355
|
+
}
|
|
356
|
+
setError(errorMessage2);
|
|
324
357
|
};
|
|
325
|
-
if (
|
|
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;
|
|
326
365
|
handleOAuthError();
|
|
327
366
|
return;
|
|
328
367
|
}
|
|
329
|
-
if (
|
|
368
|
+
if (hasCode) {
|
|
330
369
|
callbackProcessedRef.current = true;
|
|
331
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);
|
|
332
377
|
}
|
|
333
|
-
|
|
378
|
+
setError(errorMessage);
|
|
379
|
+
}, [searchParams, router, config, redirectTo, onSuccess, onError]);
|
|
334
380
|
if (error) {
|
|
335
381
|
if (errorComponent) {
|
|
336
382
|
return errorComponent(error);
|
|
@@ -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;
|
|
@@ -248,7 +255,9 @@ function CallbackPage({
|
|
|
248
255
|
config,
|
|
249
256
|
redirectTo = "/",
|
|
250
257
|
loadingComponent = null,
|
|
251
|
-
errorComponent
|
|
258
|
+
errorComponent,
|
|
259
|
+
onSuccess,
|
|
260
|
+
onError
|
|
252
261
|
}) {
|
|
253
262
|
const router = useRouter();
|
|
254
263
|
const searchParams = useSearchParams();
|
|
@@ -270,6 +279,14 @@ function CallbackPage({
|
|
|
270
279
|
if (!authUser) {
|
|
271
280
|
throw new Error("Authentication failed: no user data received from login callback");
|
|
272
281
|
}
|
|
282
|
+
const user = {
|
|
283
|
+
sub: authUser.profile.sub,
|
|
284
|
+
email: authUser.profile.email,
|
|
285
|
+
nickname: authUser.profile.nickname
|
|
286
|
+
};
|
|
287
|
+
if (onSuccess) {
|
|
288
|
+
await onSuccess(user);
|
|
289
|
+
}
|
|
273
290
|
window.close();
|
|
274
291
|
} else if (authUser) {
|
|
275
292
|
const tokenData = {
|
|
@@ -294,29 +311,58 @@ function CallbackPage({
|
|
|
294
311
|
if (!result?.ok) {
|
|
295
312
|
throw new Error("NextAuth sign-in failed: unknown error");
|
|
296
313
|
}
|
|
297
|
-
|
|
314
|
+
const user = {
|
|
315
|
+
sub: authUser.profile.sub,
|
|
316
|
+
email: authUser.profile.email,
|
|
317
|
+
nickname: authUser.profile.nickname
|
|
318
|
+
};
|
|
319
|
+
if (onSuccess) {
|
|
320
|
+
await onSuccess(user);
|
|
321
|
+
}
|
|
322
|
+
const resolvedRedirectTo = typeof redirectTo === "function" ? redirectTo(user) || "/" : redirectTo;
|
|
323
|
+
router.replace(resolvedRedirectTo);
|
|
298
324
|
} else {
|
|
299
325
|
throw new Error("Authentication failed: no user data received from login callback");
|
|
300
326
|
}
|
|
301
327
|
} catch (err) {
|
|
302
|
-
|
|
328
|
+
const errorMessage2 = err instanceof Error ? err.message : "Authentication failed";
|
|
329
|
+
if (onError) {
|
|
330
|
+
onError(errorMessage2);
|
|
331
|
+
}
|
|
332
|
+
setError(errorMessage2);
|
|
303
333
|
}
|
|
304
334
|
};
|
|
305
335
|
const handleOAuthError = () => {
|
|
306
336
|
const errorCode = searchParams.get("error");
|
|
307
337
|
const errorDescription = searchParams.get("error_description");
|
|
308
|
-
const
|
|
309
|
-
|
|
338
|
+
const errorMessage2 = errorDescription || errorCode || "Authentication failed";
|
|
339
|
+
if (onError) {
|
|
340
|
+
onError(errorMessage2);
|
|
341
|
+
}
|
|
342
|
+
setError(errorMessage2);
|
|
310
343
|
};
|
|
311
|
-
if (
|
|
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;
|
|
312
351
|
handleOAuthError();
|
|
313
352
|
return;
|
|
314
353
|
}
|
|
315
|
-
if (
|
|
354
|
+
if (hasCode) {
|
|
316
355
|
callbackProcessedRef.current = true;
|
|
317
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);
|
|
318
363
|
}
|
|
319
|
-
|
|
364
|
+
setError(errorMessage);
|
|
365
|
+
}, [searchParams, router, config, redirectTo, onSuccess, onError]);
|
|
320
366
|
if (error) {
|
|
321
367
|
if (errorComponent) {
|
|
322
368
|
return errorComponent(error);
|
package/dist/node/index.cjs
CHANGED
|
@@ -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,
|
package/dist/node/index.js
CHANGED
|
@@ -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,14 +1,30 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { ImmutableAuthConfig } from '../types';
|
|
2
|
+
import type { ImmutableAuthConfig, ImmutableUser } from '../types';
|
|
3
3
|
export interface CallbackPageProps {
|
|
4
4
|
/**
|
|
5
5
|
* Immutable auth configuration
|
|
6
6
|
*/
|
|
7
7
|
config: ImmutableAuthConfig;
|
|
8
8
|
/**
|
|
9
|
-
* URL to redirect to after successful authentication (when not in popup)
|
|
9
|
+
* URL to redirect to after successful authentication (when not in popup).
|
|
10
|
+
* Can be a string or a function that receives the authenticated user.
|
|
11
|
+
* If a function returns void/undefined, defaults to "/".
|
|
12
|
+
* @default "/"
|
|
13
|
+
*
|
|
14
|
+
* @example Static redirect
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <CallbackPage config={config} redirectTo="/dashboard" />
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example Dynamic redirect based on user
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <CallbackPage
|
|
22
|
+
* config={config}
|
|
23
|
+
* redirectTo={(user) => user.email?.endsWith('@admin.com') ? '/admin' : '/dashboard'}
|
|
24
|
+
* />
|
|
25
|
+
* ```
|
|
10
26
|
*/
|
|
11
|
-
redirectTo?: string;
|
|
27
|
+
redirectTo?: string | ((user: ImmutableUser) => string | void);
|
|
12
28
|
/**
|
|
13
29
|
* Custom loading component
|
|
14
30
|
*/
|
|
@@ -17,6 +33,19 @@ export interface CallbackPageProps {
|
|
|
17
33
|
* Custom error component
|
|
18
34
|
*/
|
|
19
35
|
errorComponent?: (error: string) => React.ReactElement | null;
|
|
36
|
+
/**
|
|
37
|
+
* Callback fired after successful authentication.
|
|
38
|
+
* Receives the authenticated user as a parameter.
|
|
39
|
+
* Called before redirect (non-popup) or before window.close (popup).
|
|
40
|
+
* If this callback returns a Promise, it will be awaited before proceeding.
|
|
41
|
+
*/
|
|
42
|
+
onSuccess?: (user: ImmutableUser) => void | Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Callback fired when authentication fails.
|
|
45
|
+
* Receives the error message as a parameter.
|
|
46
|
+
* Called before the error UI is displayed.
|
|
47
|
+
*/
|
|
48
|
+
onError?: (error: string) => void;
|
|
20
49
|
}
|
|
21
50
|
/**
|
|
22
51
|
* Callback page component for handling OAuth redirects (App Router version).
|
|
@@ -39,4 +68,4 @@ export interface CallbackPageProps {
|
|
|
39
68
|
* }
|
|
40
69
|
* ```
|
|
41
70
|
*/
|
|
42
|
-
export declare function CallbackPage({ config, redirectTo, loadingComponent, errorComponent, }: CallbackPageProps): import("react/jsx-runtime").JSX.Element | null;
|
|
71
|
+
export declare function CallbackPage({ config, redirectTo, loadingComponent, errorComponent, onSuccess, onError, }: CallbackPageProps): import("react/jsx-runtime").JSX.Element | null;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -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.
|
|
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.
|
|
54
|
+
"@imtbl/auth": "2.12.4-alpha.8"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"next": "14.2.25",
|