@imtbl/auth-nextjs 2.12.4-alpha.4 → 2.12.4-alpha.6

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
@@ -1,38 +1,58 @@
1
1
  # @imtbl/auth-nextjs
2
2
 
3
- Next.js authentication integration for Immutable SDK using NextAuth.js.
3
+ Next.js App Router authentication integration for Immutable SDK using Auth.js v5.
4
4
 
5
- This package bridges `@imtbl/auth` popup-based authentication with NextAuth.js session management, providing:
5
+ This package bridges `@imtbl/auth` popup-based authentication with Auth.js session management, providing:
6
6
 
7
7
  - Server-side session storage in encrypted JWT cookies
8
8
  - Automatic token refresh on both server and client
9
- - Full SSR support with `getServerSession`
9
+ - Full SSR support with `auth()` function
10
10
  - React hooks for easy client-side authentication
11
+ - Middleware support for protecting routes
12
+
13
+ ## Requirements
14
+
15
+ - Next.js 14+ with App Router
16
+ - Auth.js v5 (next-auth@5.x)
17
+ - React 18+
11
18
 
12
19
  ## Installation
13
20
 
14
21
  ```bash
15
- pnpm add @imtbl/auth-nextjs next-auth
22
+ pnpm add @imtbl/auth-nextjs next-auth@beta
16
23
  ```
17
24
 
18
25
  ## Quick Start
19
26
 
20
- ### 1. Set Up Auth API Route
27
+ ### 1. Create Auth Configuration
21
28
 
22
29
  ```typescript
23
- // pages/api/auth/[...nextauth].ts
24
- import { ImmutableAuth } from "@imtbl/auth-nextjs";
30
+ // lib/auth.ts
31
+ import { createImmutableAuth } from "@imtbl/auth-nextjs";
25
32
 
26
- export default ImmutableAuth({
33
+ const config = {
27
34
  clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
28
35
  redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
29
- });
36
+ };
37
+
38
+ export const { handlers, auth, signIn, signOut } = createImmutableAuth(config);
30
39
  ```
31
40
 
32
- ### 2. Create Callback Page
41
+ ### 2. Set Up Auth API Route
33
42
 
34
43
  ```typescript
35
- // pages/callback.tsx
44
+ // app/api/auth/[...nextauth]/route.ts
45
+ import { handlers } from "@/lib/auth";
46
+
47
+ export const { GET, POST } = handlers;
48
+ ```
49
+
50
+ ### 3. Create Callback Page
51
+
52
+ ```typescript
53
+ // app/callback/page.tsx
54
+ "use client";
55
+
36
56
  import { CallbackPage } from "@imtbl/auth-nextjs/client";
37
57
 
38
58
  const config = {
@@ -45,10 +65,12 @@ export default function Callback() {
45
65
  }
46
66
  ```
47
67
 
48
- ### 3. Add Provider to App
68
+ ### 4. Add Provider to Layout
49
69
 
50
70
  ```typescript
51
- // pages/_app.tsx
71
+ // app/providers.tsx
72
+ "use client";
73
+
52
74
  import { ImmutableAuthProvider } from "@imtbl/auth-nextjs/client";
53
75
 
54
76
  const config = {
@@ -56,21 +78,39 @@ const config = {
56
78
  redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
57
79
  };
58
80
 
59
- export default function App({ Component, pageProps }: AppProps) {
81
+ export function Providers({ children }: { children: React.ReactNode }) {
60
82
  return (
61
- <ImmutableAuthProvider config={config} session={pageProps.session}>
62
- <Component {...pageProps} />
63
- </ImmutableAuthProvider>
83
+ <ImmutableAuthProvider config={config}>{children}</ImmutableAuthProvider>
84
+ );
85
+ }
86
+
87
+ // app/layout.tsx
88
+ import { Providers } from "./providers";
89
+
90
+ export default function RootLayout({
91
+ children,
92
+ }: {
93
+ children: React.ReactNode;
94
+ }) {
95
+ return (
96
+ <html>
97
+ <body>
98
+ <Providers>{children}</Providers>
99
+ </body>
100
+ </html>
64
101
  );
65
102
  }
66
103
  ```
