@tidecloak/nextjs 0.13.9 → 0.13.13

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.
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTideCloakProxy = createTideCloakProxy;
4
+ const server_1 = require("next/server");
5
+ const verify_1 = require("@tidecloak/verify");
6
+ const routerMatcher_1 = require("./routerMatcher");
7
+ const DEFAULTS = {
8
+ protectedRoutes: {},
9
+ onRequest: undefined,
10
+ onSuccess: undefined,
11
+ };
12
+ /**
13
+ * Returns a Next.js 16+ Proxy function enforcing TideCloak auth.
14
+ *
15
+ * This is the recommended approach for Next.js 16+. The proxy runs on Node.js runtime.
16
+ * For Edge runtime, use `createTideCloakMiddleware` instead (deprecated in Next.js 16).
17
+ *
18
+ * Example usage in your `proxy.ts`:
19
+ *
20
+ * ```ts
21
+ * import tidecloakConfig from './tidecloakAdapter.json'
22
+ * import { createTideCloakProxy } from '@tidecloak/nextjs/server'
23
+ *
24
+ * export const proxy = createTideCloakProxy({
25
+ * config: tidecloakConfig,
26
+ * protectedRoutes: {
27
+ * '/admin/*': ['admin'],
28
+ * '/api/private/*': ['user']
29
+ * },
30
+ * onFailure: ({ token }, req) => NextResponse.redirect(new URL('/login', req.url)),
31
+ * })
32
+ *
33
+ * export const config = {
34
+ * matcher: ['/((?!_next|.*\\..*).*)'],
35
+ * }
36
+ * ```
37
+ */
38
+ function createTideCloakProxy(opts) {
39
+ const settings = { ...DEFAULTS, ...opts };
40
+ // Prepare arrays of test functions for protected routes
41
+ const protectedTests = (0, routerMatcher_1.normalizeProtectedRoutes)(settings.protectedRoutes);
42
+ return async function proxy(req) {
43
+ var _a;
44
+ const path = req.nextUrl.pathname;
45
+ try {
46
+ // Extract the raw JWT from the specified cookie
47
+ const token = ((_a = req.cookies.get("kcToken")) === null || _a === void 0 ? void 0 : _a.value) || null;
48
+ // Allow custom logic before auth checks
49
+ if (settings.onRequest) {
50
+ const result = settings.onRequest({ token }, req);
51
+ if (result)
52
+ return result;
53
+ }
54
+ // Iterate protected routes; the first match enforces a role check
55
+ for (const { test, roles } of protectedTests) {
56
+ if (test(path, req)) {
57
+ // Verify signature, issuer, and presence of at least one allowed role
58
+ const payload = await (0, verify_1.verifyTideCloakToken)(settings.config, token, roles);
59
+ if (!payload) {
60
+ // Custom onFailure hook or default JSON response
61
+ if (settings.onFailure) {
62
+ const result = settings.onFailure({ token }, req);
63
+ if (result)
64
+ return result;
65
+ }
66
+ return server_1.NextResponse.json({ error: '[TideCloak Proxy] Access forbidden: invalid token' }, { status: 403 });
67
+ }
68
+ // Custom onSuccess hook if provided
69
+ if (settings.onSuccess) {
70
+ const result = settings.onSuccess({ payload }, req);
71
+ if (result)
72
+ return result;
73
+ }
74
+ // Token valid and role check passed
75
+ return server_1.NextResponse.next();
76
+ }
77
+ }
78
+ // No protected route matched; continue
79
+ return server_1.NextResponse.next();
80
+ }
81
+ catch (err) {
82
+ // Handle unexpected errors
83
+ if (settings.onError) {
84
+ return settings.onError(err, req);
85
+ }
86
+ console.error("[TideCloak Proxy] ", err);
87
+ throw err;
88
+ }
89
+ };
90
+ }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.exchangeCodeForTokens = exchangeCodeForTokens;
4
+ exports.refreshAccessToken = refreshAccessToken;
5
+ exports.parseAuthCodeData = parseAuthCodeData;
6
+ exports.setSessionCookie = setSessionCookie;
7
+ exports.getSessionFromRequest = getSessionFromRequest;
8
+ exports.clearSessionCookie = clearSessionCookie;
9
+ /**
10
+ * Exchange an authorization code for tokens.
11
+ * Use this in your Next.js API route to complete the hybrid mode flow.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * // app/api/auth/callback/route.ts
16
+ * import { exchangeCodeForTokens } from '@tidecloak/nextjs/server';
17
+ *
18
+ * export async function POST(req: NextRequest) {
19
+ * const body = await req.json();
20
+ * const authData = JSON.parse(body.accessToken);
21
+ *
22
+ * const result = await exchangeCodeForTokens({
23
+ * authServerUrl: process.env.TIDECLOAK_URL!,
24
+ * realm: process.env.TIDECLOAK_REALM!,
25
+ * clientId: process.env.TIDECLOAK_CLIENT_ID!,
26
+ * }, authData);
27
+ *
28
+ * if (!result.success) {
29
+ * return NextResponse.json({ error: result.error }, { status: 401 });
30
+ * }
31
+ *
32
+ * // Store tokens server-side and create session
33
+ * return NextResponse.json({ success: true });
34
+ * }
35
+ * ```
36
+ */
37
+ async function exchangeCodeForTokens(config, authData) {
38
+ const tokenEndpoint = `${config.authServerUrl}/realms/${config.realm}/protocol/openid-connect/token`;
39
+ const params = new URLSearchParams({
40
+ grant_type: 'authorization_code',
41
+ client_id: config.clientId,
42
+ code: authData.code,
43
+ code_verifier: authData.code_verifier,
44
+ redirect_uri: authData.redirect_uri,
45
+ });
46
+ if (config.clientSecret) {
47
+ params.set('client_secret', config.clientSecret);
48
+ }
49
+ try {
50
+ const response = await fetch(tokenEndpoint, {
51
+ method: 'POST',
52
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
53
+ body: params,
54
+ });
55
+ if (!response.ok) {
56
+ const errorText = await response.text();
57
+ return { success: false, error: `Token exchange failed: ${errorText}` };
58
+ }
59
+ const tokens = await response.json();
60
+ return { success: true, tokens };
61
+ }
62
+ catch (err) {
63
+ return { success: false, error: `Token exchange error: ${err.message}` };
64
+ }
65
+ }
66
+ /**
67
+ * Refresh an access token using a refresh token.
68
+ * Use this to get a new access token when the current one expires.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const result = await refreshAccessToken({
73
+ * authServerUrl: process.env.TIDECLOAK_URL!,
74
+ * realm: process.env.TIDECLOAK_REALM!,
75
+ * clientId: process.env.TIDECLOAK_CLIENT_ID!,
76
+ * }, session.tokens.refresh_token);
77
+ *
78
+ * if (result.success) {
79
+ * // Update stored tokens
80
+ * session.tokens = result.tokens;
81
+ * }
82
+ * ```
83
+ */
84
+ async function refreshAccessToken(config, refreshToken) {
85
+ const tokenEndpoint = `${config.authServerUrl}/realms/${config.realm}/protocol/openid-connect/token`;
86
+ const params = new URLSearchParams({
87
+ grant_type: 'refresh_token',
88
+ client_id: config.clientId,
89
+ refresh_token: refreshToken,
90
+ });
91
+ if (config.clientSecret) {
92
+ params.set('client_secret', config.clientSecret);
93
+ }
94
+ try {
95
+ const response = await fetch(tokenEndpoint, {
96
+ method: 'POST',
97
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
98
+ body: params,
99
+ });
100
+ if (!response.ok) {
101
+ const errorText = await response.text();
102
+ return { success: false, error: `Token refresh failed: ${errorText}` };
103
+ }
104
+ const tokens = await response.json();
105
+ return { success: true, tokens };
106
+ }
107
+ catch (err) {
108
+ return { success: false, error: `Token refresh error: ${err.message}` };
109
+ }
110
+ }
111
+ /**
112
+ * Parse the auth data from the client request body.
113
+ * The client sends the authorization code data as a JSON string in accessToken field.
114
+ */
115
+ function parseAuthCodeData(requestBody) {
116
+ if (!requestBody.accessToken)
117
+ return null;
118
+ try {
119
+ const data = JSON.parse(requestBody.accessToken);
120
+ if (!data.code || !data.code_verifier || !data.redirect_uri) {
121
+ return null;
122
+ }
123
+ return {
124
+ code: data.code,
125
+ code_verifier: data.code_verifier,
126
+ redirect_uri: data.redirect_uri,
127
+ };
128
+ }
129
+ catch {
130
+ return null;
131
+ }
132
+ }
133
+ /**
134
+ * Create a session cookie response helper.
135
+ *
136
+ * @example
137
+ * ```ts
138
+ * const response = NextResponse.json({ success: true });
139
+ * setSessionCookie(response, sessionId, { maxAge: 86400 });
140
+ * return response;
141
+ * ```
142
+ */
143
+ function setSessionCookie(response, sessionId, options = {}) {
144
+ const { name = 'session', maxAge = 86400, // 1 day
145
+ path = '/', secure = true, sameSite = 'lax', httpOnly = true, } = options;
146
+ response.cookies.set(name, sessionId, {
147
+ httpOnly,
148
+ secure,
149
+ sameSite,
150
+ path,
151
+ maxAge,
152
+ });
153
+ }
154
+ /**
155
+ * Get session ID from request cookies
156
+ */
157
+ function getSessionFromRequest(req, cookieName = 'session') {
158
+ var _a;
159
+ return ((_a = req.cookies.get(cookieName)) === null || _a === void 0 ? void 0 : _a.value) || null;
160
+ }
161
+ /**
162
+ * Clear session cookie
163
+ */
164
+ function clearSessionCookie(response, cookieName = 'session') {
165
+ response.cookies.delete(cookieName);
166
+ }
package/dist/esm/index.js CHANGED
@@ -1,4 +1,22 @@
1
1
  'use client';
