@imtbl/auth-nextjs 2.12.4-alpha.5 → 2.12.4-alpha.7
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 +199 -121
- package/dist/node/{chunk-OPPMGNFZ.js → chunk-BRDI4KXS.js} +75 -14
- package/dist/node/client/index.cjs +38 -21
- package/dist/node/client/index.js +37 -20
- package/dist/node/index.cjs +39 -21
- package/dist/node/index.js +15 -46
- package/dist/node/server/index.cjs +107 -59
- package/dist/node/server/index.js +48 -47
- package/dist/types/client/callback.d.ts +42 -8
- package/dist/types/client/provider.d.ts +20 -6
- package/dist/types/config.d.ts +9 -11
- package/dist/types/index.d.ts +28 -14
- package/dist/types/refresh.d.ts +1 -1
- package/dist/types/server/index.d.ts +104 -2
- package/dist/types/types.d.ts +19 -32
- 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 = {
|
|
@@ -41,14 +61,18 @@ const config = {
|
|
|
41
61
|
};
|
|
42
62
|
|
|
43
63
|
export default function Callback() {
|
|
44
|
-
return <CallbackPage config={config} />;
|
|
64
|
+
return <CallbackPage config={config} redirectTo="/dashboard" />;
|
|
45
65
|
}
|
|
46
66
|
```
|
|
47
67
|
|
|
48
|
-
|
|
68
|
+
See [CallbackPage Props](#callbackpage-props) for all available options.
|
|
69
|
+
|
|
70
|
+
### 4. Add Provider to Layout
|
|
49
71
|
|
|
50
72
|
```typescript
|
|
51
|
-
//
|
|
73
|
+
// app/providers.tsx
|
|
74
|
+
"use client";
|
|
75
|
+
|
|
52
76
|
import { ImmutableAuthProvider } from "@imtbl/auth-nextjs/client";
|
|
53
77
|
|
|
54
78
|
const config = {
|
|
@@ -56,21 +80,39 @@ const config = {
|
|
|
56
80
|
redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
|
|
57
81
|
};
|
|
58
82
|
|
|
59
|
-
export
|
|
83
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
84
|
+
return (
|
|
85
|
+
<ImmutableAuthProvider config={config}>{children}</ImmutableAuthProvider>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// app/layout.tsx
|
|
90
|
+
import { Providers } from "./providers";
|
|
91
|
+
|
|
92
|
+
export default function RootLayout({
|
|
93
|
+
children,
|
|
94
|
+
}: {
|
|
95
|
+
children: React.ReactNode;
|
|
96
|
+
}) {
|
|
60
97
|
return (
|
|
61
|
-
<
|
|
62
|
-
<
|
|
63
|
-
|
|
98
|
+
<html>
|
|
99
|
+
<body>
|
|
100
|
+
<Providers>{children}</Providers>
|
|
101
|
+
</body>
|
|
102
|
+
</html>
|
|
64
103
|
);
|
|
65
104
|
}
|
|
66
105
|
```
|
|
67
106
|
|
|
68
|
-
###
|
|
107
|
+
### 5. Use in Components
|
|
69
108
|
|
|
70
109
|
```typescript
|
|
110
|
+
// app/components/LoginButton.tsx
|
|
111
|
+
"use client";
|
|
112
|
+
|
|
71
113
|
import { useImmutableAuth } from "@imtbl/auth-nextjs/client";
|
|
72
114
|
|
|
73
|
-
function LoginButton() {
|
|
115
|
+
export function LoginButton() {
|
|
74
116
|
const { user, isLoading, signIn, signOut } = useImmutableAuth();
|
|
75
117
|
|
|
76
118
|
if (isLoading) return <div>Loading...</div>;
|
|
@@ -84,52 +126,42 @@ function LoginButton() {
|
|
|
84
126
|
);
|
|
85
127
|
}
|
|
86
128
|
|
|
87
|
-
return <button onClick={signIn}>Login with Immutable</button>;
|
|
129
|
+
return <button onClick={() => signIn()}>Login with Immutable</button>;
|
|
88
130
|
}
|
|
89
131
|
```
|
|
90
132
|
|
|
91
|
-
###
|
|
133
|
+
### 6. Access Session in Server Components
|
|
92
134
|
|
|
93
135
|
```typescript
|
|
94
|
-
//
|
|
95
|
-
import {
|
|
96
|
-
import
|
|
136
|
+
// app/profile/page.tsx
|
|
137
|
+
import { auth } from "@/lib/auth";
|
|
138
|
+
import { redirect } from "next/navigation";
|
|
97
139
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
|
|
101
|
-
};
|
|
140
|
+
export default async function ProfilePage() {
|
|
141
|
+
const session = await auth();
|
|
102
142
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
143
|
+
if (!session) {
|
|
144
|
+
redirect("/login");
|
|
145
|
+
}
|
|
107
146
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return { props: { user: session?.user ?? null } };
|
|
111
|
-
};
|
|
147
|
+
return <h1>Welcome, {session.user.email}</h1>;
|
|
148
|
+
}
|
|
112
149
|
```
|
|
113
150
|
|
|
114
|
-
###
|
|
151
|
+
### 7. Protect Routes with Middleware (Optional)
|
|
115
152
|
|
|
116
153
|
```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
|
-
};
|
|
124
|
-
|
|
125
|
-
function DashboardPage() {
|
|
126
|
-
return <h1>Dashboard (protected)</h1>;
|
|
127
|
-
}
|
|
154
|
+
// middleware.ts
|
|
155
|
+
import { createAuthMiddleware } from "@imtbl/auth-nextjs/server";
|
|
156
|
+
import { auth } from "@/lib/auth";
|
|
128
157
|
|
|
129
|
-
export default
|
|
158
|
+
export default createAuthMiddleware(auth, {
|
|
159
|
+
loginUrl: "/login",
|
|
160
|
+
});
|
|
130
161
|
|
|
131
|
-
|
|
132
|
-
|
|
162
|
+
export const config = {
|
|
163
|
+
matcher: ["/dashboard/:path*", "/profile/:path*"],
|
|
164
|
+
};
|
|
133
165
|
```
|
|
134
166
|
|
|
135
167
|
## Configuration Options
|
|
@@ -152,9 +184,8 @@ The `ImmutableAuthConfig` object accepts the following properties:
|
|
|
152
184
|
NEXT_PUBLIC_IMMUTABLE_CLIENT_ID=your-client-id
|
|
153
185
|
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
154
186
|
|
|
155
|
-
# Required by
|
|
156
|
-
|
|
157
|
-
NEXTAUTH_URL=http://localhost:3000
|
|
187
|
+
# Required by Auth.js for cookie encryption
|
|
188
|
+
AUTH_SECRET=generate-with-openssl-rand-base64-32
|
|
158
189
|
```
|
|
159
190
|
|
|
160
191
|
Generate a secret:
|
|
@@ -167,99 +198,146 @@ openssl rand -base64 32
|
|
|
167
198
|
|
|
168
199
|
### Main Exports (`@imtbl/auth-nextjs`)
|
|
169
200
|
|
|
170
|
-
| Export
|
|
171
|
-
|
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
201
|
+
| Export | Description |
|
|
202
|
+
| --------------------------------------- | ------------------------------------------------------------------- |
|
|
203
|
+
| `createImmutableAuth(config, options?)` | Creates Auth.js instance with `{ handlers, auth, signIn, signOut }` |
|
|
204
|
+
| `createAuthConfig(config)` | Creates Auth.js config (for advanced use) |
|
|
205
|
+
| `refreshAccessToken(token, config)` | Utility to refresh an expired access token |
|
|
206
|
+
| `isTokenExpired(expires, buffer?)` | Utility to check if a token is expired |
|
|
175
207
|
|
|
176
208
|
**Types:**
|
|
177
209
|
|
|
178
|
-
| Type
|
|
179
|
-
|
|
|
180
|
-
| `ImmutableAuthConfig`
|
|
181
|
-
| `ImmutableAuthOverrides`
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
210
|
+
| Type | Description |
|
|
211
|
+
| ------------------------ | ----------------------------------------- |
|
|
212
|
+
| `ImmutableAuthConfig` | Configuration options |
|
|
213
|
+
| `ImmutableAuthOverrides` | Auth.js options override type |
|
|
214
|
+
| `ImmutableAuthResult` | Return type of createImmutableAuth |
|
|
215
|
+
| `ImmutableUser` | User profile type |
|
|
216
|
+
| `ImmutableTokenData` | Token data passed to credentials provider |
|
|
217
|
+
| `ZkEvmInfo` | zkEVM wallet information type |
|
|
186
218
|
|
|
187
219
|
### Client Exports (`@imtbl/auth-nextjs/client`)
|
|
188
220
|
|
|
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
|
|
221
|
+
| Export | Description |
|
|
222
|
+
| ----------------------- | ------------------------------------------------------ |
|
|
223
|
+
| `ImmutableAuthProvider` | React context provider (wraps Auth.js SessionProvider) |
|
|
224
|
+
| `useImmutableAuth()` | Hook for authentication state and methods (see below) |
|
|
225
|
+
| `useAccessToken()` | Hook returning `getAccessToken` function |
|
|
226
|
+
| `CallbackPage` | Pre-built callback page component for OAuth redirects |
|
|
227
|
+
|
|
228
|
+
#### CallbackPage Props
|
|
229
|
+
|
|
230
|
+
| Prop | Type | Default | Description |
|
|
231
|
+
| ------------------ | ----------------------------------------------------- | ------- | ------------------------------------------------------------------ |
|
|
232
|
+
| `config` | `ImmutableAuthConfig` | - | Required. Immutable auth configuration |
|
|
233
|
+
| `redirectTo` | `string \| ((user: ImmutableUser) => string \| void)` | `"/"` | Where to redirect after successful auth (supports dynamic routing) |
|
|
234
|
+
| `loadingComponent` | `React.ReactElement \| null` | `null` | Custom loading UI while processing authentication |
|
|
235
|
+
| `errorComponent` | `(error: string) => React.ReactElement \| null` | - | Custom error UI component |
|
|
236
|
+
| `onSuccess` | `(user: ImmutableUser) => void \| Promise<void>` | - | Callback fired after successful authentication |
|
|
237
|
+
| `onError` | `(error: string) => void` | - | Callback fired when authentication fails |
|
|
238
|
+
|
|
239
|
+
**Example with all props:**
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
// app/callback/page.tsx
|
|
243
|
+
"use client";
|
|
244
|
+
|
|
245
|
+
import { CallbackPage } from "@imtbl/auth-nextjs/client";
|
|
246
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
247
|
+
|
|
248
|
+
const config = {
|
|
249
|
+
clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
|
|
250
|
+
redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
export default function Callback() {
|
|
254
|
+
return (
|
|
255
|
+
<CallbackPage
|
|
256
|
+
config={config}
|
|
257
|
+
// Dynamic redirect based on user
|
|
258
|
+
redirectTo={(user) => {
|
|
259
|
+
if (user.email?.endsWith("@admin.com")) return "/admin";
|
|
260
|
+
return "/dashboard";
|
|
261
|
+
}}
|
|
262
|
+
// Custom loading UI
|
|
263
|
+
loadingComponent={
|
|
264
|
+
<div className="flex items-center justify-center min-h-screen">
|
|
265
|
+
<Spinner />
|
|
266
|
+
<span>Completing authentication...</span>
|
|
267
|
+
</div>
|
|
268
|
+
}
|
|
269
|
+
// Custom error UI
|
|
270
|
+
errorComponent={(error) => (
|
|
271
|
+
<div className="text-center p-8">
|
|
272
|
+
<h2 className="text-red-500">Authentication Error</h2>
|
|
273
|
+
<p>{error}</p>
|
|
274
|
+
<a href="/">Return Home</a>
|
|
275
|
+
</div>
|
|
276
|
+
)}
|
|
277
|
+
// Success callback for analytics
|
|
278
|
+
onSuccess={async (user) => {
|
|
279
|
+
await analytics.track("login_success", { userId: user.sub });
|
|
280
|
+
}}
|
|
281
|
+
// Error callback for logging
|
|
282
|
+
onError={(error) => {
|
|
283
|
+
console.error("Auth failed:", error);
|
|
284
|
+
Sentry.captureMessage(error);
|
|
285
|
+
}}
|
|
286
|
+
/>
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
```
|
|
195
290
|
|
|
196
291
|
**`useImmutableAuth()` Return Value:**
|
|
197
292
|
|
|
198
293
|
| Property | Type | Description |
|
|
199
294
|
| ----------------- | ----------------------- | ------------------------------------------------ |
|
|
200
295
|
| `user` | `ImmutableUser \| null` | Current user profile (null if not authenticated) |
|
|
201
|
-
| `session` | `Session \| null` | Full
|
|
296
|
+
| `session` | `Session \| null` | Full Auth.js session with tokens |
|
|
202
297
|
| `isLoading` | `boolean` | Whether authentication state is loading |
|
|
203
298
|
| `isAuthenticated` | `boolean` | Whether user is authenticated |
|
|
204
|
-
| `signIn` | `() => Promise
|
|
205
|
-
| `signOut` | `() => Promise<void>` | Sign out from both
|
|
299
|
+
| `signIn` | `(options?) => Promise` | Sign in with Immutable (opens popup) |
|
|
300
|
+
| `signOut` | `() => Promise<void>` | Sign out from both Auth.js and Immutable |
|
|
206
301
|
| `getAccessToken` | `() => Promise<string>` | Get a valid access token (refreshes if needed) |
|
|
207
302
|
| `auth` | `Auth \| null` | The underlying Auth instance (for advanced use) |
|
|
208
303
|
|
|
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
304
|
### Server Exports (`@imtbl/auth-nextjs/server`)
|
|
220
305
|
|
|
221
|
-
| Export
|
|
222
|
-
|
|
|
223
|
-
| `
|
|
224
|
-
| `
|
|
225
|
-
|
|
226
|
-
**`withPageAuthRequired` Options:**
|
|
306
|
+
| Export | Description |
|
|
307
|
+
| ----------------------------------- | ------------------------------------------------ |
|
|
308
|
+
| `createImmutableAuth` | Re-exported for convenience |
|
|
309
|
+
| `createAuthMiddleware(auth, opts?)` | Create middleware for protecting routes |
|
|
310
|
+
| `withAuth(auth, handler)` | HOC for protecting Server Actions/Route Handlers |
|
|
227
311
|
|
|
228
|
-
|
|
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 |
|
|
312
|
+
**`createAuthMiddleware` Options:**
|
|
233
313
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
```
|
|
246
|
-
|
|
247
|
-
**Types:**
|
|
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) |
|
|
314
|
+
| Option | Type | Default | Description |
|
|
315
|
+
| ---------------- | ---------------------- | ---------- | -------------------------------------- |
|
|
316
|
+
| `loginUrl` | `string` | `"/login"` | URL to redirect when not authenticated |
|
|
317
|
+
| `protectedPaths` | `(string \| RegExp)[]` | - | Paths that require authentication |
|
|
318
|
+
| `publicPaths` | `(string \| RegExp)[]` | - | Paths to exclude from protection |
|
|
254
319
|
|
|
255
320
|
## How It Works
|
|
256
321
|
|
|
257
322
|
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**: `
|
|
323
|
+
2. **Session Creation**: Tokens passed to Auth.js credentials provider → stored in encrypted JWT cookie
|
|
324
|
+
3. **Token Refresh**: Auth.js JWT callback automatically refreshes expired tokens using refresh_token
|
|
325
|
+
4. **SSR**: `auth()` reads and decrypts cookie, providing full session with tokens
|
|
261
326
|
5. **Auto-hydration**: If localStorage is cleared but session cookie exists, the Auth instance is automatically hydrated from session tokens
|
|
262
327
|
|
|
328
|
+
## Migration from v4 (Pages Router)
|
|
329
|
+
|
|
330
|
+
If you're migrating from the Pages Router version:
|
|
331
|
+
|
|
332
|
+
| v4 (Pages Router) | v5 (App Router) |
|
|
333
|
+
| --------------------------------------- | --------------------------------------------- |
|
|
334
|
+
| `ImmutableAuth(config)` | `createImmutableAuth(config)` |
|
|
335
|
+
| `getImmutableSession(req, res, config)` | `auth()` (from createImmutableAuth) |
|
|
336
|
+
| `withPageAuthRequired(config)` | `createAuthMiddleware(auth)` or layout checks |
|
|
337
|
+
| `pages/api/auth/[...nextauth].ts` | `app/api/auth/[...nextauth]/route.ts` |
|
|
338
|
+
| `pages/_app.tsx` with provider | `app/layout.tsx` with provider |
|
|
339
|
+
| `NEXTAUTH_SECRET` | `AUTH_SECRET` |
|
|
340
|
+
|
|
263
341
|
## License
|
|
264
342
|
|
|
265
343
|
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
|
};
|