@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 +133 -120
- package/dist/node/{chunk-OPPMGNFZ.js → chunk-BRDI4KXS.js} +75 -14
- package/dist/node/client/index.cjs +16 -20
- package/dist/node/client/index.js +17 -20
- package/dist/node/index.cjs +42 -21
- package/dist/node/index.js +16 -45
- package/dist/node/server/index.cjs +107 -59
- package/dist/node/server/index.js +48 -47
- package/dist/types/client/callback.d.ts +9 -4
- package/dist/types/client/index.d.ts +2 -0
- package/dist/types/client/provider.d.ts +20 -6
- package/dist/types/config.d.ts +9 -11
- package/dist/types/index.d.ts +30 -14
- package/dist/types/refresh.d.ts +1 -1
- package/dist/types/server/index.d.ts +104 -2
- package/dist/types/types.d.ts +21 -33
- package/package.json +5 -5
- package/dist/types/server/with-page-auth.d.ts +0 -94
package/README.md
CHANGED
|
@@ -1,38 +1,58 @@
|
|
|
1
1
|
# @imtbl/auth-nextjs
|
|
2
2
|
|
|
3
|
-
Next.js authentication integration for Immutable SDK using
|
|
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
|
|
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 `
|
|
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.
|
|
27
|
+
### 1. Create Auth Configuration
|
|
21
28
|
|
|
22
29
|
```typescript
|
|
23
|
-
//
|
|
24
|
-
import {
|
|
30
|
+
// lib/auth.ts
|
|
31
|
+
import { createImmutableAuth } from "@imtbl/auth-nextjs";
|
|
25
32
|
|
|
26
|
-
|
|
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.
|
|
41
|
+
### 2. Set Up Auth API Route
|
|
33
42
|
|
|
34
43
|
```typescript
|
|
35
|
-
//
|
|
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
|
-
###
|
|
68
|
+
### 4. Add Provider to Layout
|
|
49
69
|
|
|
50
70
|
```typescript
|
|
51
|
-
//
|
|
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
|
|
81
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
60
82
|
return (
|
|
61
|
-
<ImmutableAuthProvider config={config}
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
###
|
|
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
|
-
###
|
|
131
|
+
### 6. Access Session in Server Components
|
|
92
132
|
|
|
93
133
|
```typescript
|
|
94
|
-
//
|
|
95
|
-
import {
|
|
96
|
-
import
|
|
134
|
+
// app/profile/page.tsx
|
|
135
|
+
import { auth } from "@/lib/auth";
|
|
136
|
+
import { redirect } from "next/navigation";
|
|
97
137
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
|
|
101
|
-
};
|
|
138
|
+
export default async function ProfilePage() {
|
|
139
|
+
const session = await auth();
|
|
102
140
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
141
|
+
if (!session) {
|
|
142
|
+
redirect("/login");
|
|
143
|
+
}
|
|
107
144
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return { props: { user: session?.user ?? null } };
|
|
111
|
-
};
|
|
145
|
+
return <h1>Welcome, {session.user.email}</h1>;
|
|
146
|
+
}
|
|
112
147
|
```
|
|
113
148
|
|
|
114
|
-
###
|
|
149
|
+
### 7. Protect Routes with Middleware (Optional)
|
|
115
150
|
|
|
116
151
|
```typescript
|
|
117
|
-
//
|
|
118
|
-
import {
|
|
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
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export default DashboardPage;
|
|
156
|
+
export default createAuthMiddleware(auth, {
|
|
157
|
+
loginUrl: "/login",
|
|
158
|
+
});
|
|
130
159
|
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
156
|
-
|
|
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
|
|
171
|
-
|
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
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
|
|
179
|
-
|
|
|
180
|
-
| `ImmutableAuthConfig`
|
|
181
|
-
| `ImmutableAuthOverrides`
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
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
|
|
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
|
|
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
|
|
205
|
-
| `signOut` | `() => Promise<void>` | Sign out from both
|
|
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
|
|
222
|
-
|
|
|
223
|
-
| `
|
|
224
|
-
| `
|
|
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
|
-
|
|
247
|
+
**`createAuthMiddleware` Options:**
|
|
248
248
|
|
|
249
|
-
| Type
|
|
250
|
-
|
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
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
|
|
259
|
-
3. **Token Refresh**:
|
|
260
|
-
4. **SSR**: `
|
|
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
|
-
|
|
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
|
|
99
|
+
function createAuthConfig(config) {
|
|
92
100
|
const authDomain = config.authenticationDomain || DEFAULT_AUTH_DOMAIN;
|
|
93
101
|
return {
|
|
94
102
|
providers: [
|
|
95
|
-
|
|
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
|
-
...
|
|
168
|
-
...
|
|
169
|
-
...
|
|
170
|
-
...
|
|
171
|
-
...
|
|
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
|
-
|
|
202
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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 =
|
|
319
|
-
const errorDescription =
|
|
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 (
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
326
|
-
if (router.query.error) {
|
|
325
|
+
if (searchParams.get("error")) {
|
|
327
326
|
handleOAuthError();
|
|
328
327
|
return;
|
|
329
328
|
}
|
|
330
|
-
if (
|
|
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
|
});
|