2
- import { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider } from '@tidecloak/react';
2
+ import { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider,
3
+ // Role-based guards
4
+ HasRealmRole, HasClientRole,
5
+ // Status components
6
+ Offline, Online, WasOffline, NeedsReauth, AuthLoading,
7
+ // Hybrid mode utilities
8
+ useAuthCallback, parseCallbackUrl, AuthCallback, SimpleAuthCallback,
9
+ // Re-export RequestEnclave for encryption
10
+ RequestEnclave } from '@tidecloak/react';
11
+ // Core exports
3
12
  export { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider };
13
+ // Role-based guard components
14
+ export { HasRealmRole, HasClientRole };
15
+ // Status components
16
+ export { Offline, Online, WasOffline, NeedsReauth, AuthLoading };
17
+ // Hybrid mode utilities
18
+ export { useAuthCallback, parseCallbackUrl, AuthCallback, SimpleAuthCallback };
19
+ // Encryption utility
20
+ export { RequestEnclave };
21
+ // Next.js specific provider
4
22
  export { TideCloakProvider } from "./contexts/TideCloakProvider";
@@ -1,2 +1,8 @@
1
+ // Middleware (for Edge runtime - deprecated in Next.js 16+, but still supported)
1
2
  export { createTideCloakMiddleware } from './tidecloakMiddleware';