67
104
 
68
- ### 4. Use in Components
105
+ ### 5. Use in Components
69
106
 
70
107
  ```typescript
108
+ // app/components/LoginButton.tsx
109
+ "use client";
110
+
71
111
  import { useImmutableAuth } from "@imtbl/auth-nextjs/client";
72
112
 
73
- function LoginButton() {
113
+ export function LoginButton() {
74
114
  const { user, isLoading, signIn, signOut } = useImmutableAuth();
75
115
 
76
116
  if (isLoading) return <div>Loading...</div>;
@@ -84,52 +124,42 @@ function LoginButton() {
84
124
  );
85
125
  }
86
126
 
87
- return <button onClick={signIn}>Login with Immutable</button>;
127
+ return <button onClick={() => signIn()}>Login with Immutable</button>;
88
128
  }
89
129
  ```
90
130
 
91
- ### 5. Access Session Server-Side (SSR)
131
+ ### 6. Access Session in Server Components
92
132
 
93
133
  ```typescript
94
- // pages/profile.tsx
95
- import { getImmutableSession } from "@imtbl/auth-nextjs/server";
96
- import type { GetServerSideProps } from "next";
134
+ // app/profile/page.tsx
135
+ import { auth } from "@/lib/auth";
136
+ import { redirect } from "next/navigation";
97
137
 
98
- const config = {
99
- clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
100
- redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
101
- };
138
+ export default async function ProfilePage() {
139
+ const session = await auth();
102
140
 
103
- export default function ProfilePage({ user }) {
104
- if (!user) return <p>Not logged in</p>;
105
- return <h1>Welcome, {user.email}</h1>;
106
- }
141
+ if (!session) {
142
+ redirect("/login");
143
+ }
107
144
 
108
- export const getServerSideProps: GetServerSideProps = async (ctx) => {
109
- const session = await getImmutableSession(ctx.req, ctx.res, config);
110
- return { props: { user: session?.user ?? null } };
111
- };
145
+ return <h1>Welcome, {session.user.email}</h1>;
146
+ }
112
147
  ```
113
148
 
114
- ### 6. Protect Pages (Optional)
149
+ ### 7. Protect Routes with Middleware (Optional)
115
150
 
116
151
  ```typescript
117
- // pages/dashboard.tsx
118
- import { withPageAuthRequired } from "@imtbl/auth-nextjs/server";
119
-
120
- const config = {
121
- clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
122
- redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
123
- };
152
+ // middleware.ts
153
+ import { createAuthMiddleware } from "@imtbl/auth-nextjs/server";
154
+ import { auth } from "@/lib/auth";
124
155
 
125
- function DashboardPage() {
126
- return <h1>Dashboard (protected)</h1>;
127
- }
128
-
129
- export default DashboardPage;
156
+ export default createAuthMiddleware(auth, {
157
+ loginUrl: "/login",
158
+ });
130
159
 
131
- // Redirects to /login if not authenticated
132
- export const getServerSideProps = withPageAuthRequired(config);
160
+ export const config = {
161
+ matcher: ["/dashboard/:path*", "/profile/:path*"],
162
+ };
133
163
  ```
134
164
 
135
165
  ## Configuration Options
@@ -152,9 +182,8 @@ The `ImmutableAuthConfig` object accepts the following properties:
152
182
  NEXT_PUBLIC_IMMUTABLE_CLIENT_ID=your-client-id
153
183
  NEXT_PUBLIC_BASE_URL=http://localhost:3000
154
184
 
