@artatol-acp/auth-nextjs 0.5.3 → 0.5.4

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.
@@ -1,8 +1,16 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
2
  export type ACPAuthMiddlewareOptions = {
3
+ baseUrl: string;
4
+ apiKey?: string;
3
5
  jwtPublicKey: string;
4
6
  publicPaths?: string[];
5
7
  loginPath?: string;
8
+ cookies?: {
9
+ domain?: string;
10
+ path?: string;
11
+ secure?: boolean;
12
+ sameSite?: 'strict' | 'lax' | 'none';
13
+ };
6
14
  };
7
15
  export declare function createACPAuthMiddleware(options: ACPAuthMiddlewareOptions): (request: NextRequest) => Promise<NextResponse<unknown>>;
8
16
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD,MAAM,MAAM,wBAAwB,GAAG;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,IAO/B,SAAS,WAAW,oCAyD7D"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGxD,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;KACtC,CAAC;CACH,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,IAiB/B,SAAS,WAAW,oCA4F7D"}
@@ -2,56 +2,116 @@ import { NextResponse } from 'next/server';
2
2
  import { jwtVerify, importSPKI } from 'jose';
3
3
  let publicKey = null;
4
4
  export function createACPAuthMiddleware(options) {
5
- const { jwtPublicKey, publicPaths = ['/login', '/register', '/forgot-password', '/reset-password'], loginPath = '/login', } = options;
5
+ const { baseUrl, apiKey, jwtPublicKey, publicPaths = ['/login', '/register', '/forgot-password', '/reset-password', '/verify-email', '/verify-2fa'], loginPath = '/login', cookies: cookieConfig = {}, } = options;
6
+ const { domain: cookieDomain, path: cookiePath = '/', secure = process.env.NODE_ENV === 'production', sameSite = 'lax', } = cookieConfig;
6
7
  return async function acpAuthMiddleware(request) {
7
8
  const { pathname } = request.nextUrl;
8
9
  // Allow public paths
9
10
  if (publicPaths.some((path) => pathname.startsWith(path))) {
10
11
  return NextResponse.next();
11
12
  }
13
+ // Allow API routes (they handle their own auth)
14
+ if (pathname.startsWith('/api/')) {
15
+ return NextResponse.next();
16
+ }
12
17
  // Check for access token
13
18
  const accessToken = request.cookies.get('access_token')?.value;
19
+ const refreshToken = request.cookies.get('refresh_token')?.value;
20
+ // If no access token, try to refresh
14
21
  if (!accessToken) {
15
- // Redirect to login
16
- const url = request.nextUrl.clone();
17
- url.pathname = loginPath;
18
- url.searchParams.set('from', pathname);
19
- return NextResponse.redirect(url);
22
+ if (!refreshToken) {
23
+ // No tokens at all, redirect to login
24
+ const url = request.nextUrl.clone();
25
+ url.pathname = loginPath;
26
+ url.searchParams.set('from', pathname);
27
+ return NextResponse.redirect(url);
28
+ }
29
+ // Try to refresh
30
+ const newAccessToken = await tryRefresh(baseUrl, apiKey, refreshToken);
31
+ if (!newAccessToken) {
32
+ // Refresh failed, redirect to login
33
+ const url = request.nextUrl.clone();
34
+ url.pathname = loginPath;
35
+ url.searchParams.set('from', pathname);
36
+ return NextResponse.redirect(url);
37
+ }
38
+ // Set new access token cookie and continue
39
+ const response = NextResponse.next();
40
+ response.cookies.set('access_token', newAccessToken, {
41
+ httpOnly: true,
42
+ secure,
43
+ sameSite,
44
+ maxAge: 60 * 5, // 5 minutes
45
+ path: cookiePath,
46
+ ...(cookieDomain && { domain: cookieDomain }),
47
+ });
48
+ return response;
20
49
  }
21
50
  // Verify access token
22
51
  try {
23
52
  if (!publicKey) {
24
53
  publicKey = await importSPKI(jwtPublicKey, 'EdDSA');
25
54
  }
26
- const { payload } = await jwtVerify(accessToken, publicKey, {
55
+ await jwtVerify(accessToken, publicKey, {
27
56
  algorithms: ['EdDSA'],
28
57
  });
29
- // Check if token is close to expiration (within 60 seconds)
30
- const exp = payload.exp;
31
- if (exp) {
32
- const timeUntilExpiry = exp * 1000 - Date.now();
33
- const refreshThreshold = 60 * 1000; // 60 seconds
34
- if (timeUntilExpiry < refreshThreshold) {
35
- // Token is close to expiration, trigger refresh by redirecting to a refresh endpoint
36
- // This is a lightweight approach - the refresh will happen server-side
37
- const refreshToken = request.cookies.get('refresh_token')?.value;
38
- if (refreshToken) {
39
- // Note: In middleware, we can't directly make server calls easily
40
- // The best approach is to let the SDK handle this on the client side
41
- // or implement a refresh endpoint that middleware can call
42
- // For now, we'll let it pass and rely on client-side auto-refresh
43
- }
44
- }
45
- }
46
58
  return NextResponse.next();
47
59
  }
48
- catch (error) {
49
- // Token invalid or expired, redirect to login
50
- const url = request.nextUrl.clone();
51
- url.pathname = loginPath;
52
- url.searchParams.set('from', pathname);
53
- return NextResponse.redirect(url);
60
+ catch {
61
+ // Token invalid or expired, try to refresh
62
+ if (!refreshToken) {
63
+ const url = request.nextUrl.clone();
64
+ url.pathname = loginPath;
65
+ url.searchParams.set('from', pathname);
66
+ return NextResponse.redirect(url);
67
+ }
68
+ const newAccessToken = await tryRefresh(baseUrl, apiKey, refreshToken);
69
+ if (!newAccessToken) {
70
+ // Refresh failed, redirect to login
71
+ const url = request.nextUrl.clone();
72
+ url.pathname = loginPath;
73
+ url.searchParams.set('from', pathname);
74
+ return NextResponse.redirect(url);
75
+ }
76
+ // Set new access token cookie and continue
77
+ const response = NextResponse.next();
78
+ response.cookies.set('access_token', newAccessToken, {
79
+ httpOnly: true,
80
+ secure,
81
+ sameSite,
82
+ maxAge: 60 * 5, // 5 minutes
83
+ path: cookiePath,
84
+ ...(cookieDomain && { domain: cookieDomain }),
85
+ });
86
+ return response;
54
87
  }
55
88
  };
56
89
  }
90
+ async function tryRefresh(baseUrl, apiKey, refreshToken) {
91
+ try {
92
+ const response = await fetch(`${baseUrl}/refresh`, {
93
+ method: 'POST',
94
+ headers: {
95
+ 'Content-Type': 'application/json',
96
+ ...(apiKey ? { 'X-API-Key': apiKey } : {}),
97
+ Cookie: `refresh_token=${refreshToken}`,
98
+ },
99
+ });
100
+ if (!response.ok) {
101
+ console.error('[ACP Auth Middleware] Refresh failed:', response.status);
102
+ return null;
103
+ }
104
+ const data = await response.json();
105
+ if (!data.success || !data.data?.accessToken) {
106
+ console.error('[ACP Auth Middleware] Invalid refresh response');
107
+ return null;
108
+ }
109
+ console.log('[ACP Auth Middleware] Token refreshed successfully');
110
+ return data.data.accessToken;
111
+ }
112
+ catch (error) {
113
+ console.error('[ACP Auth Middleware] Refresh error:', error);
114
+ return null;
115
+ }
116
+ }
57
117
  //# sourceMappingURL=middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAgB,MAAM,MAAM,CAAC;AAQ3D,IAAI,SAAS,GAAmB,IAAI,CAAC;AAErC,MAAM,UAAU,uBAAuB,CAAC,OAAiC;IACvE,MAAM,EACJ,YAAY,EACZ,WAAW,GAAG,CAAC,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,EAC5E,SAAS,GAAG,QAAQ,GACrB,GAAG,OAAO,CAAC;IAEZ,OAAO,KAAK,UAAU,iBAAiB,CAAC,OAAoB;QAC1D,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;QAErC,qBAAqB;QACrB,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;QAED,yBAAyB;QACzB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,KAAK,CAAC;QAE/D,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,oBAAoB;YACpB,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC;YACzB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACvC,OAAO,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,GAAG,MAAM,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YACtD,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE;gBAC1D,UAAU,EAAE,CAAC,OAAO,CAAC;aACtB,CAAC,CAAC;YAEH,4DAA4D;YAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YACxB,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChD,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;gBAEjD,IAAI,eAAe,GAAG,gBAAgB,EAAE,CAAC;oBACvC,qFAAqF;oBACrF,uEAAuE;oBACvE,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;oBACjE,IAAI,YAAY,EAAE,CAAC;wBACjB,kEAAkE;wBAClE,qEAAqE;wBACrE,2DAA2D;wBAC3D,kEAAkE;oBACpE,CAAC;gBACH,CAAC;YACH,CAAC;YAED,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,8CAA8C;YAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACpC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC;YACzB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACvC,OAAO,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artatol-acp/auth-nextjs",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Next.js SDK for Artatol Cloud Platform Authentication with support for App Router, Server Actions, and Middleware",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",