@solvapay/next 1.1.0 → 1.2.0-preview-e89fa52f99b6d0c7bf9834fcf2d1403141051fa0
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 +13 -0
- package/dist/chunk-WSXIXEUB.js +134 -0
- package/dist/index.cjs +87 -26
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/middleware.cjs +87 -26
- package/dist/middleware.d.cts +44 -134
- package/dist/middleware.d.ts +44 -134
- package/dist/middleware.js +3 -1
- package/package.json +4 -4
- package/dist/chunk-F7TBIH6W.js +0 -74
package/README.md
CHANGED
|
@@ -69,6 +69,19 @@ export const middleware = createSupabaseAuthMiddleware({
|
|
|
69
69
|
export const config = { matcher: ['/api/:path*'] }
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
Auth0 has the same high-level API:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { createAuth0AuthMiddleware } from '@solvapay/next/middleware'
|
|
76
|
+
import { auth0 } from './lib/auth0'
|
|
77
|
+
|
|
78
|
+
export const proxy = createAuth0AuthMiddleware({ auth0 })
|
|
79
|
+
|
|
80
|
+
export const config = {
|
|
81
|
+
matcher: ['/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)'],
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
72
85
|
Next.js 16 renamed middleware to proxy — use `@solvapay/next/middleware` and export `proxy` instead of `middleware` when required.
|
|
73
86
|
|
|
74
87
|
## Requirements
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// src/helpers/middleware.ts
|
|
2
|
+
import { NextResponse } from "next/server";
|
|
3
|
+
import { SOLVAPAY_AUTHORIZATION_HEADER, SOLVAPAY_USER_ID_HEADER } from "@solvapay/auth";
|
|
4
|
+
import { createAuth0AuthAdapter } from "@solvapay/auth/auth0";
|
|
5
|
+
function mergeSetCookies(target, source) {
|
|
6
|
+
for (const cookie of source.headers.getSetCookie()) {
|
|
7
|
+
target.headers.append("set-cookie", cookie);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
async function resolveIdentity(adapter, req) {
|
|
11
|
+
if (adapter.getIdentityFromRequest) {
|
|
12
|
+
return adapter.getIdentityFromRequest(req);
|
|
13
|
+
}
|
|
14
|
+
const userId = await adapter.getUserIdFromRequest(req);
|
|
15
|
+
if (!userId) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return { userId };
|
|
19
|
+
}
|
|
20
|
+
function buildForwardResponse(req, userIdHeader, identity) {
|
|
21
|
+
const requestHeaders = new Headers(req.headers);
|
|
22
|
+
requestHeaders.delete(userIdHeader);
|
|
23
|
+
requestHeaders.delete(SOLVAPAY_AUTHORIZATION_HEADER);
|
|
24
|
+
if (identity) {
|
|
25
|
+
requestHeaders.set(userIdHeader, identity.userId);
|
|
26
|
+
if (identity.claimsToken) {
|
|
27
|
+
requestHeaders.set(SOLVAPAY_AUTHORIZATION_HEADER, `Bearer ${identity.claimsToken}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return NextResponse.next({
|
|
31
|
+
request: {
|
|
32
|
+
headers: requestHeaders
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function getPathname(req) {
|
|
37
|
+
if (req.nextUrl) {
|
|
38
|
+
return req.nextUrl.pathname;
|
|
39
|
+
}
|
|
40
|
+
return new URL(req.url).pathname;
|
|
41
|
+
}
|
|
42
|
+
function createAuthMiddleware(options) {
|
|
43
|
+
const {
|
|
44
|
+
adapter,
|
|
45
|
+
publicRoutes = [],
|
|
46
|
+
userIdHeader = SOLVAPAY_USER_ID_HEADER,
|
|
47
|
+
processAllRoutes = false,
|
|
48
|
+
protectedRoutePrefix = "/api"
|
|
49
|
+
} = options;
|
|
50
|
+
return async function middleware(request) {
|
|
51
|
+
const req = request;
|
|
52
|
+
const pathname = getPathname(req);
|
|
53
|
+
if (!processAllRoutes && !pathname.startsWith("/api")) {
|
|
54
|
+
return NextResponse.next();
|
|
55
|
+
}
|
|
56
|
+
const handleResult = adapter.handleRequest ? await adapter.handleRequest(req) : null;
|
|
57
|
+
if (handleResult?.ownsRequest && handleResult.response) {
|
|
58
|
+
return handleResult.response;
|
|
59
|
+
}
|
|
60
|
+
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
61
|
+
const identity = await resolveIdentity(adapter, req);
|
|
62
|
+
const userId = identity?.userId ?? null;
|
|
63
|
+
const isProtectedApiRoute = pathname.startsWith(protectedRoutePrefix) && !isPublicRoute;
|
|
64
|
+
if (isProtectedApiRoute && !userId) {
|
|
65
|
+
const unauthorized = NextResponse.json(
|
|
66
|
+
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
67
|
+
{ status: 401 }
|
|
68
|
+
);
|
|
69
|
+
if (handleResult?.sessionResponse) {
|
|
70
|
+
mergeSetCookies(unauthorized, handleResult.sessionResponse);
|
|
71
|
+
}
|
|
72
|
+
return unauthorized;
|
|
73
|
+
}
|
|
74
|
+
const forward = buildForwardResponse(req, userIdHeader, identity);
|
|
75
|
+
if (handleResult?.sessionResponse) {
|
|
76
|
+
mergeSetCookies(forward, handleResult.sessionResponse);
|
|
77
|
+
}
|
|
78
|
+
return forward;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createAuth0AuthMiddleware(options) {
|
|
82
|
+
const {
|
|
83
|
+
auth0,
|
|
84
|
+
authRoutePrefix,
|
|
85
|
+
publicRoutes = [],
|
|
86
|
+
userIdHeader = SOLVAPAY_USER_ID_HEADER,
|
|
87
|
+
protectedRoutePrefix = "/api"
|
|
88
|
+
} = options;
|
|
89
|
+
return createAuthMiddleware({
|
|
90
|
+
adapter: createAuth0AuthAdapter({ auth0, authRoutePrefix }),
|
|
91
|
+
publicRoutes,
|
|
92
|
+
userIdHeader,
|
|
93
|
+
protectedRoutePrefix,
|
|
94
|
+
processAllRoutes: true
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function createSupabaseAuthMiddleware(options = {}) {
|
|
98
|
+
const { jwtSecret, publicRoutes = [], userIdHeader = SOLVAPAY_USER_ID_HEADER } = options;
|
|
99
|
+
let authAdapter = null;
|
|
100
|
+
let adapterPromise = null;
|
|
101
|
+
const lazyAdapter = {
|
|
102
|
+
async getUserIdFromRequest(req) {
|
|
103
|
+
if (!authAdapter) {
|
|
104
|
+
if (!adapterPromise) {
|
|
105
|
+
adapterPromise = (async () => {
|
|
106
|
+
const secret = jwtSecret || process.env.SUPABASE_JWT_SECRET;
|
|
107
|
+
if (!secret) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
"SUPABASE_JWT_SECRET environment variable is required. Please set it in your .env.local file. Get it from: Supabase Dashboard \u2192 Settings \u2192 API \u2192 JWT Secret"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
const { SupabaseAuthAdapter } = await import("@solvapay/auth/supabase");
|
|
113
|
+
authAdapter = new SupabaseAuthAdapter({ jwtSecret: secret });
|
|
114
|
+
return authAdapter;
|
|
115
|
+
})();
|
|
116
|
+
}
|
|
117
|
+
authAdapter = await adapterPromise;
|
|
118
|
+
}
|
|
119
|
+
return authAdapter.getUserIdFromRequest(req);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
return createAuthMiddleware({
|
|
123
|
+
adapter: lazyAdapter,
|
|
124
|
+
publicRoutes,
|
|
125
|
+
userIdHeader,
|
|
126
|
+
processAllRoutes: false
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
createAuthMiddleware,
|
|
132
|
+
createAuth0AuthMiddleware,
|
|
133
|
+
createSupabaseAuthMiddleware
|
|
134
|
+
};
|
package/dist/index.cjs
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
checkPurchase: () => checkPurchase,
|
|
36
36
|
clearAllPurchaseCache: () => clearAllPurchaseCache,
|
|
37
37
|
clearPurchaseCache: () => clearPurchaseCache,
|
|
38
|
+
createAuth0AuthMiddleware: () => createAuth0AuthMiddleware,
|
|
38
39
|
createAuthMiddleware: () => createAuthMiddleware,
|
|
39
40
|
createCheckoutSession: () => createCheckoutSession,
|
|
40
41
|
createCustomerSession: () => createCustomerSession,
|
|
@@ -353,44 +354,102 @@ async function trackUsage(request, body, options = {}) {
|
|
|
353
354
|
|
|
354
355
|
// src/helpers/middleware.ts
|
|
355
356
|
var import_server17 = require("next/server");
|
|
357
|
+
var import_auth = require("@solvapay/auth");
|
|
358
|
+
var import_auth0 = require("@solvapay/auth/auth0");
|
|
359
|
+
function mergeSetCookies(target, source) {
|
|
360
|
+
for (const cookie of source.headers.getSetCookie()) {
|
|
361
|
+
target.headers.append("set-cookie", cookie);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
async function resolveIdentity(adapter, req) {
|
|
365
|
+
if (adapter.getIdentityFromRequest) {
|
|
366
|
+
return adapter.getIdentityFromRequest(req);
|
|
367
|
+
}
|
|
368
|
+
const userId = await adapter.getUserIdFromRequest(req);
|
|
369
|
+
if (!userId) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
return { userId };
|
|
373
|
+
}
|
|
374
|
+
function buildForwardResponse(req, userIdHeader, identity) {
|
|
375
|
+
const requestHeaders = new Headers(req.headers);
|
|
376
|
+
requestHeaders.delete(userIdHeader);
|
|
377
|
+
requestHeaders.delete(import_auth.SOLVAPAY_AUTHORIZATION_HEADER);
|
|
378
|
+
if (identity) {
|
|
379
|
+
requestHeaders.set(userIdHeader, identity.userId);
|
|
380
|
+
if (identity.claimsToken) {
|
|
381
|
+
requestHeaders.set(import_auth.SOLVAPAY_AUTHORIZATION_HEADER, `Bearer ${identity.claimsToken}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return import_server17.NextResponse.next({
|
|
385
|
+
request: {
|
|
386
|
+
headers: requestHeaders
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function getPathname(req) {
|
|
391
|
+
if (req.nextUrl) {
|
|
392
|
+
return req.nextUrl.pathname;
|
|
393
|
+
}
|
|
394
|
+
return new URL(req.url).pathname;
|
|
395
|
+
}
|
|
356
396
|
function createAuthMiddleware(options) {
|
|
357
|
-
const {
|
|
397
|
+
const {
|
|
398
|
+
adapter,
|
|
399
|
+
publicRoutes = [],
|
|
400
|
+
userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER,
|
|
401
|
+
processAllRoutes = false,
|
|
402
|
+
protectedRoutePrefix = "/api"
|
|
403
|
+
} = options;
|
|
358
404
|
return async function middleware(request) {
|
|
359
405
|
const req = request;
|
|
360
|
-
const
|
|
361
|
-
if (!pathname.startsWith("/api")) {
|
|
406
|
+
const pathname = getPathname(req);
|
|
407
|
+
if (!processAllRoutes && !pathname.startsWith("/api")) {
|
|
362
408
|
return import_server17.NextResponse.next();
|
|
363
409
|
}
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const requestHeaders2 = new Headers(req.headers);
|
|
368
|
-
if (userId) {
|
|
369
|
-
requestHeaders2.set(userIdHeader, userId);
|
|
370
|
-
}
|
|
371
|
-
return import_server17.NextResponse.next({
|
|
372
|
-
request: {
|
|
373
|
-
headers: requestHeaders2
|
|
374
|
-
}
|
|
375
|
-
});
|
|
410
|
+
const handleResult = adapter.handleRequest ? await adapter.handleRequest(req) : null;
|
|
411
|
+
if (handleResult?.ownsRequest && handleResult.response) {
|
|
412
|
+
return handleResult.response;
|
|
376
413
|
}
|
|
377
|
-
|
|
378
|
-
|
|
414
|
+
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
415
|
+
const identity = await resolveIdentity(adapter, req);
|
|
416
|
+
const userId = identity?.userId ?? null;
|
|
417
|
+
const isProtectedApiRoute = pathname.startsWith(protectedRoutePrefix) && !isPublicRoute;
|
|
418
|
+
if (isProtectedApiRoute && !userId) {
|
|
419
|
+
const unauthorized = import_server17.NextResponse.json(
|
|
379
420
|
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
380
421
|
{ status: 401 }
|
|
381
422
|
);
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
requestHeaders.set(userIdHeader, userId);
|
|
385
|
-
return import_server17.NextResponse.next({
|
|
386
|
-
request: {
|
|
387
|
-
headers: requestHeaders
|
|
423
|
+
if (handleResult?.sessionResponse) {
|
|
424
|
+
mergeSetCookies(unauthorized, handleResult.sessionResponse);
|
|
388
425
|
}
|
|
389
|
-
|
|
426
|
+
return unauthorized;
|
|
427
|
+
}
|
|
428
|
+
const forward = buildForwardResponse(req, userIdHeader, identity);
|
|
429
|
+
if (handleResult?.sessionResponse) {
|
|
430
|
+
mergeSetCookies(forward, handleResult.sessionResponse);
|
|
431
|
+
}
|
|
432
|
+
return forward;
|
|
390
433
|
};
|
|
391
434
|
}
|
|
435
|
+
function createAuth0AuthMiddleware(options) {
|
|
436
|
+
const {
|
|
437
|
+
auth0,
|
|
438
|
+
authRoutePrefix,
|
|
439
|
+
publicRoutes = [],
|
|
440
|
+
userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER,
|
|
441
|
+
protectedRoutePrefix = "/api"
|
|
442
|
+
} = options;
|
|
443
|
+
return createAuthMiddleware({
|
|
444
|
+
adapter: (0, import_auth0.createAuth0AuthAdapter)({ auth0, authRoutePrefix }),
|
|
445
|
+
publicRoutes,
|
|
446
|
+
userIdHeader,
|
|
447
|
+
protectedRoutePrefix,
|
|
448
|
+
processAllRoutes: true
|
|
449
|
+
});
|
|
450
|
+
}
|
|
392
451
|
function createSupabaseAuthMiddleware(options = {}) {
|
|
393
|
-
const { jwtSecret, publicRoutes = [], userIdHeader =
|
|
452
|
+
const { jwtSecret, publicRoutes = [], userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER } = options;
|
|
394
453
|
let authAdapter = null;
|
|
395
454
|
let adapterPromise = null;
|
|
396
455
|
const lazyAdapter = {
|
|
@@ -417,7 +476,8 @@ function createSupabaseAuthMiddleware(options = {}) {
|
|
|
417
476
|
return createAuthMiddleware({
|
|
418
477
|
adapter: lazyAdapter,
|
|
419
478
|
publicRoutes,
|
|
420
|
-
userIdHeader
|
|
479
|
+
userIdHeader,
|
|
480
|
+
processAllRoutes: false
|
|
421
481
|
});
|
|
422
482
|
}
|
|
423
483
|
|
|
@@ -460,6 +520,7 @@ async function checkPurchase(request, options = {}) {
|
|
|
460
520
|
checkPurchase,
|
|
461
521
|
clearAllPurchaseCache,
|
|
462
522
|
clearPurchaseCache,
|
|
523
|
+
createAuth0AuthMiddleware,
|
|
463
524
|
createAuthMiddleware,
|
|
464
525
|
createCheckoutSession,
|
|
465
526
|
createCustomerSession,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { AuthenticatedUser, SolvaPay } from '@solvapay/server';
|
|
3
|
-
export { AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.cjs';
|
|
3
|
+
export { Auth0AuthMiddlewareOptions, AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuth0AuthMiddleware, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.cjs';
|
|
4
4
|
import '@solvapay/auth';
|
|
5
|
+
import '@solvapay/auth/auth0';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Purchase Cache Utilities
|
|
@@ -508,6 +509,7 @@ declare function trackUsage(request: globalThis.Request, body: {
|
|
|
508
509
|
productRef?: string;
|
|
509
510
|
description?: string;
|
|
510
511
|
metadata?: Record<string, unknown>;
|
|
512
|
+
idempotencyKey?: string;
|
|
511
513
|
}, options?: {
|
|
512
514
|
solvaPay?: SolvaPay;
|
|
513
515
|
}): Promise<NextResponse>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import { AuthenticatedUser, SolvaPay } from '@solvapay/server';
|
|
3
|
-
export { AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.js';
|
|
3
|
+
export { Auth0AuthMiddlewareOptions, AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuth0AuthMiddleware, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.js';
|
|
4
4
|
import '@solvapay/auth';
|
|
5
|
+
import '@solvapay/auth/auth0';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Purchase Cache Utilities
|
|
@@ -508,6 +509,7 @@ declare function trackUsage(request: globalThis.Request, body: {
|
|
|
508
509
|
productRef?: string;
|
|
509
510
|
description?: string;
|
|
510
511
|
metadata?: Record<string, unknown>;
|
|
512
|
+
idempotencyKey?: string;
|
|
511
513
|
}, options?: {
|
|
512
514
|
solvaPay?: SolvaPay;
|
|
513
515
|
}): Promise<NextResponse>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createAuth0AuthMiddleware,
|
|
2
3
|
createAuthMiddleware,
|
|
3
4
|
createSupabaseAuthMiddleware
|
|
4
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WSXIXEUB.js";
|
|
5
6
|
|
|
6
7
|
// src/index.ts
|
|
7
8
|
import { NextResponse as NextResponse4 } from "next/server";
|
|
@@ -354,6 +355,7 @@ export {
|
|
|
354
355
|
checkPurchase,
|
|
355
356
|
clearAllPurchaseCache,
|
|
356
357
|
clearPurchaseCache,
|
|
358
|
+
createAuth0AuthMiddleware,
|
|
357
359
|
createAuthMiddleware,
|
|
358
360
|
createCheckoutSession,
|
|
359
361
|
createCustomerSession,
|
package/dist/middleware.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/middleware.ts
|
|
31
31
|
var middleware_exports = {};
|
|
32
32
|
__export(middleware_exports, {
|
|
33
|
+
createAuth0AuthMiddleware: () => createAuth0AuthMiddleware,
|
|
33
34
|
createAuthMiddleware: () => createAuthMiddleware,
|
|
34
35
|
createSupabaseAuthMiddleware: () => createSupabaseAuthMiddleware
|
|
35
36
|
});
|
|
@@ -37,44 +38,102 @@ module.exports = __toCommonJS(middleware_exports);
|
|
|
37
38
|
|
|
38
39
|
// src/helpers/middleware.ts
|
|
39
40
|
var import_server = require("next/server");
|
|
41
|
+
var import_auth = require("@solvapay/auth");
|
|
42
|
+
var import_auth0 = require("@solvapay/auth/auth0");
|
|
43
|
+
function mergeSetCookies(target, source) {
|
|
44
|
+
for (const cookie of source.headers.getSetCookie()) {
|
|
45
|
+
target.headers.append("set-cookie", cookie);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function resolveIdentity(adapter, req) {
|
|
49
|
+
if (adapter.getIdentityFromRequest) {
|
|
50
|
+
return adapter.getIdentityFromRequest(req);
|
|
51
|
+
}
|
|
52
|
+
const userId = await adapter.getUserIdFromRequest(req);
|
|
53
|
+
if (!userId) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return { userId };
|
|
57
|
+
}
|
|
58
|
+
function buildForwardResponse(req, userIdHeader, identity) {
|
|
59
|
+
const requestHeaders = new Headers(req.headers);
|
|
60
|
+
requestHeaders.delete(userIdHeader);
|
|
61
|
+
requestHeaders.delete(import_auth.SOLVAPAY_AUTHORIZATION_HEADER);
|
|
62
|
+
if (identity) {
|
|
63
|
+
requestHeaders.set(userIdHeader, identity.userId);
|
|
64
|
+
if (identity.claimsToken) {
|
|
65
|
+
requestHeaders.set(import_auth.SOLVAPAY_AUTHORIZATION_HEADER, `Bearer ${identity.claimsToken}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return import_server.NextResponse.next({
|
|
69
|
+
request: {
|
|
70
|
+
headers: requestHeaders
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function getPathname(req) {
|
|
75
|
+
if (req.nextUrl) {
|
|
76
|
+
return req.nextUrl.pathname;
|
|
77
|
+
}
|
|
78
|
+
return new URL(req.url).pathname;
|
|
79
|
+
}
|
|
40
80
|
function createAuthMiddleware(options) {
|
|
41
|
-
const {
|
|
81
|
+
const {
|
|
82
|
+
adapter,
|
|
83
|
+
publicRoutes = [],
|
|
84
|
+
userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER,
|
|
85
|
+
processAllRoutes = false,
|
|
86
|
+
protectedRoutePrefix = "/api"
|
|
87
|
+
} = options;
|
|
42
88
|
return async function middleware(request) {
|
|
43
89
|
const req = request;
|
|
44
|
-
const
|
|
45
|
-
if (!pathname.startsWith("/api")) {
|
|
90
|
+
const pathname = getPathname(req);
|
|
91
|
+
if (!processAllRoutes && !pathname.startsWith("/api")) {
|
|
46
92
|
return import_server.NextResponse.next();
|
|
47
93
|
}
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const requestHeaders2 = new Headers(req.headers);
|
|
52
|
-
if (userId) {
|
|
53
|
-
requestHeaders2.set(userIdHeader, userId);
|
|
54
|
-
}
|
|
55
|
-
return import_server.NextResponse.next({
|
|
56
|
-
request: {
|
|
57
|
-
headers: requestHeaders2
|
|
58
|
-
}
|
|
59
|
-
});
|
|
94
|
+
const handleResult = adapter.handleRequest ? await adapter.handleRequest(req) : null;
|
|
95
|
+
if (handleResult?.ownsRequest && handleResult.response) {
|
|
96
|
+
return handleResult.response;
|
|
60
97
|
}
|
|
61
|
-
|
|
62
|
-
|
|
98
|
+
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
99
|
+
const identity = await resolveIdentity(adapter, req);
|
|
100
|
+
const userId = identity?.userId ?? null;
|
|
101
|
+
const isProtectedApiRoute = pathname.startsWith(protectedRoutePrefix) && !isPublicRoute;
|
|
102
|
+
if (isProtectedApiRoute && !userId) {
|
|
103
|
+
const unauthorized = import_server.NextResponse.json(
|
|
63
104
|
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
64
105
|
{ status: 401 }
|
|
65
106
|
);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
requestHeaders.set(userIdHeader, userId);
|
|
69
|
-
return import_server.NextResponse.next({
|
|
70
|
-
request: {
|
|
71
|
-
headers: requestHeaders
|
|
107
|
+
if (handleResult?.sessionResponse) {
|
|
108
|
+
mergeSetCookies(unauthorized, handleResult.sessionResponse);
|
|
72
109
|
}
|
|
73
|
-
|
|
110
|
+
return unauthorized;
|
|
111
|
+
}
|
|
112
|
+
const forward = buildForwardResponse(req, userIdHeader, identity);
|
|
113
|
+
if (handleResult?.sessionResponse) {
|
|
114
|
+
mergeSetCookies(forward, handleResult.sessionResponse);
|
|
115
|
+
}
|
|
116
|
+
return forward;
|
|
74
117
|
};
|
|
75
118
|
}
|
|
119
|
+
function createAuth0AuthMiddleware(options) {
|
|
120
|
+
const {
|
|
121
|
+
auth0,
|
|
122
|
+
authRoutePrefix,
|
|
123
|
+
publicRoutes = [],
|
|
124
|
+
userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER,
|
|
125
|
+
protectedRoutePrefix = "/api"
|
|
126
|
+
} = options;
|
|
127
|
+
return createAuthMiddleware({
|
|
128
|
+
adapter: (0, import_auth0.createAuth0AuthAdapter)({ auth0, authRoutePrefix }),
|
|
129
|
+
publicRoutes,
|
|
130
|
+
userIdHeader,
|
|
131
|
+
protectedRoutePrefix,
|
|
132
|
+
processAllRoutes: true
|
|
133
|
+
});
|
|
134
|
+
}
|
|
76
135
|
function createSupabaseAuthMiddleware(options = {}) {
|
|
77
|
-
const { jwtSecret, publicRoutes = [], userIdHeader =
|
|
136
|
+
const { jwtSecret, publicRoutes = [], userIdHeader = import_auth.SOLVAPAY_USER_ID_HEADER } = options;
|
|
78
137
|
let authAdapter = null;
|
|
79
138
|
let adapterPromise = null;
|
|
80
139
|
const lazyAdapter = {
|
|
@@ -101,11 +160,13 @@ function createSupabaseAuthMiddleware(options = {}) {
|
|
|
101
160
|
return createAuthMiddleware({
|
|
102
161
|
adapter: lazyAdapter,
|
|
103
162
|
publicRoutes,
|
|
104
|
-
userIdHeader
|
|
163
|
+
userIdHeader,
|
|
164
|
+
processAllRoutes: false
|
|
105
165
|
});
|
|
106
166
|
}
|
|
107
167
|
// Annotate the CommonJS export names for ESM import in node:
|
|
108
168
|
0 && (module.exports = {
|
|
169
|
+
createAuth0AuthMiddleware,
|
|
109
170
|
createAuthMiddleware,
|
|
110
171
|
createSupabaseAuthMiddleware
|
|
111
172
|
});
|
package/dist/middleware.d.cts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { NextRequest
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
2
|
import { AuthAdapter } from '@solvapay/auth';
|
|
3
|
+
import { Auth0ClientLike } from '@solvapay/auth/auth0';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Next.js Middleware Helpers
|
|
6
7
|
*
|
|
7
8
|
* Helpers for creating authentication middleware in Next.js.
|
|
8
|
-
* Works with any AuthAdapter implementation (Supabase, custom, etc.)
|
|
9
|
+
* Works with any AuthAdapter implementation (Supabase, Auth0, custom, etc.)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -23,156 +24,65 @@ interface AuthMiddlewareOptions {
|
|
|
23
24
|
*/
|
|
24
25
|
publicRoutes?: string[];
|
|
25
26
|
/**
|
|
26
|
-
* Header name to store the user ID (default:
|
|
27
|
+
* Header name to store the user ID (default: `x-user-id`)
|
|
27
28
|
*/
|
|
28
29
|
userIdHeader?: string;
|
|
30
|
+
/**
|
|
31
|
+
* When true, process all matched routes (not only `/api/*`).
|
|
32
|
+
* Use with session-based adapters (Auth0) that refresh cookies on every request.
|
|
33
|
+
* Default: false (legacy Supabase API-only behaviour).
|
|
34
|
+
*/
|
|
35
|
+
processAllRoutes?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* When `processAllRoutes` is true, only enforce 401 on paths starting with this prefix.
|
|
38
|
+
* Default: `/api`
|
|
39
|
+
*/
|
|
40
|
+
protectedRoutePrefix?: string;
|
|
29
41
|
}
|
|
30
42
|
/**
|
|
31
43
|
* Creates a Next.js middleware function for authentication
|
|
32
|
-
*
|
|
33
|
-
* This helper:
|
|
34
|
-
* 1. Uses the provided AuthAdapter to extract userId from requests
|
|
35
|
-
* 2. Handles public vs protected routes
|
|
36
|
-
* 3. Adds userId to request headers for downstream routes
|
|
37
|
-
* 4. Returns appropriate error responses for auth failures
|
|
38
|
-
*
|
|
39
|
-
* @param options - Configuration options
|
|
40
|
-
* @returns Next.js middleware function (can be exported as `middleware` or `proxy`)
|
|
41
|
-
*
|
|
42
|
-
* @example Next.js 15
|
|
43
|
-
* ```typescript
|
|
44
|
-
* // middleware.ts (at project root)
|
|
45
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
46
|
-
* import { SupabaseAuthAdapter } from '@solvapay/auth/supabase';
|
|
47
|
-
*
|
|
48
|
-
* const adapter = new SupabaseAuthAdapter({
|
|
49
|
-
* jwtSecret: process.env.SUPABASE_JWT_SECRET!,
|
|
50
|
-
* });
|
|
51
|
-
*
|
|
52
|
-
* export const middleware = createAuthMiddleware({
|
|
53
|
-
* adapter,
|
|
54
|
-
* publicRoutes: ['/api/list-plans'],
|
|
55
|
-
* });
|
|
56
|
-
*
|
|
57
|
-
* export const config = {
|
|
58
|
-
* matcher: ['/api/:path*'],
|
|
59
|
-
* };
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* @example Next.js 16 with src/ folder
|
|
63
|
-
* ```typescript
|
|
64
|
-
* // src/proxy.ts (in src/ folder, not project root)
|
|
65
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
66
|
-
* import { SupabaseAuthAdapter } from '@solvapay/auth/supabase';
|
|
67
|
-
*
|
|
68
|
-
* const adapter = new SupabaseAuthAdapter({
|
|
69
|
-
* jwtSecret: process.env.SUPABASE_JWT_SECRET!,
|
|
70
|
-
* });
|
|
71
|
-
*
|
|
72
|
-
* // Use 'proxy' export for Next.js 16 (no deprecation warning)
|
|
73
|
-
* export const proxy = createAuthMiddleware({
|
|
74
|
-
* adapter,
|
|
75
|
-
* publicRoutes: ['/api/list-plans'],
|
|
76
|
-
* });
|
|
77
|
-
*
|
|
78
|
-
* export const config = {
|
|
79
|
-
* matcher: ['/api/:path*'],
|
|
80
|
-
* };
|
|
81
|
-
* ```
|
|
82
|
-
*
|
|
83
|
-
* @example Custom adapter
|
|
84
|
-
* ```typescript
|
|
85
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
86
|
-
* import type { AuthAdapter } from '@solvapay/auth';
|
|
87
|
-
*
|
|
88
|
-
* const myAdapter: AuthAdapter = {
|
|
89
|
-
* async getUserIdFromRequest(req) {
|
|
90
|
-
* // Your custom auth logic
|
|
91
|
-
* return userId;
|
|
92
|
-
* },
|
|
93
|
-
* };
|
|
94
|
-
*
|
|
95
|
-
* export const middleware = createAuthMiddleware({
|
|
96
|
-
* adapter: myAdapter,
|
|
97
|
-
* });
|
|
98
|
-
* ```
|
|
99
|
-
*
|
|
100
|
-
* **File Location Notes:**
|
|
101
|
-
* - **Next.js 15**: Place `middleware.ts` at project root
|
|
102
|
-
* - **Next.js 16 without `src/` folder**: Place `middleware.ts` or `proxy.ts` at project root
|
|
103
|
-
* - **Next.js 16 with `src/` folder**: Place `src/proxy.ts` or `src/middleware.ts` (in `src/` folder, not root)
|
|
104
|
-
*
|
|
105
|
-
* **Note:** Next.js 16 renamed "middleware" to "proxy". You can export the return value as either
|
|
106
|
-
* `middleware` or `proxy` - both work, but `proxy` is recommended to avoid deprecation warnings.
|
|
107
44
|
*/
|
|
108
|
-
declare function createAuthMiddleware(options: AuthMiddlewareOptions): (request: NextRequest) => Promise<
|
|
45
|
+
declare function createAuthMiddleware(options: AuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
109
46
|
/**
|
|
110
|
-
* Configuration options for
|
|
47
|
+
* Configuration options for Auth0 authentication middleware
|
|
111
48
|
*/
|
|
112
|
-
interface
|
|
49
|
+
interface Auth0AuthMiddlewareOptions {
|
|
113
50
|
/**
|
|
114
|
-
*
|
|
115
|
-
* If not provided, will use SUPABASE_JWT_SECRET environment variable
|
|
51
|
+
* Auth0 client instance used by the adapter.
|
|
116
52
|
*/
|
|
117
|
-
|
|
53
|
+
auth0: Auth0ClientLike;
|
|
118
54
|
/**
|
|
119
|
-
* Public routes that don't require authentication
|
|
120
|
-
* Routes are matched using pathname.startsWith()
|
|
55
|
+
* Public routes that don't require authentication.
|
|
121
56
|
*/
|
|
122
57
|
publicRoutes?: string[];
|
|
123
58
|
/**
|
|
124
|
-
*
|
|
59
|
+
* Route prefix owned by Auth0 (default: `/auth`).
|
|
125
60
|
*/
|
|
61
|
+
authRoutePrefix?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Header name to store the user ID (default: `x-user-id`)
|
|
64
|
+
*/
|
|
65
|
+
userIdHeader?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Route prefix that enforces 401 when unauthenticated (default: `/api`)
|
|
68
|
+
*/
|
|
69
|
+
protectedRoutePrefix?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates a Next.js middleware function for Auth0 authentication.
|
|
73
|
+
*/
|
|
74
|
+
declare function createAuth0AuthMiddleware(options: Auth0AuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
75
|
+
/**
|
|
76
|
+
* Configuration options for Supabase authentication middleware
|
|
77
|
+
*/
|
|
78
|
+
interface SupabaseAuthMiddlewareOptions {
|
|
79
|
+
jwtSecret?: string;
|
|
80
|
+
publicRoutes?: string[];
|
|
126
81
|
userIdHeader?: string;
|
|
127
82
|
}
|
|
128
83
|
/**
|
|
129
84
|
* Creates a Next.js middleware function for Supabase authentication
|
|
130
|
-
*
|
|
131
|
-
* Convenience function that creates a SupabaseAuthAdapter and wraps it with createAuthMiddleware.
|
|
132
|
-
* Only use this if you're using Supabase - otherwise use createAuthMiddleware with your own adapter.
|
|
133
|
-
*
|
|
134
|
-
* Uses dynamic import to avoid requiring Supabase as a dependency in @solvapay/next.
|
|
135
|
-
*
|
|
136
|
-
* @param options - Configuration options
|
|
137
|
-
* @returns Next.js middleware function (can be exported as `middleware` or `proxy`)
|
|
138
|
-
*
|
|
139
|
-
* @example Next.js 15
|
|
140
|
-
* ```typescript
|
|
141
|
-
* // middleware.ts (at project root)
|
|
142
|
-
* import { createSupabaseAuthMiddleware } from '@solvapay/next';
|
|
143
|
-
*
|
|
144
|
-
* export const middleware = createSupabaseAuthMiddleware({
|
|
145
|
-
* publicRoutes: ['/api/list-plans'],
|
|
146
|
-
* });
|
|
147
|
-
*
|
|
148
|
-
* export const config = {
|
|
149
|
-
* matcher: ['/api/:path*'],
|
|
150
|
-
* };
|
|
151
|
-
* ```
|
|
152
|
-
*
|
|
153
|
-
* @example Next.js 16 with src/ folder
|
|
154
|
-
* ```typescript
|
|
155
|
-
* // src/proxy.ts (in src/ folder, not project root)
|
|
156
|
-
* import { createSupabaseAuthMiddleware } from '@solvapay/next';
|
|
157
|
-
*
|
|
158
|
-
* // Use 'proxy' export for Next.js 16 (no deprecation warning)
|
|
159
|
-
* export const proxy = createSupabaseAuthMiddleware({
|
|
160
|
-
* publicRoutes: ['/api/list-plans'],
|
|
161
|
-
* });
|
|
162
|
-
*
|
|
163
|
-
* export const config = {
|
|
164
|
-
* matcher: ['/api/:path*'],
|
|
165
|
-
* };
|
|
166
|
-
* ```
|
|
167
|
-
*
|
|
168
|
-
* **File Location Notes:**
|
|
169
|
-
* - **Next.js 15**: Place `middleware.ts` at project root
|
|
170
|
-
* - **Next.js 16 without `src/` folder**: Place `middleware.ts` or `proxy.ts` at project root
|
|
171
|
-
* - **Next.js 16 with `src/` folder**: Place `src/proxy.ts` or `src/middleware.ts` (in `src/` folder, not root)
|
|
172
|
-
*
|
|
173
|
-
* **Note:** Next.js 16 renamed "middleware" to "proxy". You can export the return value as either
|
|
174
|
-
* `middleware` or `proxy` - both work, but `proxy` is recommended to avoid deprecation warnings.
|
|
175
85
|
*/
|
|
176
|
-
declare function createSupabaseAuthMiddleware(options?: SupabaseAuthMiddlewareOptions): (request: NextRequest) => Promise<
|
|
86
|
+
declare function createSupabaseAuthMiddleware(options?: SupabaseAuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
177
87
|
|
|
178
|
-
export { type AuthMiddlewareOptions, type SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware };
|
|
88
|
+
export { type Auth0AuthMiddlewareOptions, type AuthMiddlewareOptions, type SupabaseAuthMiddlewareOptions, createAuth0AuthMiddleware, createAuthMiddleware, createSupabaseAuthMiddleware };
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { NextRequest
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
2
|
import { AuthAdapter } from '@solvapay/auth';
|
|
3
|
+
import { Auth0ClientLike } from '@solvapay/auth/auth0';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Next.js Middleware Helpers
|
|
6
7
|
*
|
|
7
8
|
* Helpers for creating authentication middleware in Next.js.
|
|
8
|
-
* Works with any AuthAdapter implementation (Supabase, custom, etc.)
|
|
9
|
+
* Works with any AuthAdapter implementation (Supabase, Auth0, custom, etc.)
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -23,156 +24,65 @@ interface AuthMiddlewareOptions {
|
|
|
23
24
|
*/
|
|
24
25
|
publicRoutes?: string[];
|
|
25
26
|
/**
|
|
26
|
-
* Header name to store the user ID (default:
|
|
27
|
+
* Header name to store the user ID (default: `x-user-id`)
|
|
27
28
|
*/
|
|
28
29
|
userIdHeader?: string;
|
|
30
|
+
/**
|
|
31
|
+
* When true, process all matched routes (not only `/api/*`).
|
|
32
|
+
* Use with session-based adapters (Auth0) that refresh cookies on every request.
|
|
33
|
+
* Default: false (legacy Supabase API-only behaviour).
|
|
34
|
+
*/
|
|
35
|
+
processAllRoutes?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* When `processAllRoutes` is true, only enforce 401 on paths starting with this prefix.
|
|
38
|
+
* Default: `/api`
|
|
39
|
+
*/
|
|
40
|
+
protectedRoutePrefix?: string;
|
|
29
41
|
}
|
|
30
42
|
/**
|
|
31
43
|
* Creates a Next.js middleware function for authentication
|
|
32
|
-
*
|
|
33
|
-
* This helper:
|
|
34
|
-
* 1. Uses the provided AuthAdapter to extract userId from requests
|
|
35
|
-
* 2. Handles public vs protected routes
|
|
36
|
-
* 3. Adds userId to request headers for downstream routes
|
|
37
|
-
* 4. Returns appropriate error responses for auth failures
|
|
38
|
-
*
|
|
39
|
-
* @param options - Configuration options
|
|
40
|
-
* @returns Next.js middleware function (can be exported as `middleware` or `proxy`)
|
|
41
|
-
*
|
|
42
|
-
* @example Next.js 15
|
|
43
|
-
* ```typescript
|
|
44
|
-
* // middleware.ts (at project root)
|
|
45
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
46
|
-
* import { SupabaseAuthAdapter } from '@solvapay/auth/supabase';
|
|
47
|
-
*
|
|
48
|
-
* const adapter = new SupabaseAuthAdapter({
|
|
49
|
-
* jwtSecret: process.env.SUPABASE_JWT_SECRET!,
|
|
50
|
-
* });
|
|
51
|
-
*
|
|
52
|
-
* export const middleware = createAuthMiddleware({
|
|
53
|
-
* adapter,
|
|
54
|
-
* publicRoutes: ['/api/list-plans'],
|
|
55
|
-
* });
|
|
56
|
-
*
|
|
57
|
-
* export const config = {
|
|
58
|
-
* matcher: ['/api/:path*'],
|
|
59
|
-
* };
|
|
60
|
-
* ```
|
|
61
|
-
*
|
|
62
|
-
* @example Next.js 16 with src/ folder
|
|
63
|
-
* ```typescript
|
|
64
|
-
* // src/proxy.ts (in src/ folder, not project root)
|
|
65
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
66
|
-
* import { SupabaseAuthAdapter } from '@solvapay/auth/supabase';
|
|
67
|
-
*
|
|
68
|
-
* const adapter = new SupabaseAuthAdapter({
|
|
69
|
-
* jwtSecret: process.env.SUPABASE_JWT_SECRET!,
|
|
70
|
-
* });
|
|
71
|
-
*
|
|
72
|
-
* // Use 'proxy' export for Next.js 16 (no deprecation warning)
|
|
73
|
-
* export const proxy = createAuthMiddleware({
|
|
74
|
-
* adapter,
|
|
75
|
-
* publicRoutes: ['/api/list-plans'],
|
|
76
|
-
* });
|
|
77
|
-
*
|
|
78
|
-
* export const config = {
|
|
79
|
-
* matcher: ['/api/:path*'],
|
|
80
|
-
* };
|
|
81
|
-
* ```
|
|
82
|
-
*
|
|
83
|
-
* @example Custom adapter
|
|
84
|
-
* ```typescript
|
|
85
|
-
* import { createAuthMiddleware } from '@solvapay/next';
|
|
86
|
-
* import type { AuthAdapter } from '@solvapay/auth';
|
|
87
|
-
*
|
|
88
|
-
* const myAdapter: AuthAdapter = {
|
|
89
|
-
* async getUserIdFromRequest(req) {
|
|
90
|
-
* // Your custom auth logic
|
|
91
|
-
* return userId;
|
|
92
|
-
* },
|
|
93
|
-
* };
|
|
94
|
-
*
|
|
95
|
-
* export const middleware = createAuthMiddleware({
|
|
96
|
-
* adapter: myAdapter,
|
|
97
|
-
* });
|
|
98
|
-
* ```
|
|
99
|
-
*
|
|
100
|
-
* **File Location Notes:**
|
|
101
|
-
* - **Next.js 15**: Place `middleware.ts` at project root
|
|
102
|
-
* - **Next.js 16 without `src/` folder**: Place `middleware.ts` or `proxy.ts` at project root
|
|
103
|
-
* - **Next.js 16 with `src/` folder**: Place `src/proxy.ts` or `src/middleware.ts` (in `src/` folder, not root)
|
|
104
|
-
*
|
|
105
|
-
* **Note:** Next.js 16 renamed "middleware" to "proxy". You can export the return value as either
|
|
106
|
-
* `middleware` or `proxy` - both work, but `proxy` is recommended to avoid deprecation warnings.
|
|
107
44
|
*/
|
|
108
|
-
declare function createAuthMiddleware(options: AuthMiddlewareOptions): (request: NextRequest) => Promise<
|
|
45
|
+
declare function createAuthMiddleware(options: AuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
109
46
|
/**
|
|
110
|
-
* Configuration options for
|
|
47
|
+
* Configuration options for Auth0 authentication middleware
|
|
111
48
|
*/
|
|
112
|
-
interface
|
|
49
|
+
interface Auth0AuthMiddlewareOptions {
|
|
113
50
|
/**
|
|
114
|
-
*
|
|
115
|
-
* If not provided, will use SUPABASE_JWT_SECRET environment variable
|
|
51
|
+
* Auth0 client instance used by the adapter.
|
|
116
52
|
*/
|
|
117
|
-
|
|
53
|
+
auth0: Auth0ClientLike;
|
|
118
54
|
/**
|
|
119
|
-
* Public routes that don't require authentication
|
|
120
|
-
* Routes are matched using pathname.startsWith()
|
|
55
|
+
* Public routes that don't require authentication.
|
|
121
56
|
*/
|
|
122
57
|
publicRoutes?: string[];
|
|
123
58
|
/**
|
|
124
|
-
*
|
|
59
|
+
* Route prefix owned by Auth0 (default: `/auth`).
|
|
125
60
|
*/
|
|
61
|
+
authRoutePrefix?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Header name to store the user ID (default: `x-user-id`)
|
|
64
|
+
*/
|
|
65
|
+
userIdHeader?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Route prefix that enforces 401 when unauthenticated (default: `/api`)
|
|
68
|
+
*/
|
|
69
|
+
protectedRoutePrefix?: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates a Next.js middleware function for Auth0 authentication.
|
|
73
|
+
*/
|
|
74
|
+
declare function createAuth0AuthMiddleware(options: Auth0AuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
75
|
+
/**
|
|
76
|
+
* Configuration options for Supabase authentication middleware
|
|
77
|
+
*/
|
|
78
|
+
interface SupabaseAuthMiddlewareOptions {
|
|
79
|
+
jwtSecret?: string;
|
|
80
|
+
publicRoutes?: string[];
|
|
126
81
|
userIdHeader?: string;
|
|
127
82
|
}
|
|
128
83
|
/**
|
|
129
84
|
* Creates a Next.js middleware function for Supabase authentication
|
|
130
|
-
*
|
|
131
|
-
* Convenience function that creates a SupabaseAuthAdapter and wraps it with createAuthMiddleware.
|
|
132
|
-
* Only use this if you're using Supabase - otherwise use createAuthMiddleware with your own adapter.
|
|
133
|
-
*
|
|
134
|
-
* Uses dynamic import to avoid requiring Supabase as a dependency in @solvapay/next.
|
|
135
|
-
*
|
|
136
|
-
* @param options - Configuration options
|
|
137
|
-
* @returns Next.js middleware function (can be exported as `middleware` or `proxy`)
|
|
138
|
-
*
|
|
139
|
-
* @example Next.js 15
|
|
140
|
-
* ```typescript
|
|
141
|
-
* // middleware.ts (at project root)
|
|
142
|
-
* import { createSupabaseAuthMiddleware } from '@solvapay/next';
|
|
143
|
-
*
|
|
144
|
-
* export const middleware = createSupabaseAuthMiddleware({
|
|
145
|
-
* publicRoutes: ['/api/list-plans'],
|
|
146
|
-
* });
|
|
147
|
-
*
|
|
148
|
-
* export const config = {
|
|
149
|
-
* matcher: ['/api/:path*'],
|
|
150
|
-
* };
|
|
151
|
-
* ```
|
|
152
|
-
*
|
|
153
|
-
* @example Next.js 16 with src/ folder
|
|
154
|
-
* ```typescript
|
|
155
|
-
* // src/proxy.ts (in src/ folder, not project root)
|
|
156
|
-
* import { createSupabaseAuthMiddleware } from '@solvapay/next';
|
|
157
|
-
*
|
|
158
|
-
* // Use 'proxy' export for Next.js 16 (no deprecation warning)
|
|
159
|
-
* export const proxy = createSupabaseAuthMiddleware({
|
|
160
|
-
* publicRoutes: ['/api/list-plans'],
|
|
161
|
-
* });
|
|
162
|
-
*
|
|
163
|
-
* export const config = {
|
|
164
|
-
* matcher: ['/api/:path*'],
|
|
165
|
-
* };
|
|
166
|
-
* ```
|
|
167
|
-
*
|
|
168
|
-
* **File Location Notes:**
|
|
169
|
-
* - **Next.js 15**: Place `middleware.ts` at project root
|
|
170
|
-
* - **Next.js 16 without `src/` folder**: Place `middleware.ts` or `proxy.ts` at project root
|
|
171
|
-
* - **Next.js 16 with `src/` folder**: Place `src/proxy.ts` or `src/middleware.ts` (in `src/` folder, not root)
|
|
172
|
-
*
|
|
173
|
-
* **Note:** Next.js 16 renamed "middleware" to "proxy". You can export the return value as either
|
|
174
|
-
* `middleware` or `proxy` - both work, but `proxy` is recommended to avoid deprecation warnings.
|
|
175
85
|
*/
|
|
176
|
-
declare function createSupabaseAuthMiddleware(options?: SupabaseAuthMiddlewareOptions): (request: NextRequest) => Promise<
|
|
86
|
+
declare function createSupabaseAuthMiddleware(options?: SupabaseAuthMiddlewareOptions): (request: NextRequest) => Promise<Response>;
|
|
177
87
|
|
|
178
|
-
export { type AuthMiddlewareOptions, type SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware };
|
|
88
|
+
export { type Auth0AuthMiddlewareOptions, type AuthMiddlewareOptions, type SupabaseAuthMiddlewareOptions, createAuth0AuthMiddleware, createAuthMiddleware, createSupabaseAuthMiddleware };
|
package/dist/middleware.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solvapay/next",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-preview-e89fa52f99b6d0c7bf9834fcf2d1403141051fa0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
},
|
|
35
35
|
"sideEffects": false,
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@solvapay/auth": "1.0
|
|
37
|
+
"@solvapay/auth": "1.1.0-preview-e89fa52f99b6d0c7bf9834fcf2d1403141051fa0",
|
|
38
38
|
"@solvapay/core": "1.0.9",
|
|
39
|
-
"@solvapay/server": "1.2.
|
|
39
|
+
"@solvapay/server": "1.2.1-preview-e89fa52f99b6d0c7bf9834fcf2d1403141051fa0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"next": ">=13.0.0"
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsup src/index.ts src/middleware.ts --format esm,cjs --dts --tsconfig tsconfig.build.json --external next",
|
|
53
|
-
"test": "vitest run
|
|
53
|
+
"test": "vitest run",
|
|
54
54
|
"test:watch": "vitest",
|
|
55
55
|
"lint": "eslint src",
|
|
56
56
|
"lint:fix": "eslint src --fix"
|
package/dist/chunk-F7TBIH6W.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
// src/helpers/middleware.ts
|
|
2
|
-
import { NextResponse } from "next/server";
|
|
3
|
-
function createAuthMiddleware(options) {
|
|
4
|
-
const { adapter, publicRoutes = [], userIdHeader = "x-user-id" } = options;
|
|
5
|
-
return async function middleware(request) {
|
|
6
|
-
const req = request;
|
|
7
|
-
const { pathname } = req.nextUrl;
|
|
8
|
-
if (!pathname.startsWith("/api")) {
|
|
9
|
-
return NextResponse.next();
|
|
10
|
-
}
|
|
11
|
-
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
12
|
-
const userId = await adapter.getUserIdFromRequest(req);
|
|
13
|
-
if (isPublicRoute) {
|
|
14
|
-
const requestHeaders2 = new Headers(req.headers);
|
|
15
|
-
if (userId) {
|
|
16
|
-
requestHeaders2.set(userIdHeader, userId);
|
|
17
|
-
}
|
|
18
|
-
return NextResponse.next({
|
|
19
|
-
request: {
|
|
20
|
-
headers: requestHeaders2
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
if (!userId) {
|
|
25
|
-
return NextResponse.json(
|
|
26
|
-
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
27
|
-
{ status: 401 }
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
const requestHeaders = new Headers(req.headers);
|
|
31
|
-
requestHeaders.set(userIdHeader, userId);
|
|
32
|
-
return NextResponse.next({
|
|
33
|
-
request: {
|
|
34
|
-
headers: requestHeaders
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function createSupabaseAuthMiddleware(options = {}) {
|
|
40
|
-
const { jwtSecret, publicRoutes = [], userIdHeader = "x-user-id" } = options;
|
|
41
|
-
let authAdapter = null;
|
|
42
|
-
let adapterPromise = null;
|
|
43
|
-
const lazyAdapter = {
|
|
44
|
-
async getUserIdFromRequest(req) {
|
|
45
|
-
if (!authAdapter) {
|
|
46
|
-
if (!adapterPromise) {
|
|
47
|
-
adapterPromise = (async () => {
|
|
48
|
-
const secret = jwtSecret || process.env.SUPABASE_JWT_SECRET;
|
|
49
|
-
if (!secret) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
"SUPABASE_JWT_SECRET environment variable is required. Please set it in your .env.local file. Get it from: Supabase Dashboard \u2192 Settings \u2192 API \u2192 JWT Secret"
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
const { SupabaseAuthAdapter } = await import("@solvapay/auth/supabase");
|
|
55
|
-
authAdapter = new SupabaseAuthAdapter({ jwtSecret: secret });
|
|
56
|
-
return authAdapter;
|
|
57
|
-
})();
|
|
58
|
-
}
|
|
59
|
-
authAdapter = await adapterPromise;
|
|
60
|
-
}
|
|
61
|
-
return authAdapter.getUserIdFromRequest(req);
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
return createAuthMiddleware({
|
|
65
|
-
adapter: lazyAdapter,
|
|
66
|
-
publicRoutes,
|
|
67
|
-
userIdHeader
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export {
|
|
72
|
-
createAuthMiddleware,
|
|
73
|
-
createSupabaseAuthMiddleware
|
|
74
|
-
};
|