3
+ // Proxy (for Next.js 16+ - Node.js runtime)
4
+ export { createTideCloakProxy } from './tidecloakProxy';
5
+ // Token verification
2
6
  export { verifyTideCloakToken } from '@tidecloak/verify';
7
+ // Hybrid mode token exchange utilities
8
+ export { exchangeCodeForTokens, refreshAccessToken, parseAuthCodeData, setSessionCookie, getSessionFromRequest, clearSessionCookie } from './tokenExchange';
@@ -0,0 +1,87 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { verifyTideCloakToken } from '@tidecloak/verify';
3
+ import { normalizeProtectedRoutes } from './routerMatcher';
4
+ const DEFAULTS = {
5
+ protectedRoutes: {},
6
+ onRequest: undefined,
7
+ onSuccess: undefined,
8
+ };
9
+ /**
10
+ * Returns a Next.js 16+ Proxy function enforcing TideCloak auth.
11
+ *
12
+ * This is the recommended approach for Next.js 16+. The proxy runs on Node.js runtime.
13
+ * For Edge runtime, use `createTideCloakMiddleware` instead (deprecated in Next.js 16).
14
+ *
15
+ * Example usage in your `proxy.ts`:
16
+ *
17
+ * ```ts
18
+ * import tidecloakConfig from './tidecloakAdapter.json'
19
+ * import { createTideCloakProxy } from '@tidecloak/nextjs/server'
20
+ *
21
+ * export const proxy = createTideCloakProxy({
22
+ * config: tidecloakConfig,
23
+ * protectedRoutes: {
24
+ * '/admin/*': ['admin'],
25
+ * '/api/private/*': ['user']
26
+ * },
27
+ * onFailure: ({ token }, req) => NextResponse.redirect(new URL('/login', req.url)),
28
+ * })
29
+ *
30
+ * export const config = {
31
+ * matcher: ['/((?!_next|.*\\..*).*)'],
32
+ * }
33
+ * ```
34
+ */
35
+ export function createTideCloakProxy(opts) {
36
+ const settings = { ...DEFAULTS, ...opts };
37
+ // Prepare arrays of test functions for protected routes
38
+ const protectedTests = normalizeProtectedRoutes(settings.protectedRoutes);
39
+ return async function proxy(req) {
40
+ var _a;
41
+ const path = req.nextUrl.pathname;
42
+ try {
43
+ // Extract the raw JWT from the specified cookie
44
+ const token = ((_a = req.cookies.get("kcToken")) === null || _a === void 0 ? void 0 : _a.value) || null;
45
+ // Allow custom logic before auth checks
46
+ if (settings.onRequest) {
47
+ const result = settings.onRequest({ token }, req);
48
+ if (result)
49
+ return result;
50
+ }
51
+ // Iterate protected routes; the first match enforces a role check
52
+ for (const { test, roles } of protectedTests) {
53
+ if (test(path, req)) {
54
+ // Verify signature, issuer, and presence of at least one allowed role
55
+ const payload = await verifyTideCloakToken(settings.config, token, roles);
56
+ if (!payload) {
57
+ // Custom onFailure hook or default JSON response
58
+ if (settings.onFailure) {
59
+ const result = settings.onFailure({ token }, req);
60
+ if (result)
61
+ return result;
62
+ }
63
+ return NextResponse.json({ error: '[TideCloak Proxy] Access forbidden: invalid token' }, { status: 403 });
64
+ }
65
+ // Custom onSuccess hook if provided
66
+ if (settings.onSuccess) {
67
+ const result = settings.onSuccess({ payload }, req);
68
+ if (result)
69
+ return result;
70
+ }
71
+ // Token valid and role check passed
72
+ return NextResponse.next();
73
+ }
74
+ }
75
+ // No protected route matched; continue
76
+ return NextResponse.next();
77
+ }
78
+ catch (err) {
79
+ // Handle unexpected errors
80
+ if (settings.onError) {
81
+ return settings.onError(err, req);
82
+ }
83
+ console.error("[TideCloak Proxy] ", err);
84
+ throw err;
85
+ }
86
+ };
87
+ }
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Exchange an authorization code for tokens.
3
+ * Use this in your Next.js API route to complete the hybrid mode flow.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * // app/api/auth/callback/route.ts
8
+ * import { exchangeCodeForTokens } from '@tidecloak/nextjs/server';
9
+ *
10
+ * export async function POST(req: NextRequest) {
11
+ * const body = await req.json();
12
+ * const authData = JSON.parse(body.accessToken);
13
+ *
14
+ * const result = await exchangeCodeForTokens({
15
+ * authServerUrl: process.env.TIDECLOAK_URL!,
16
+ * realm: process.env.TIDECLOAK_REALM!,
17
+ * clientId: process.env.TIDECLOAK_CLIENT_ID!,
18
+ * }, authData);
19
+ *
20
+ * if (!result.success) {
21
+ * return NextResponse.json({ error: result.error }, { status: 401 });
22
+ * }
23
+ *
24
+ * // Store tokens server-side and create session
25
+ * return NextResponse.json({ success: true });
26
+ * }
27
+ * ```
28
+ */
29
+ export async function exchangeCodeForTokens(config, authData) {
30
+ const tokenEndpoint = `${config.authServerUrl}/realms/${config.realm}/protocol/openid-connect/token`;
31
+ const params = new URLSearchParams({
32
+ grant_type: 'authorization_code',
33
+ client_id: config.clientId,
34
+ code: authData.code,
35
+ code_verifier: authData.code_verifier,
36
+ redirect_uri: authData.redirect_uri,
37
+ });
38
+ if (config.clientSecret) {
39
+ params.set('client_secret', config.clientSecret);
40
+ }
41
+ try {
42
+ const response = await fetch(tokenEndpoint, {
43
+ method: 'POST',
44
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
45
+ body: params,
46
+ });
47
+ if (!response.ok) {
48
+ const errorText = await response.text();
49
+ return { success: false, error: `Token exchange failed: ${errorText}` };
50
+ }
51
+ const tokens = await response.json();
52
+ return { success: true, tokens };
53
+ }
54
+ catch (err) {
55
+ return { success: false, error: `Token exchange error: ${err.message}` };
56
+ }
57
+ }
58
+ /**
59
+ * Refresh an access token using a refresh token.
60
+ * Use this to get a new access token when the current one expires.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * const result = await refreshAccessToken({
65
+ * authServerUrl: process.env.TIDECLOAK_URL!,
66
+ * realm: process.env.TIDECLOAK_REALM!,
67
+ * clientId: process.env.TIDECLOAK_CLIENT_ID!,
68
+ * }, session.tokens.refresh_token);
69
+ *
70
+ * if (result.success) {
71
+ * // Update stored tokens
72
+ * session.tokens = result.tokens;
73
+ * }
74
+ * ```
75
+ */
76
+ export async function refreshAccessToken(config, refreshToken) {
77
+ const tokenEndpoint = `${config.authServerUrl}/realms/${config.realm}/protocol/openid-connect/token`;
78
+ const params = new URLSearchParams({
79
+ grant_type: 'refresh_token',
80
+ client_id: config.clientId,
81
+ refresh_token: refreshToken,
82
+ });
83
+ if (config.clientSecret) {
84
+ params.set('client_secret', config.clientSecret);
85
+ }
86
+ try {
87
+ const response = await fetch(tokenEndpoint, {
88
+ method: 'POST',
89
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
90
+ body: params,
91
+ });
92
+ if (!response.ok) {
93
+ const errorText = await response.text();
94
+ return { success: false, error: `Token refresh failed: ${errorText}` };
95
+ }
96
+ const tokens = await response.json();
97
+ return { success: true, tokens };
98
+ }
99
+ catch (err) {
100
+ return { success: false, error: `Token refresh error: ${err.message}` };
101
+ }
102
+ }
103
+ /**
104
+ * Parse the auth data from the client request body.
105
+ * The client sends the authorization code data as a JSON string in accessToken field.
106
+ */
107
+ export function parseAuthCodeData(requestBody) {
108
+ if (!requestBody.accessToken)
109
+ return null;
110
+ try {
111
+ const data = JSON.parse(requestBody.accessToken);
112
+ if (!data.code || !data.code_verifier || !data.redirect_uri) {
113
+ return null;
114
+ }
115
+ return {
116
+ code: data.code,
117
+ code_verifier: data.code_verifier,
118
+ redirect_uri: data.redirect_uri,
119
+ };
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * Create a session cookie response helper.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * const response = NextResponse.json({ success: true });
131
+ * setSessionCookie(response, sessionId, { maxAge: 86400 });
132
+ * return response;
133
+ * ```
134
+ */
135
+ export function setSessionCookie(response, sessionId, options = {}) {
136
+ const { name = 'session', maxAge = 86400, // 1 day
137
+ path = '/', secure = true, sameSite = 'lax', httpOnly = true, } = options;
138
+ response.cookies.set(name, sessionId, {
139
+ httpOnly,
140
+ secure,
141
+ sameSite,
142
+ path,
143
+ maxAge,
144
+ });
145
+ }
146
+ /**
147
+ * Get session ID from request cookies
148
+ */
149
+ export function getSessionFromRequest(req, cookieName = 'session') {
150
+ var _a;
151
+ return ((_a = req.cookies.get(cookieName)) === null || _a === void 0 ? void 0 : _a.value) || null;
152
+ }
153
+ /**
154
+ * Clear session cookie
155
+ */
156
+ export function clearSessionCookie(response, cookieName = 'session') {
157
+ response.cookies.delete(cookieName);
158
+ }
@@ -1,4 +1,10 @@
1
- import { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider } from '@tidecloak/react';
1
+ import { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider, HasRealmRole, HasClientRole, Offline, Online, WasOffline, NeedsReauth, AuthLoading, useAuthCallback, parseCallbackUrl, AuthCallback, SimpleAuthCallback, RequestEnclave } from '@tidecloak/react';
2
2
  export { useTideCloak, Authenticated, Unauthenticated, TideCloakContextProvider };
3
+ export { HasRealmRole, HasClientRole };
4
+ export { Offline, Online, WasOffline, NeedsReauth, AuthLoading };
5
+ export { useAuthCallback, parseCallbackUrl, AuthCallback, SimpleAuthCallback };
6
+ export { RequestEnclave };
7
+ export type { TideCloakContextValue, TideCloakContextProviderProps } from '@tidecloak/react';
8
+ export type { AuthCallbackState, UseAuthCallbackOptions, AuthCallbackProps } from '@tidecloak/react';
3
9
  export { TideCloakProvider } from "./contexts/TideCloakProvider";
4
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,wBAAwB,EACzB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,wBAAwB,EACzB,CAAC;AACF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,wBAAwB,EAExB,YAAY,EACZ,aAAa,EAEb,OAAO,EACP,MAAM,EACN,UAAU,EACV,WAAW,EACX,WAAW,EAEX,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAElB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,EACf,wBAAwB,EACzB,CAAC;AAGF,OAAO,EACL,YAAY,EACZ,aAAa,EACd,CAAC;AAGF,OAAO,EACL,OAAO,EACP,MAAM,EACN,UAAU,EACV,WAAW,EACX,WAAW,EACZ,CAAC;AAGF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EACnB,CAAC;AAGF,OAAO,EAAE,cAAc,EAAE,CAAC;AAG1B,YAAY,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAC7F,YAAY,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA"}
@@ -1,3 +1,8 @@
1
1
  export { createTideCloakMiddleware } from './tidecloakMiddleware';
2
+ export type { TideMiddlewareOptions, TidecloakConfig } from './tidecloakMiddleware';
3
+ export { createTideCloakProxy } from './tidecloakProxy';
4
+ export type { TideProxyOptions } from './tidecloakProxy';
2
5
  export { verifyTideCloakToken } from '@tidecloak/verify';
6
+ export { exchangeCodeForTokens, refreshAccessToken, parseAuthCodeData, setSessionCookie, getSessionFromRequest, clearSessionCookie } from './tokenExchange';
7
+ export type { TokenExchangeConfig, TokenResponse, AuthCodeData } from './tokenExchange';
3
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AACjE,YAAY,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAGnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAGxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAGxD,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,iBAAiB,CAAA;AAExB,YAAY,EACV,mBAAmB,EACnB,aAAa,EACb,YAAY,EACb,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import type { TidecloakConfig, TideMiddlewareOptions } from './tidecloakMiddleware';
3
+ export type { TidecloakConfig, TideMiddlewareOptions };
4
+ /**
5
+ * Alias for TideMiddlewareOptions for use with the proxy convention
6
+ */
7
+ export type TideProxyOptions = TideMiddlewareOptions;
8
+ /**
9
+ * Returns a Next.js 16+ Proxy function enforcing TideCloak auth.
10
+ *
11
+ * This is the recommended approach for Next.js 16+. The proxy runs on Node.js runtime.
12
+ * For Edge runtime, use `createTideCloakMiddleware` instead (deprecated in Next.js 16).
13
+ *
14
+ * Example usage in your `proxy.ts`:
15
+ *
16
+ * ```ts
17
+ * import tidecloakConfig from './tidecloakAdapter.json'
18
+ * import { createTideCloakProxy } from '@tidecloak/nextjs/server'
19
+ *
20
+ * export const proxy = createTideCloakProxy({
21
+ * config: tidecloakConfig,
22
+ * protectedRoutes: {
23
+ * '/admin/*': ['admin'],
24
+ * '/api/private/*': ['user']
25
+ * },
26
+ * onFailure: ({ token }, req) => NextResponse.redirect(new URL('/login', req.url)),
27
+ * })
28
+ *
29
+ * export const config = {
30
+ * matcher: ['/((?!_next|.*\\..*).*)'],
31
+ * }
32
+ * ```
33
+ */
34
+ export declare function createTideCloakProxy(opts: TideProxyOptions): (req: NextRequest) => Promise<NextResponse<unknown>>;
35
+ //# sourceMappingURL=tidecloakProxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tidecloakProxy.d.ts","sourceRoot":"","sources":["../../../src/server/tidecloakProxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAMvD,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAGnF,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,CAAA;AAEtD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,CAAA;AAQpD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,IAM7B,KAAK,WAAW,oCAqD7C"}