155
- # Required by NextAuth for cookie encryption
156
- NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32
157
- NEXTAUTH_URL=http://localhost:3000
185
+ # Required by Auth.js for cookie encryption
186
+ AUTH_SECRET=generate-with-openssl-rand-base64-32
158
187
  ```
159
188
 
160
189
  Generate a secret:
@@ -167,99 +196,83 @@ openssl rand -base64 32
167
196
 
168
197
  ### Main Exports (`@imtbl/auth-nextjs`)
169
198
 
170
- | Export | Description |
171
- | ----------------------------------- | ------------------------------------------- |
172
- | `ImmutableAuth(config, overrides?)` | Creates NextAuth handler (use in API route) |
173
- | `refreshAccessToken(token)` | Utility to refresh an expired access token |
174
- | `isTokenExpired(token)` | Utility to check if a token is expired |
199
+ | Export | Description |
200
+ | --------------------------------------- | ------------------------------------------------------------------- |
201
+ | `createImmutableAuth(config, options?)` | Creates Auth.js instance with `{ handlers, auth, signIn, signOut }` |
202
+ | `createAuthConfig(config)` | Creates Auth.js config (for advanced use) |
203
+ | `refreshAccessToken(token, config)` | Utility to refresh an expired access token |
204
+ | `isTokenExpired(expires, buffer?)` | Utility to check if a token is expired |
175
205
 
176
206
  **Types:**
177
207
 
178
- | Type | Description |
179
- | ----------------------------- | ----------------------------------------- |
180
- | `ImmutableAuthConfig` | Configuration options |
181
- | `ImmutableAuthOverrides` | NextAuth options override type |
182
- | `ImmutableUser` | User profile type |
183
- | `ImmutableTokenData` | Token data passed to credentials provider |
184
- | `ZkEvmInfo` | zkEVM wallet information type |
185
- | `WithPageAuthRequiredOptions` | Options for page protection |
208
+ | Type | Description |
209
+ | ------------------------ | ----------------------------------------- |
210
+ | `ImmutableAuthConfig` | Configuration options |
211
+ | `ImmutableAuthOverrides` | Auth.js options override type |
212
+ | `ImmutableAuthResult` | Return type of createImmutableAuth |
213
+ | `ImmutableUser` | User profile type |
214
+ | `ImmutableTokenData` | Token data passed to credentials provider |
215
+ | `ZkEvmInfo` | zkEVM wallet information type |
186
216
 
187
217
  ### Client Exports (`@imtbl/auth-nextjs/client`)
188
218
 
189
- | Export | Description |
190
- | ----------------------- | ------------------------------------------------------- |
191
- | `ImmutableAuthProvider` | React context provider (wraps NextAuth SessionProvider) |
192
- | `useImmutableAuth()` | Hook for authentication state and methods (see below) |
193
- | `useAccessToken()` | Hook returning `getAccessToken` function |
194
- | `CallbackPage` | Pre-built callback page component for OAuth redirects |
219
+ | Export | Description |
220
+ | ----------------------- | ------------------------------------------------------ |
221
+ | `ImmutableAuthProvider` | React context provider (wraps Auth.js SessionProvider) |
222
+ | `useImmutableAuth()` | Hook for authentication state and methods (see below) |
223
+ | `useAccessToken()` | Hook returning `getAccessToken` function |
224
+ | `CallbackPage` | Pre-built callback page component for OAuth redirects |
195
225
 
196
226
  **`useImmutableAuth()` Return Value:**
197
227
 
198
228
  | Property | Type | Description |
199
229
  | ----------------- | ----------------------- | ------------------------------------------------ |
200
230
  | `user` | `ImmutableUser \| null` | Current user profile (null if not authenticated) |
201
- | `session` | `Session \| null` | Full NextAuth session with tokens |
231
+ | `session` | `Session \| null` | Full Auth.js session with tokens |
202
232
  | `isLoading` | `boolean` | Whether authentication state is loading |
203
233
  | `isAuthenticated` | `boolean` | Whether user is authenticated |
204
- | `signIn` | `() => Promise<void>` | Sign in with Immutable (opens popup) |
205
- | `signOut` | `() => Promise<void>` | Sign out from both NextAuth and Immutable |
234
+ | `signIn` | `(options?) => Promise` | Sign in with Immutable (opens popup) |
235
+ | `signOut` | `() => Promise<void>` | Sign out from both Auth.js and Immutable |
206
236
  | `getAccessToken` | `() => Promise<string>` | Get a valid access token (refreshes if needed) |
207
237
  | `auth` | `Auth \| null` | The underlying Auth instance (for advanced use) |
208
238
 
209
- **Types:**
210
-
211
- | Type | Description |
212
- | ---------------------------- | -------------------------------- |
213
- | `ImmutableAuthProviderProps` | Props for the provider component |
214
- | `UseImmutableAuthReturn` | Return type of useImmutableAuth |
215
- | `CallbackPageProps` | Props for CallbackPage component |
216
- | `ImmutableAuthConfig` | Re-exported configuration type |
217
- | `ImmutableUser` | Re-exported user type |
218
-
219
239
  ### Server Exports (`@imtbl/auth-nextjs/server`)
220
240
 
221
- | Export | Description |
222
- | ---------------------------------------- | ---------------------------------------- |
223
- | `getImmutableSession(req, res, config)` | Get session server-side |
224
- | `withPageAuthRequired(config, options?)` | HOC for protecting pages with auth check |
225
-
226
- **`withPageAuthRequired` Options:**
227
-
228
- | Option | Type | Default | Description |
229
- | -------------------- | ----------------------- | ------------ | ---------------------------------------------------- |
230
- | `loginUrl` | `string` | `"/login"` | URL to redirect to when not authenticated |
231
- | `returnTo` | `string \| false` | current page | URL to redirect to after login (`false` to disable) |
232
- | `getServerSideProps` | `(ctx, session) => ...` | - | Custom getServerSideProps that runs after auth check |
233
-
234
- **Example with custom getServerSideProps:**
235
-
236
- ```typescript
237
- export const getServerSideProps = withPageAuthRequired(config, {
238
- loginUrl: "/auth/signin",
239
- async getServerSideProps(ctx, session) {
240
- // session is guaranteed to exist here
241
- const data = await fetchData(session.accessToken);
242
- return { props: { data } };
243
- },
244
- });
245
- ```
241
+ | Export | Description |
242
+ | ----------------------------------- | ------------------------------------------------ |
243
+ | `createImmutableAuth` | Re-exported for convenience |
244
+ | `createAuthMiddleware(auth, opts?)` | Create middleware for protecting routes |
245
+ | `withAuth(auth, handler)` | HOC for protecting Server Actions/Route Handlers |
246
246
 
247
- **Types:**
247
+ **`createAuthMiddleware` Options:**
248
248
 
249
- | Type | Description |
250
- | --------------------------------- | ----------------------------------------- |
251
- | `WithPageAuthRequiredOptions` | Basic options for page protection |
252
- | `WithPageAuthRequiredFullOptions` | Full options including getServerSideProps |
253
- | `WithPageAuthRequiredProps` | Props added to protected pages (session) |
249
+ | Option | Type | Default | Description |
250
+ | ---------------- | ---------------------- | ---------- | -------------------------------------- |
251
+ | `loginUrl` | `string` | `"/login"` | URL to redirect when not authenticated |
252
+ | `protectedPaths` | `(string \| RegExp)[]` | - | Paths that require authentication |
253
+ | `publicPaths` | `(string \| RegExp)[]` | - | Paths to exclude from protection |
254
254
 
255
255
  ## How It Works
256
256
 
257
257
  1. **Login**: User clicks login → `@imtbl/auth` opens popup → tokens returned
258
- 2. **Session Creation**: Tokens passed to NextAuth's credentials provider → stored in encrypted JWT cookie
259
- 3. **Token Refresh**: NextAuth JWT callback automatically refreshes expired tokens using refresh_token
260
- 4. **SSR**: `getServerSession()` reads and decrypts cookie, providing full session with tokens
258
+ 2. **Session Creation**: Tokens passed to Auth.js credentials provider → stored in encrypted JWT cookie
259
+ 3. **Token Refresh**: Auth.js JWT callback automatically refreshes expired tokens using refresh_token
260
+ 4. **SSR**: `auth()` reads and decrypts cookie, providing full session with tokens
261
261
  5. **Auto-hydration**: If localStorage is cleared but session cookie exists, the Auth instance is automatically hydrated from session tokens
262
262
 
263
+ ## Migration from v4 (Pages Router)
264
+
265
+ If you're migrating from the Pages Router version:
266
+
267
+ | v4 (Pages Router) | v5 (App Router) |
268
+ | --------------------------------------- | --------------------------------------------- |
269
+ | `ImmutableAuth(config)` | `createImmutableAuth(config)` |
270
+ | `getImmutableSession(req, res, config)` | `auth()` (from createImmutableAuth) |
271
+ | `withPageAuthRequired(config)` | `createAuthMiddleware(auth)` or layout checks |
272
+ | `pages/api/auth/[...nextauth].ts` | `app/api/auth/[...nextauth]/route.ts` |
273
+ | `pages/_app.tsx` with provider | `app/layout.tsx` with provider |
274
+ | `NEXTAUTH_SECRET` | `AUTH_SECRET` |
275
+
263
276
  ## License
264
277
 
265
278
  Apache-2.0
@@ -1,6 +1,15 @@
1
+ // src/index.ts
2
+ import NextAuthImport from "next-auth";
3
+
4
+ // src/config.ts
5
+ import CredentialsImport from "next-auth/providers/credentials";
6
+
1
7
  // src/constants.ts
2
8
  var DEFAULT_AUTH_DOMAIN = "https://auth.immutable.com";
9
+ var DEFAULT_AUDIENCE = "platform_api";
10
+ var DEFAULT_SCOPE = "openid profile email offline_access transact";
3
11
  var IMMUTABLE_PROVIDER_ID = "immutable";
12
+ var DEFAULT_NEXTAUTH_BASE_PATH = "/api/auth";
4
13
  var DEFAULT_TOKEN_EXPIRY_SECONDS = 900;
5
14
  var DEFAULT_TOKEN_EXPIRY_MS = DEFAULT_TOKEN_EXPIRY_SECONDS * 1e3;
6
15
  var TOKEN_EXPIRY_BUFFER_SECONDS = 60;
@@ -68,8 +77,7 @@ function isTokenExpired(accessTokenExpires, bufferSeconds = TOKEN_EXPIRY_BUFFER_
68
77
  }
69
78
 
70
79
  // src/config.ts
71
- import Credentials from "next-auth/providers/credentials";
72
- var CredentialsProvider = Credentials.default || Credentials;
80
+ var Credentials = CredentialsImport.default || CredentialsImport;
73
81
  async function validateTokens(accessToken, authDomain) {
74
82
  try {
75
83
  const response = await fetch(`${authDomain}/userinfo`, {
@@ -88,18 +96,18 @@ async function validateTokens(accessToken, authDomain) {
88
96
  return null;
89
97
  }
90
98
  }
91
- function createAuthOptions(config) {
99
+ function createAuthConfig(config) {
92
100
  const authDomain = config.authenticationDomain || DEFAULT_AUTH_DOMAIN;
93
101
  return {
94
102
  providers: [
95
- CredentialsProvider({
103
+ Credentials({
96
104
  id: IMMUTABLE_PROVIDER_ID,
97
105
  name: "Immutable",
98
106
  credentials: {
99
107
  tokens: { label: "Tokens", type: "text" }
100
108
  },
101
109
  async authorize(credentials) {
102
- if (!credentials?.tokens) {
110
+ if (!credentials?.tokens || typeof credentials.tokens !== "string") {
103
111
  return null;
104
112
  }
105
113
  let tokenData;
@@ -142,6 +150,7 @@ function createAuthOptions(config) {
142
150
  })
143
151
  ],
144
152
  callbacks: {
153
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
145
154
  async jwt({
146
155
  token,
147
156
  user,
@@ -162,13 +171,14 @@ function createAuthOptions(config) {
162
171
  };
163
172
  }
164
173
  if (trigger === "update" && sessionUpdate) {
174
+ const update = sessionUpdate;
165
175
  return {
166
176
  ...token,
167
- ...sessionUpdate.accessToken && { accessToken: sessionUpdate.accessToken },
168
- ...sessionUpdate.refreshToken && { refreshToken: sessionUpdate.refreshToken },
169
- ...sessionUpdate.idToken && { idToken: sessionUpdate.idToken },
170
- ...sessionUpdate.accessTokenExpires && { accessTokenExpires: sessionUpdate.accessTokenExpires },
171
- ...sessionUpdate.zkEvm && { zkEvm: sessionUpdate.zkEvm }
177
+ ...update.accessToken ? { accessToken: update.accessToken } : {},
178
+ ...update.refreshToken ? { refreshToken: update.refreshToken } : {},
179
+ ...update.idToken ? { idToken: update.idToken } : {},
180
+ ...update.accessTokenExpires ? { accessTokenExpires: update.accessTokenExpires } : {},
181
+ ...update.zkEvm ? { zkEvm: update.zkEvm } : {}
172
182
  };
173
183
  }
174
184
  if (!isTokenExpired(token.accessTokenExpires)) {
@@ -176,10 +186,12 @@ function createAuthOptions(config) {
176
186
  }
177
187
  return refreshAccessToken(token, config);
178
188
  },
189
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
179
190
  async session({ session, token }) {
180
191
  return {
181
192
  ...session,
182
193
  user: {
194
+ ...session.user,
183
195
  sub: token.sub,
184
196
  email: token.email,
185
197
  nickname: token.nickname
@@ -197,14 +209,63 @@ function createAuthOptions(config) {
197
209
  strategy: "jwt",
198
210
  // Session max age in seconds (30 days default)
199
211
  maxAge: DEFAULT_SESSION_MAX_AGE_SECONDS
200
- },
201
- // Use NEXTAUTH_SECRET from environment
202
- secret: process.env.NEXTAUTH_SECRET
212
+ }
213
+ };
214
+ }
215
+
216
+ // src/index.ts
217
+ import { MarketingConsentStatus } from "@imtbl/auth";
218
+ var NextAuth = NextAuthImport.default || NextAuthImport;
219
+ function createImmutableAuth(config, overrides) {
220
+ const authConfig = createAuthConfig(config);
221
+ if (!overrides) {
222
+ return NextAuth(authConfig);
223
+ }
224
+ const composedCallbacks = {
225
+ ...authConfig.callbacks
226
+ };
227
+ if (overrides.callbacks) {
228
+ if (overrides.callbacks.jwt) {
229
+ const internalJwt = authConfig.callbacks?.jwt;
230
+ const userJwt = overrides.callbacks.jwt;
231
+ composedCallbacks.jwt = async (params) => {
232
+ const token = internalJwt ? await internalJwt(params) : params.token;
233
+ return userJwt({ ...params, token });
234
+ };
235
+ }
236
+ if (overrides.callbacks.session) {
237
+ const internalSession = authConfig.callbacks?.session;
238
+ const userSession = overrides.callbacks.session;
239
+ composedCallbacks.session = async (params) => {
240
+ const session = internalSession ? await internalSession(params) : params.session;
241
+ return userSession({ ...params, session });
242
+ };
243
+ }
244
+ if (overrides.callbacks.signIn) {
245
+ composedCallbacks.signIn = overrides.callbacks.signIn;
246
+ }
247
+ if (overrides.callbacks.redirect) {
248
+ composedCallbacks.redirect = overrides.callbacks.redirect;
249
+ }
250
+ }
251
+ const mergedConfig = {
252
+ ...authConfig,
253
+ ...overrides,
254
+ callbacks: composedCallbacks
203
255
  };
256
+ return NextAuth(mergedConfig);
204
257
  }
258
+ var ImmutableAuth = createImmutableAuth;
205
259
 
206
260
  export {
261
+ DEFAULT_AUTH_DOMAIN,
262
+ DEFAULT_AUDIENCE,
263
+ DEFAULT_SCOPE,
264
+ DEFAULT_NEXTAUTH_BASE_PATH,
207
265
  refreshAccessToken,
208
266
  isTokenExpired,
209
- createAuthOptions
267
+ createAuthConfig,
268
+ createImmutableAuth,
269
+ ImmutableAuth,
270
+ MarketingConsentStatus
210
271
  };
@@ -23,6 +23,7 @@ var client_exports = {};
23
23
  __export(client_exports, {
24
24
  CallbackPage: () => CallbackPage,
25
25
  ImmutableAuthProvider: () => ImmutableAuthProvider,
26
+ MarketingConsentStatus: () => import_auth4.MarketingConsentStatus,
26
27
  useAccessToken: () => useAccessToken,
27
28
  useImmutableAuth: () => useImmutableAuth
28
29
  });
@@ -176,11 +177,11 @@ function useImmutableAuth() {
176
177
  email: session.user.email,
177
178
  nickname: session.user.nickname
178
179
  } : null;
179
- const handleSignIn = (0, import_react.useCallback)(async () => {
180
+ const handleSignIn = (0, import_react.useCallback)(async (options) => {
180
181
  if (!auth) {
181
182
  throw new Error("Auth not initialized");
182
183
  }
183
- const authUser = await auth.login();
184
+ const authUser = await auth.login(options);
184
185
  if (!authUser) {
185
186
  throw new Error("Login failed");
186
187
  }
@@ -253,7 +254,7 @@ function useAccessToken() {
253
254
 
254
255
  // src/client/callback.tsx
255
256
  var import_react3 = require("react");
256
- var import_router = require("next/router");
257
+ var import_navigation = require("next/navigation");
257
258
  var import_react4 = require("next-auth/react");
258
259
  var import_auth3 = require("@imtbl/auth");
259
260
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -263,7 +264,8 @@ function CallbackPage({
263
264
  loadingComponent = null,
264
265
  errorComponent
265
266
  }) {
266
- const router = (0, import_router.useRouter)();
267
+ const router = (0, import_navigation.useRouter)();
268
+ const searchParams = (0, import_navigation.useSearchParams)();
267
269
  const [error, setError] = (0, import_react3.useState)(null);
268
270
  const callbackProcessedRef = (0, import_react3.useRef)(false);
269
271
  (0, import_react3.useEffect)(() => {
@@ -315,31 +317,20 @@ function CallbackPage({
315
317
  }
316
318
  };
317
319
  const handleOAuthError = () => {
318
- const errorCode = router.query.error;
319
- const errorDescription = router.query.error_description;
320
+ const errorCode = searchParams.get("error");
321
+ const errorDescription = searchParams.get("error_description");
320
322
  const errorMessage = errorDescription || errorCode || "Authentication failed";
321
323
  setError(errorMessage);
322
324
  };
323
- if (!router.isReady) {
324
- return;
325
- }
326
- if (router.query.error) {
325
+ if (searchParams.get("error")) {
327
326
  handleOAuthError();
328
327
  return;
329
328
  }
330
- if (router.query.code && !callbackProcessedRef.current) {
329
+ if (searchParams.get("code") && !callbackProcessedRef.current) {
331
330
  callbackProcessedRef.current = true;
332
331
  handleCallback();
333
332
  }
334
- }, [
335
- router.isReady,
336
- router.query.code,
337
- router.query.error,
338
- router.query.error_description,
339
- router,
340
- config,
341
- redirectTo
342
- ]);
333
+ }, [searchParams, router, config, redirectTo]);
343
334
  if (error) {
344
335
  if (errorComponent) {
345
336
  return errorComponent(error);
@@ -351,6 +342,7 @@ function CallbackPage({
351
342
  "button",
352
343
  {
353
344
  onClick: () => router.push("/"),
345
+ type: "button",
354
346
  style: {
355
347
  padding: "0.5rem 1rem",
356
348
  marginTop: "1rem",
@@ -366,10 +358,14 @@ function CallbackPage({
366
358
  }
367
359
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "2rem", textAlign: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: "Completing authentication..." }) });
368
360
  }
361
+
362
+ // src/client/index.ts
363
+ var import_auth4 = require("@imtbl/auth");
369
364
  // Annotate the CommonJS export names for ESM import in node:
370
365
  0 && (module.exports = {
371
366
  CallbackPage,
372
367
  ImmutableAuthProvider,
368
+ MarketingConsentStatus,
373
369
  useAccessToken,
374
370
  useImmutableAuth
375
371
  });