@descope/nextjs-sdk 0.9.0 → 0.11.0

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 CHANGED
@@ -1,13 +1,13 @@
1
- # Descope SDK for NextJS
1
+ # Descope SDK for Next.js
2
2
 
3
- The Descope SDK for NextJS provides convenient access to the Descope for an application written on top of NextJS. You can read more on the [Descope Website](https://descope.com).
3
+ The Descope SDK for Next.js provides convenient access to the Descope for an application written on top of Next.js. You can read more on the [Descope Website](https://descope.com).
4
4
 
5
5
  This SDK uses under the hood the Descope React SDK and Descope Node SDK
6
6
  Refer to the [Descope React SDK](https://github.com/descope/descope-js/tree/main/packages/sdks/react-sdk) and [Descope Node SDK](https://github.com/descope/node-sdk) for more details.
7
7
 
8
8
  ## Requirements
9
9
 
10
- - The SDK supports NextJS version 13 and above.
10
+ - The SDK supports Next.js version 13 and above.
11
11
  - A Descope `Project ID` is required for using the SDK. Find it on the [project page in the Descope Console](https://app.descope.com/settings/project).
12
12
 
13
13
  ## Installing the SDK
@@ -47,9 +47,9 @@ export default function RootLayout({
47
47
  }
48
48
  ```
49
49
 
50
- Note: `AuthProvider` uses `sessionTokenViaCookie` by default, in order that the [AuthMiddleware](<#Require-authentication-for-application-(Middleware)>) will work out of the box.
51
- The session token cookie is set to [`SameSite=Strict`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value) by default.
52
- If you need to customize this, you can set `sessionTokenViaCookie={sameSite: 'Lax'}`
50
+ Note: `AuthProvider` uses `sessionTokenViaCookie={true}` by default, in order that the [AuthMiddleware](<#Require-authentication-for-application-(Middleware)>) will work out of the box.
51
+ The session token cookie is set to [`SameSite=Strict; Secure;`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie) by default.
52
+ If you need to customize this, you can set `sessionTokenViaCookie={sameSite: 'Lax', secure: false}` (if you pass only `sameSite`, `secure` will be set to `true` by default).
53
53
 
54
54
  #### Use Descope to render Flow
55
55
 
@@ -131,7 +131,7 @@ const App = () => {
131
131
 
132
132
  ##### Require authentication for application (Middleware)
133
133
 
134
- You can use NextJS Middleware to require authentication for a page/route or a group of pages/routes.
134
+ You can use Next.js Middleware to require authentication for a page/route or a group of pages/routes.
135
135
 
136
136
  Descope SDK provides a middleware function that can be used to require authentication for a page/route or a group of pages/routes.
137
137
 
@@ -154,6 +154,10 @@ export default authMiddleware({
154
154
  publicRoutes?: string[],
155
155
  privateRoutes?: string[]
156
156
  // If you having privateRoutes and publicRoutes defined at the same time, privateRoutes will be ignored.
157
+
158
+ // Optional: log level for the middleware
159
+ // Defaults to 'info'
160
+ // logLevel: 'debug' | 'info' | 'warn' | 'error'
157
161
  })
158
162
 
159
163
  export const config = {
@@ -225,7 +229,7 @@ Route handler:
225
229
  // src/pages/api/routes.ts
226
230
  export async function GET() {
227
231
  const currSession = await session();
228
- if (!currSession.isAuthenticated) {
232
+ if (!currSession) {
229
233
  // ...
230
234
  }
231
235
 
@@ -234,12 +238,29 @@ export async function GET() {
234
238
  }
235
239
  ```
236
240
 
241
+ The `session()` function uses Next.js's `cookies()` and `headers()` functions to retrieve the session token. If you are using Next.js Version 13, you can use the `getSession(req)` instead.
242
+
243
+ ```js
244
+ import { getSession } from '@descope/nextjs-sdk/server';
245
+
246
+ export async function GET(req) {
247
+ const currSession = await getSession(req);
248
+
249
+ // ...
250
+ }
251
+ ```
252
+
237
253
  ##### Optional Parameters
238
254
 
239
255
  If the middleware did not set a session, The `session()` function will attempt to retrieve the session token from cookies and validates it, this requires the project ID to be either set in the environment variables or passed as a parameter to the function.
256
+ You can also pass the log level to the function (defaults to 'info').
240
257
 
241
258
  ```
242
- session({ projectId?: string, baseUrl?: string })
259
+ session({
260
+ projectId?: string;
261
+ baseUrl?: string;
262
+ logLevel?: 'debug' | 'info' | 'warn' | 'error'
263
+ })
243
264
  ```
244
265
 
245
266
  - **projectId:** The Descope Project ID. If not provided, the function will fall back to `DESCOPE_PROJECT_ID` from the environment variables.
@@ -5,8 +5,8 @@ var descopeSdk = require('@descope/node-sdk');
5
5
  var constants = require('./constants.js');
6
6
  var sdk = require('./sdk.js');
7
7
  var utils = require('./utils.js');
8
+ var logger = require('./logger.js');
8
9
 
9
- /* eslint-disable no-console */
10
10
  const getSessionJwt = (req) => {
11
11
  let jwt = req.headers?.get('Authorization')?.split(' ')[1];
12
12
  if (jwt) {
@@ -32,7 +32,7 @@ const isPublicRoute = (req, options) => {
32
32
  const isDefaultPublicRoute = Object.values(constants.DEFAULT_PUBLIC_ROUTES).includes(pathname);
33
33
  if (publicRoutes.length > 0) {
34
34
  if (privateRoutes.length > 0) {
35
- console.warn('Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.');
35
+ logger.logger.warn('Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.');
36
36
  }
37
37
  return (isDefaultPublicRoute ||
38
38
  publicRoutes.some((route) => matchWildcardRoute(route, pathname)));
@@ -56,7 +56,8 @@ const addSessionToHeadersIfExists = (headers, session) => {
56
56
  // if the user is not authenticated, it redirects to the redirectUrl
57
57
  // if the user is authenticated, it adds the session to the headers
58
58
  const createAuthMiddleware = (options = {}) => async (req) => {
59
- console.debug('Auth middleware starts');
59
+ logger.setLogger(options.logLevel);
60
+ logger.logger.debug('Auth middleware starts');
60
61
  const jwt = getSessionJwt(req);
61
62
  // check if the user is authenticated
62
63
  let session;
@@ -67,7 +68,7 @@ const createAuthMiddleware = (options = {}) => async (req) => {
67
68
  }).validateJwt(jwt);
68
69
  }
69
70
  catch (err) {
70
- console.debug('Auth middleware, Failed to validate JWT', err);
71
+ logger.logger.debug('Auth middleware, Failed to validate JWT', err);
71
72
  if (!isPublicRoute(req, options)) {
72
73
  const redirectUrl = options.redirectUrl || constants.DEFAULT_PUBLIC_ROUTES.signIn;
73
74
  const url = req.nextUrl.clone();
@@ -78,11 +79,11 @@ const createAuthMiddleware = (options = {}) => async (req) => {
78
79
  if (searchParams) {
79
80
  url.search = searchParams;
80
81
  }
81
- console.debug(`Auth middleware, Redirecting to ${redirectUrl}`);
82
+ logger.logger.debug(`Auth middleware, Redirecting to ${redirectUrl}`);
82
83
  return server_js.NextResponse.redirect(url);
83
84
  }
84
85
  }
85
- console.debug('Auth middleware finishes');
86
+ logger.logger.debug('Auth middleware finishes');
86
87
  // add the session to the request, if it exists
87
88
  const headers = addSessionToHeadersIfExists(req.headers, session);
88
89
  return server_js.NextResponse.next({
@@ -1 +1 @@
1
- {"version":3,"file":"authMiddleware.js","sources":["../../../src/server/authMiddleware.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { NextRequest, NextResponse } from 'next/server';\nimport descopeSdk from '@descope/node-sdk';\nimport type { AuthenticationInfo } from '@descope/node-sdk';\nimport { DEFAULT_PUBLIC_ROUTES, DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk } from './sdk';\nimport { mergeSearchParams } from './utils';\n\ntype MiddlewareOptions = {\n\t// The Descope project ID to use for authentication\n\t// Defaults to process.env.DESCOPE_PROJECT_ID\n\tprojectId?: string;\n\n\t// The base URL to use for authentication\n\t// Defaults to process.env.DESCOPE_BASE_URL\n\tbaseUrl?: string;\n\n\t// The URL to redirect to if the user is not authenticated\n\t// Defaults to process.env.SIGN_IN_ROUTE or '/sign-in' if not provided\n\t// NOTE: In case it contains query parameters that exist in the original URL, they will override the original query parameters. e.g. if the original URL is /page?param1=1&param2=2 and the redirect URL is /sign-in?param1=3, the final redirect URL will be /sign-in?param1=3&param2=2\n\tredirectUrl?: string;\n\n\t// An array of public routes that do not require authentication\n\t// In addition to the default public routes:\n\t// - process.env.SIGN_IN_ROUTE or /sign-in if not provided\n\t// - process.env.SIGN_UP_ROUTE or /sign-up if not provided\n\tpublicRoutes?: string[];\n\n\t// An array of private routes that require authentication\n\t// If privateRoutes is defined, routes not listed in this array will default to public routes\n\tprivateRoutes?: string[];\n};\n\nconst getSessionJwt = (req: NextRequest): string | undefined => {\n\tlet jwt = req.headers?.get('Authorization')?.split(' ')[1];\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\n\tjwt = req.cookies?.get(descopeSdk.SessionTokenCookieName)?.value;\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\treturn undefined;\n};\n\nconst matchWildcardRoute = (route: string, path: string) => {\n\tlet regexPattern = route.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n\t// Convert wildcard (*) to match path segments only\n\tregexPattern = regexPattern.replace(/\\*/g, '[^/]*');\n\tconst regex = new RegExp(`^${regexPattern}$`);\n\n\treturn regex.test(path);\n};\n\nconst isPublicRoute = (req: NextRequest, options: MiddlewareOptions) => {\n\t// Ensure publicRoutes and privateRoutes are arrays, defaulting to empty arrays if not defined\n\tconst { publicRoutes = [], privateRoutes = [] } = options;\n\tconst { pathname } = req.nextUrl;\n\n\tconst isDefaultPublicRoute = Object.values(DEFAULT_PUBLIC_ROUTES).includes(\n\t\tpathname\n\t);\n\n\tif (publicRoutes.length > 0) {\n\t\tif (privateRoutes.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t'Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.'\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\tpublicRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\tif (privateRoutes.length > 0) {\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\t!privateRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\t// If no routes are provided, all routes are private\n\treturn isDefaultPublicRoute;\n};\n\nconst addSessionToHeadersIfExists = (\n\theaders: Headers,\n\tsession: AuthenticationInfo | undefined\n): Headers => {\n\tif (session) {\n\t\tconst requestHeaders = new Headers(headers);\n\t\trequestHeaders.set(\n\t\t\tDESCOPE_SESSION_HEADER,\n\t\t\tBuffer.from(JSON.stringify(session)).toString('base64')\n\t\t);\n\t\treturn requestHeaders;\n\t}\n\treturn headers;\n};\n\n// returns a Middleware that checks if the user is authenticated\n// if the user is not authenticated, it redirects to the redirectUrl\n// if the user is authenticated, it adds the session to the headers\nconst createAuthMiddleware =\n\t(options: MiddlewareOptions = {}) =>\n\tasync (req: NextRequest) => {\n\t\tconsole.debug('Auth middleware starts');\n\n\t\tconst jwt = getSessionJwt(req);\n\n\t\t// check if the user is authenticated\n\t\tlet session: AuthenticationInfo | undefined;\n\t\ttry {\n\t\t\tsession = await getGlobalSdk({\n\t\t\t\tprojectId: options.projectId,\n\t\t\t\tbaseUrl: options.baseUrl\n\t\t\t}).validateJwt(jwt);\n\t\t} catch (err) {\n\t\t\tconsole.debug('Auth middleware, Failed to validate JWT', err);\n\t\t\tif (!isPublicRoute(req, options)) {\n\t\t\t\tconst redirectUrl = options.redirectUrl || DEFAULT_PUBLIC_ROUTES.signIn;\n\t\t\t\tconst url = req.nextUrl.clone();\n\t\t\t\t// Create a URL object for redirectUrl. 'http://example.com' is just a placeholder.\n\t\t\t\tconst parsedRedirectUrl = new URL(redirectUrl, 'http://example.com');\n\t\t\t\turl.pathname = parsedRedirectUrl.pathname;\n\n\t\t\t\tconst searchParams = mergeSearchParams(\n\t\t\t\t\turl.search,\n\t\t\t\t\tparsedRedirectUrl.search\n\t\t\t\t);\n\t\t\t\tif (searchParams) {\n\t\t\t\t\turl.search = searchParams;\n\t\t\t\t}\n\t\t\t\tconsole.debug(`Auth middleware, Redirecting to ${redirectUrl}`);\n\t\t\t\treturn NextResponse.redirect(url);\n\t\t\t}\n\t\t}\n\n\t\tconsole.debug('Auth middleware finishes');\n\t\t// add the session to the request, if it exists\n\t\tconst headers = addSessionToHeadersIfExists(req.headers, session);\n\t\treturn NextResponse.next({\n\t\t\trequest: {\n\t\t\t\theaders\n\t\t\t}\n\t\t});\n\t};\n\nexport default createAuthMiddleware;\n"],"names":["DEFAULT_PUBLIC_ROUTES","DESCOPE_SESSION_HEADER","getGlobalSdk","mergeSearchParams","NextResponse"],"mappings":"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"}
1
+ {"version":3,"file":"authMiddleware.js","sources":["../../../src/server/authMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport descopeSdk from '@descope/node-sdk';\nimport type { AuthenticationInfo } from '@descope/node-sdk';\nimport { DEFAULT_PUBLIC_ROUTES, DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk } from './sdk';\nimport { mergeSearchParams } from './utils';\nimport { LogLevel } from '../types';\nimport { logger, setLogger } from './logger';\n\ntype MiddlewareOptions = {\n\t// The Descope project ID to use for authentication\n\t// Defaults to process.env.DESCOPE_PROJECT_ID\n\tprojectId?: string;\n\n\t// The base URL to use for authentication\n\t// Defaults to process.env.DESCOPE_BASE_URL\n\tbaseUrl?: string;\n\n\t// The URL to redirect to if the user is not authenticated\n\t// Defaults to process.env.SIGN_IN_ROUTE or '/sign-in' if not provided\n\t// NOTE: In case it contains query parameters that exist in the original URL, they will override the original query parameters. e.g. if the original URL is /page?param1=1&param2=2 and the redirect URL is /sign-in?param1=3, the final redirect URL will be /sign-in?param1=3&param2=2\n\tredirectUrl?: string;\n\n\t// An array of public routes that do not require authentication\n\t// In addition to the default public routes:\n\t// - process.env.SIGN_IN_ROUTE or /sign-in if not provided\n\t// - process.env.SIGN_UP_ROUTE or /sign-up if not provided\n\tpublicRoutes?: string[];\n\n\t// An array of private routes that require authentication\n\t// If privateRoutes is defined, routes not listed in this array will default to public routes\n\tprivateRoutes?: string[];\n\n\t// The log level to use for the middleware\n\t// Defaults to 'info'\n\tlogLevel?: LogLevel;\n};\n\nconst getSessionJwt = (req: NextRequest): string | undefined => {\n\tlet jwt = req.headers?.get('Authorization')?.split(' ')[1];\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\n\tjwt = req.cookies?.get(descopeSdk.SessionTokenCookieName)?.value;\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\treturn undefined;\n};\n\nconst matchWildcardRoute = (route: string, path: string) => {\n\tlet regexPattern = route.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n\t// Convert wildcard (*) to match path segments only\n\tregexPattern = regexPattern.replace(/\\*/g, '[^/]*');\n\tconst regex = new RegExp(`^${regexPattern}$`);\n\n\treturn regex.test(path);\n};\n\nconst isPublicRoute = (req: NextRequest, options: MiddlewareOptions) => {\n\t// Ensure publicRoutes and privateRoutes are arrays, defaulting to empty arrays if not defined\n\tconst { publicRoutes = [], privateRoutes = [] } = options;\n\tconst { pathname } = req.nextUrl;\n\n\tconst isDefaultPublicRoute = Object.values(DEFAULT_PUBLIC_ROUTES).includes(\n\t\tpathname\n\t);\n\n\tif (publicRoutes.length > 0) {\n\t\tif (privateRoutes.length > 0) {\n\t\t\tlogger.warn(\n\t\t\t\t'Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.'\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\tpublicRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\tif (privateRoutes.length > 0) {\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\t!privateRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\t// If no routes are provided, all routes are private\n\treturn isDefaultPublicRoute;\n};\n\nconst addSessionToHeadersIfExists = (\n\theaders: Headers,\n\tsession: AuthenticationInfo | undefined\n): Headers => {\n\tif (session) {\n\t\tconst requestHeaders = new Headers(headers);\n\t\trequestHeaders.set(\n\t\t\tDESCOPE_SESSION_HEADER,\n\t\t\tBuffer.from(JSON.stringify(session)).toString('base64')\n\t\t);\n\t\treturn requestHeaders;\n\t}\n\treturn headers;\n};\n\n// returns a Middleware that checks if the user is authenticated\n// if the user is not authenticated, it redirects to the redirectUrl\n// if the user is authenticated, it adds the session to the headers\nconst createAuthMiddleware =\n\t(options: MiddlewareOptions = {}) =>\n\tasync (req: NextRequest) => {\n\t\tsetLogger(options.logLevel);\n\t\tlogger.debug('Auth middleware starts');\n\n\t\tconst jwt = getSessionJwt(req);\n\n\t\t// check if the user is authenticated\n\t\tlet session: AuthenticationInfo | undefined;\n\t\ttry {\n\t\t\tsession = await getGlobalSdk({\n\t\t\t\tprojectId: options.projectId,\n\t\t\t\tbaseUrl: options.baseUrl\n\t\t\t}).validateJwt(jwt);\n\t\t} catch (err) {\n\t\t\tlogger.debug('Auth middleware, Failed to validate JWT', err);\n\t\t\tif (!isPublicRoute(req, options)) {\n\t\t\t\tconst redirectUrl = options.redirectUrl || DEFAULT_PUBLIC_ROUTES.signIn;\n\t\t\t\tconst url = req.nextUrl.clone();\n\t\t\t\t// Create a URL object for redirectUrl. 'http://example.com' is just a placeholder.\n\t\t\t\tconst parsedRedirectUrl = new URL(redirectUrl, 'http://example.com');\n\t\t\t\turl.pathname = parsedRedirectUrl.pathname;\n\n\t\t\t\tconst searchParams = mergeSearchParams(\n\t\t\t\t\turl.search,\n\t\t\t\t\tparsedRedirectUrl.search\n\t\t\t\t);\n\t\t\t\tif (searchParams) {\n\t\t\t\t\turl.search = searchParams;\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Auth middleware, Redirecting to ${redirectUrl}`);\n\t\t\t\treturn NextResponse.redirect(url);\n\t\t\t}\n\t\t}\n\n\t\tlogger.debug('Auth middleware finishes');\n\t\t// add the session to the request, if it exists\n\t\tconst headers = addSessionToHeadersIfExists(req.headers, session);\n\t\treturn NextResponse.next({\n\t\t\trequest: {\n\t\t\t\theaders\n\t\t\t}\n\t\t});\n\t};\n\nexport default createAuthMiddleware;\n"],"names":["DEFAULT_PUBLIC_ROUTES","logger","DESCOPE_SESSION_HEADER","setLogger","getGlobalSdk","mergeSearchParams","NextResponse"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  const DESCOPE_SESSION_HEADER = 'x-descope-session';
4
4
  const baseHeaders = {
5
5
  'x-descope-sdk-name': 'nextjs',
6
- 'x-descope-sdk-version': "0.9.0"
6
+ 'x-descope-sdk-version': "0.11.0"
7
7
  };
8
8
  const DEFAULT_PUBLIC_ROUTES = {
9
9
  signIn: process.env.SIGN_IN_ROUTE || '/sign-in',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../src/server/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\nexport const DESCOPE_SESSION_HEADER = 'x-descope-session';\n\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n\nexport const DEFAULT_PUBLIC_ROUTES = {\n\tsignIn: process.env.SIGN_IN_ROUTE || '/sign-in',\n\tsignUp: process.env.SIGN_UP_ROUTE || '/sign-up'\n};\n"],"names":[],"mappings":";;AAGO,MAAM,sBAAsB,GAAG,oBAAoB;AAE7C,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,OAAa;EACrC;AAEW,MAAA,qBAAqB,GAAG;AACpC,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;AAC/C,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;;;;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../src/server/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\nexport const DESCOPE_SESSION_HEADER = 'x-descope-session';\n\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n\nexport const DEFAULT_PUBLIC_ROUTES = {\n\tsignIn: process.env.SIGN_IN_ROUTE || '/sign-in',\n\tsignUp: process.env.SIGN_UP_ROUTE || '/sign-up'\n};\n"],"names":[],"mappings":";;AAGO,MAAM,sBAAsB,GAAG,oBAAoB;AAE7C,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,QAAa;EACrC;AAEW,MAAA,qBAAqB,GAAG;AACpC,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;AAC/C,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;;;;;;;"}
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ // order of levels is important
4
+ const levels = ['debug', 'info', 'warn', 'error'];
5
+ const logger = {
6
+ debug: console.debug,
7
+ info: console.info,
8
+ log: console.log,
9
+ warn: console.warn,
10
+ error: console.error
11
+ };
12
+ const noop = () => { };
13
+ // override global logger according to the level
14
+ const setLogger = (level = 'info') => {
15
+ Object.keys(logger).forEach((key) => {
16
+ const keyToCompare = key === 'log' ? 'info' : key; // log is an alias for info
17
+ if (levels.indexOf(keyToCompare) < levels.indexOf(level)) {
18
+ logger[key] = noop;
19
+ }
20
+ else {
21
+ logger[key] = console[key];
22
+ }
23
+ });
24
+ };
25
+
26
+ exports.logger = logger;
27
+ exports.setLogger = setLogger;
28
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sources":["../../../src/server/logger.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { LogLevel } from '../types';\n\n// order of levels is important\nconst levels = ['debug', 'info', 'warn', 'error'];\n\nconst logger = {\n\tdebug: console.debug,\n\tinfo: console.info,\n\tlog: console.log,\n\twarn: console.warn,\n\terror: console.error\n};\n\nconst noop = () => {};\n\n// override global logger according to the level\nexport const setLogger = (level: LogLevel = 'info') => {\n\tObject.keys(logger).forEach((key) => {\n\t\tconst keyToCompare = key === 'log' ? 'info' : key; // log is an alias for info\n\t\tif (levels.indexOf(keyToCompare) < levels.indexOf(level)) {\n\t\t\tlogger[key] = noop;\n\t\t} else {\n\t\t\tlogger[key] = console[key];\n\t\t}\n\t});\n};\n\nexport { logger };\n"],"names":[],"mappings":";;AAGA;AACA,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD,MAAM,MAAM,GAAG;IACd,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,KAAK,EAAE,OAAO,CAAC,KAAK;EACnB;AAEF,MAAM,IAAI,GAAG,MAAK,GAAG,CAAC;AAEtB;MACa,SAAS,GAAG,CAAC,KAAkB,GAAA,MAAM,KAAI;IACrD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AACnC,QAAA,MAAM,YAAY,GAAG,GAAG,KAAK,KAAK,GAAG,MAAM,GAAG,GAAG,CAAC;AAClD,QAAA,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzD,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;SACnB;aAAM;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;SAC3B;AACF,KAAC,CAAC,CAAC;AACJ;;;;;"}
@@ -4,8 +4,8 @@ var descopeSdk = require('@descope/node-sdk');
4
4
  var headers_js = require('next/headers.js');
5
5
  var constants = require('./constants.js');
6
6
  var sdk = require('./sdk.js');
7
+ var logger = require('./logger.js');
7
8
 
8
- /* eslint-disable no-console */
9
9
  const extractSession = (descopeSession) => {
10
10
  if (!descopeSession) {
11
11
  return undefined;
@@ -19,18 +19,18 @@ const extractSession = (descopeSession) => {
19
19
  }
20
20
  };
21
21
  const getSessionFromCookie = async (config) => {
22
- console.debug('attempting to get session from cookie');
22
+ logger.logger.debug('attempting to get session from cookie');
23
23
  try {
24
24
  const sessionCookie = (await headers_js.cookies()).get(descopeSdk.SessionTokenCookieName);
25
25
  if (!sessionCookie?.value) {
26
- console.debug('Session cookie not found');
26
+ logger.logger.debug('Session cookie not found');
27
27
  return undefined;
28
28
  }
29
29
  const sdk$1 = sdk.getGlobalSdk(config);
30
30
  return await sdk$1.validateJwt(sessionCookie.value);
31
31
  }
32
32
  catch (err) {
33
- console.debug('Error getting session from cookie', err);
33
+ logger.logger.debug('Error getting session from cookie', err);
34
34
  return undefined;
35
35
  }
36
36
  };
@@ -45,13 +45,17 @@ const extractOrGetSession = async (sessionHeader, config) => {
45
45
  };
46
46
  // returns the session token if it exists in the headers
47
47
  const session = async (config) => {
48
+ logger.setLogger(config?.logLevel);
48
49
  // first attempt to get the session from the headers
49
50
  const reqHeaders = await headers_js.headers();
50
51
  const sessionHeader = reqHeaders.get(constants.DESCOPE_SESSION_HEADER);
51
52
  return extractOrGetSession(sessionHeader, config);
52
53
  };
53
54
  // returns the session token if it exists in the request headers
54
- const getSession = async (req, config) => extractOrGetSession(req.headers[constants.DESCOPE_SESSION_HEADER.toLowerCase()], config);
55
+ const getSession = async (req, config) => {
56
+ logger.setLogger(config?.logLevel);
57
+ return extractOrGetSession(req.headers[constants.DESCOPE_SESSION_HEADER.toLowerCase()], config);
58
+ };
55
59
 
56
60
  exports.getSession = getSession;
57
61
  exports.session = session;
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sources":["../../../src/server/session.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport descopeSdk, { AuthenticationInfo } from '@descope/node-sdk';\nimport { NextApiRequest } from 'next';\nimport { cookies, headers } from 'next/headers';\nimport { DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk, CreateSdkParams } from './sdk';\n\nconst extractSession = (\n\tdescopeSession?: string\n): AuthenticationInfo | undefined => {\n\tif (!descopeSession) {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\tconst authInfo = JSON.parse(\n\t\t\tBuffer.from(descopeSession, 'base64').toString()\n\t\t) as AuthenticationInfo;\n\t\treturn authInfo;\n\t} catch (err) {\n\t\treturn undefined;\n\t}\n};\n\nconst getSessionFromCookie = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n console.debug('attempting to get session from cookie');\n\ttry {\n\t\tconst sessionCookie = (await cookies()).get(\n\t\t\tdescopeSdk.SessionTokenCookieName\n\t\t);\n\t\tif (!sessionCookie?.value) {\n\t\t\tconsole.debug('Session cookie not found');\n\t\t\treturn undefined;\n\t\t}\n\t\tconst sdk = getGlobalSdk(config);\n\t\treturn await sdk.validateJwt(sessionCookie.value);\n\t} catch (err) {\n\t\tconsole.debug('Error getting session from cookie', err);\n\t\treturn undefined;\n\t}\n};\n\n// tries to extract the session header,\n// if it doesn't exist, it will attempt to get the session from the cookie\nconst extractOrGetSession = async (\n\tsessionHeader?: string,\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\tconst session = extractSession(sessionHeader);\n\tif (session) {\n\t\treturn session;\n\t}\n\n\treturn getSessionFromCookie(config);\n};\n\n// returns the session token if it exists in the headers\nexport const session = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\t// first attempt to get the session from the headers\n\tconst reqHeaders = await headers();\n\tconst sessionHeader = reqHeaders.get(DESCOPE_SESSION_HEADER);\n\treturn extractOrGetSession(sessionHeader, config);\n};\n\n// returns the session token if it exists in the request headers\nexport const getSession = async (\n\treq: NextApiRequest,\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> =>\n\textractOrGetSession(\n\t\treq.headers[DESCOPE_SESSION_HEADER.toLowerCase()] as string,\n\t\tconfig\n\t);\n"],"names":["cookies","sdk","getGlobalSdk","headers","DESCOPE_SESSION_HEADER"],"mappings":";;;;;;;AAAA;AAOA,MAAM,cAAc,GAAG,CACtB,cAAuB,KACY;IACnC,IAAI,CAAC,cAAc,EAAE;AACpB,QAAA,OAAO,SAAS,CAAC;KACjB;AACD,IAAA,IAAI;AACH,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAC1B,CAAC;AACxB,QAAA,OAAO,QAAQ,CAAC;KAChB;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,OAC5B,MAAwB,KACoB;AAC3C,IAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACxD,IAAA,IAAI;AACH,QAAA,MAAM,aAAa,GAAG,CAAC,MAAMA,kBAAO,EAAE,EAAE,GAAG,CAC1C,UAAU,CAAC,sBAAsB,CACjC,CAAC;AACF,QAAA,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE;AAC1B,YAAA,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC1C,YAAA,OAAO,SAAS,CAAC;SACjB;AACD,QAAA,MAAMC,KAAG,GAAGC,gBAAY,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,MAAMD,KAAG,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;KAClD;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;AACxD,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF;AACA;AACA,MAAM,mBAAmB,GAAG,OAC3B,aAAsB,EACtB,MAAwB,KACoB;AAC5C,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE;AACZ,QAAA,OAAO,OAAO,CAAC;KACf;AAED,IAAA,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF;MACa,OAAO,GAAG,OACtB,MAAwB,KACoB;;AAE5C,IAAA,MAAM,UAAU,GAAG,MAAME,kBAAO,EAAE,CAAC;IACnC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAACC,gCAAsB,CAAC,CAAC;AAC7D,IAAA,OAAO,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACnD,EAAE;AAEF;AACa,MAAA,UAAU,GAAG,OACzB,GAAmB,EACnB,MAAwB,KAExB,mBAAmB,CAClB,GAAG,CAAC,OAAO,CAACA,gCAAsB,CAAC,WAAW,EAAE,CAAW,EAC3D,MAAM;;;;;"}
1
+ {"version":3,"file":"session.js","sources":["../../../src/server/session.ts"],"sourcesContent":["import descopeSdk, { AuthenticationInfo } from '@descope/node-sdk';\nimport { NextApiRequest } from 'next';\nimport { cookies, headers } from 'next/headers';\nimport { DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk, CreateSdkParams } from './sdk';\nimport { LogLevel } from '../types';\nimport { logger, setLogger } from './logger';\n\ntype SessionConfig = CreateSdkParams & {\n\t// The log level to use for the middleware\n\t// Defaults to 'info'\n\tlogLevel?: LogLevel;\n};\n\nconst extractSession = (\n\tdescopeSession?: string\n): AuthenticationInfo | undefined => {\n\tif (!descopeSession) {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\tconst authInfo = JSON.parse(\n\t\t\tBuffer.from(descopeSession, 'base64').toString()\n\t\t) as AuthenticationInfo;\n\t\treturn authInfo;\n\t} catch (err) {\n\t\treturn undefined;\n\t}\n};\n\nconst getSessionFromCookie = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\tlogger.debug('attempting to get session from cookie');\n\ttry {\n\t\tconst sessionCookie = (await cookies()).get(\n\t\t\tdescopeSdk.SessionTokenCookieName\n\t\t);\n\t\tif (!sessionCookie?.value) {\n\t\t\tlogger.debug('Session cookie not found');\n\t\t\treturn undefined;\n\t\t}\n\t\tconst sdk = getGlobalSdk(config);\n\t\treturn await sdk.validateJwt(sessionCookie.value);\n\t} catch (err) {\n\t\tlogger.debug('Error getting session from cookie', err);\n\t\treturn undefined;\n\t}\n};\n\n// tries to extract the session header,\n// if it doesn't exist, it will attempt to get the session from the cookie\nconst extractOrGetSession = async (\n\tsessionHeader?: string,\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tconst session = extractSession(sessionHeader);\n\tif (session) {\n\t\treturn session;\n\t}\n\n\treturn getSessionFromCookie(config);\n};\n\n// returns the session token if it exists in the headers\nexport const session = async (\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tsetLogger(config?.logLevel);\n\t// first attempt to get the session from the headers\n\tconst reqHeaders = await headers();\n\tconst sessionHeader = reqHeaders.get(DESCOPE_SESSION_HEADER);\n\treturn extractOrGetSession(sessionHeader, config);\n};\n\n// returns the session token if it exists in the request headers\nexport const getSession = async (\n\treq: NextApiRequest,\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tsetLogger(config?.logLevel);\n\treturn extractOrGetSession(\n\t\treq.headers[DESCOPE_SESSION_HEADER.toLowerCase()] as string,\n\t\tconfig\n\t);\n};\n"],"names":["logger","cookies","sdk","getGlobalSdk","setLogger","headers","DESCOPE_SESSION_HEADER"],"mappings":";;;;;;;;AAcA,MAAM,cAAc,GAAG,CACtB,cAAuB,KACY;IACnC,IAAI,CAAC,cAAc,EAAE;AACpB,QAAA,OAAO,SAAS,CAAC;KACjB;AACD,IAAA,IAAI;AACH,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAC1B,CAAC;AACxB,QAAA,OAAO,QAAQ,CAAC;KAChB;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,OAC5B,MAAwB,KACoB;AAC5C,IAAAA,aAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACtD,IAAA,IAAI;AACH,QAAA,MAAM,aAAa,GAAG,CAAC,MAAMC,kBAAO,EAAE,EAAE,GAAG,CAC1C,UAAU,CAAC,sBAAsB,CACjC,CAAC;AACF,QAAA,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE;AAC1B,YAAAD,aAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;AACzC,YAAA,OAAO,SAAS,CAAC;SACjB;AACD,QAAA,MAAME,KAAG,GAAGC,gBAAY,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,MAAMD,KAAG,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;KAClD;IAAC,OAAO,GAAG,EAAE;AACb,QAAAF,aAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;AACvD,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF;AACA;AACA,MAAM,mBAAmB,GAAG,OAC3B,aAAsB,EACtB,MAAsB,KACsB;AAC5C,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE;AACZ,QAAA,OAAO,OAAO,CAAC;KACf;AAED,IAAA,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF;MACa,OAAO,GAAG,OACtB,MAAsB,KACsB;AAC5C,IAAAI,gBAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;;AAE5B,IAAA,MAAM,UAAU,GAAG,MAAMC,kBAAO,EAAE,CAAC;IACnC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAACC,gCAAsB,CAAC,CAAC;AAC7D,IAAA,OAAO,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACnD,EAAE;AAEF;AACa,MAAA,UAAU,GAAG,OACzB,GAAmB,EACnB,MAAsB,KACsB;AAC5C,IAAAF,gBAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC5B,IAAA,OAAO,mBAAmB,CACzB,GAAG,CAAC,OAAO,CAACE,gCAAsB,CAAC,WAAW,EAAE,CAAW,EAC3D,MAAM,CACN,CAAC;AACH;;;;;"}
@@ -3,7 +3,7 @@
3
3
  // eslint-disable-next-line import/prefer-default-export
4
4
  const baseHeaders = {
5
5
  'x-descope-sdk-name': 'nextjs',
6
- 'x-descope-sdk-version': "0.9.0"
6
+ 'x-descope-sdk-version': "0.11.0"
7
7
  };
8
8
 
9
9
  exports.baseHeaders = baseHeaders;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../src/shared/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\n// eslint-disable-next-line import/prefer-default-export\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n"],"names":[],"mappings":";;AAGA;AACa,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,OAAa;;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../src/shared/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\n// eslint-disable-next-line import/prefer-default-export\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n"],"names":[],"mappings":";;AAGA;AACa,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,QAAa;;;;;"}
@@ -3,8 +3,8 @@ import descopeSdk from '@descope/node-sdk';
3
3
  import { DEFAULT_PUBLIC_ROUTES, DESCOPE_SESSION_HEADER } from './constants.js';
4
4
  import { getGlobalSdk } from './sdk.js';
5
5
  import { mergeSearchParams } from './utils.js';
6
+ import { setLogger, logger } from './logger.js';
6
7
 
7
- /* eslint-disable no-console */
8
8
  const getSessionJwt = (req) => {
9
9
  let jwt = req.headers?.get('Authorization')?.split(' ')[1];
10
10
  if (jwt) {
@@ -30,7 +30,7 @@ const isPublicRoute = (req, options) => {
30
30
  const isDefaultPublicRoute = Object.values(DEFAULT_PUBLIC_ROUTES).includes(pathname);
31
31
  if (publicRoutes.length > 0) {
32
32
  if (privateRoutes.length > 0) {
33
- console.warn('Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.');
33
+ logger.warn('Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.');
34
34
  }
35
35
  return (isDefaultPublicRoute ||
36
36
  publicRoutes.some((route) => matchWildcardRoute(route, pathname)));
@@ -54,7 +54,8 @@ const addSessionToHeadersIfExists = (headers, session) => {
54
54
  // if the user is not authenticated, it redirects to the redirectUrl
55
55
  // if the user is authenticated, it adds the session to the headers
56
56
  const createAuthMiddleware = (options = {}) => async (req) => {
57
- console.debug('Auth middleware starts');
57
+ setLogger(options.logLevel);
58
+ logger.debug('Auth middleware starts');
58
59
  const jwt = getSessionJwt(req);
59
60
  // check if the user is authenticated
60
61
  let session;
@@ -65,7 +66,7 @@ const createAuthMiddleware = (options = {}) => async (req) => {
65
66
  }).validateJwt(jwt);
66
67
  }
67
68
  catch (err) {
68
- console.debug('Auth middleware, Failed to validate JWT', err);
69
+ logger.debug('Auth middleware, Failed to validate JWT', err);
69
70
  if (!isPublicRoute(req, options)) {
70
71
  const redirectUrl = options.redirectUrl || DEFAULT_PUBLIC_ROUTES.signIn;
71
72
  const url = req.nextUrl.clone();
@@ -76,11 +77,11 @@ const createAuthMiddleware = (options = {}) => async (req) => {
76
77
  if (searchParams) {
77
78
  url.search = searchParams;
78
79
  }
79
- console.debug(`Auth middleware, Redirecting to ${redirectUrl}`);
80
+ logger.debug(`Auth middleware, Redirecting to ${redirectUrl}`);
80
81
  return NextResponse.redirect(url);
81
82
  }
82
83
  }
83
- console.debug('Auth middleware finishes');
84
+ logger.debug('Auth middleware finishes');
84
85
  // add the session to the request, if it exists
85
86
  const headers = addSessionToHeadersIfExists(req.headers, session);
86
87
  return NextResponse.next({
@@ -1 +1 @@
1
- {"version":3,"file":"authMiddleware.js","sources":["../../../src/server/authMiddleware.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { NextRequest, NextResponse } from 'next/server';\nimport descopeSdk from '@descope/node-sdk';\nimport type { AuthenticationInfo } from '@descope/node-sdk';\nimport { DEFAULT_PUBLIC_ROUTES, DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk } from './sdk';\nimport { mergeSearchParams } from './utils';\n\ntype MiddlewareOptions = {\n\t// The Descope project ID to use for authentication\n\t// Defaults to process.env.DESCOPE_PROJECT_ID\n\tprojectId?: string;\n\n\t// The base URL to use for authentication\n\t// Defaults to process.env.DESCOPE_BASE_URL\n\tbaseUrl?: string;\n\n\t// The URL to redirect to if the user is not authenticated\n\t// Defaults to process.env.SIGN_IN_ROUTE or '/sign-in' if not provided\n\t// NOTE: In case it contains query parameters that exist in the original URL, they will override the original query parameters. e.g. if the original URL is /page?param1=1&param2=2 and the redirect URL is /sign-in?param1=3, the final redirect URL will be /sign-in?param1=3&param2=2\n\tredirectUrl?: string;\n\n\t// An array of public routes that do not require authentication\n\t// In addition to the default public routes:\n\t// - process.env.SIGN_IN_ROUTE or /sign-in if not provided\n\t// - process.env.SIGN_UP_ROUTE or /sign-up if not provided\n\tpublicRoutes?: string[];\n\n\t// An array of private routes that require authentication\n\t// If privateRoutes is defined, routes not listed in this array will default to public routes\n\tprivateRoutes?: string[];\n};\n\nconst getSessionJwt = (req: NextRequest): string | undefined => {\n\tlet jwt = req.headers?.get('Authorization')?.split(' ')[1];\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\n\tjwt = req.cookies?.get(descopeSdk.SessionTokenCookieName)?.value;\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\treturn undefined;\n};\n\nconst matchWildcardRoute = (route: string, path: string) => {\n\tlet regexPattern = route.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n\t// Convert wildcard (*) to match path segments only\n\tregexPattern = regexPattern.replace(/\\*/g, '[^/]*');\n\tconst regex = new RegExp(`^${regexPattern}$`);\n\n\treturn regex.test(path);\n};\n\nconst isPublicRoute = (req: NextRequest, options: MiddlewareOptions) => {\n\t// Ensure publicRoutes and privateRoutes are arrays, defaulting to empty arrays if not defined\n\tconst { publicRoutes = [], privateRoutes = [] } = options;\n\tconst { pathname } = req.nextUrl;\n\n\tconst isDefaultPublicRoute = Object.values(DEFAULT_PUBLIC_ROUTES).includes(\n\t\tpathname\n\t);\n\n\tif (publicRoutes.length > 0) {\n\t\tif (privateRoutes.length > 0) {\n\t\t\tconsole.warn(\n\t\t\t\t'Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.'\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\tpublicRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\tif (privateRoutes.length > 0) {\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\t!privateRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\t// If no routes are provided, all routes are private\n\treturn isDefaultPublicRoute;\n};\n\nconst addSessionToHeadersIfExists = (\n\theaders: Headers,\n\tsession: AuthenticationInfo | undefined\n): Headers => {\n\tif (session) {\n\t\tconst requestHeaders = new Headers(headers);\n\t\trequestHeaders.set(\n\t\t\tDESCOPE_SESSION_HEADER,\n\t\t\tBuffer.from(JSON.stringify(session)).toString('base64')\n\t\t);\n\t\treturn requestHeaders;\n\t}\n\treturn headers;\n};\n\n// returns a Middleware that checks if the user is authenticated\n// if the user is not authenticated, it redirects to the redirectUrl\n// if the user is authenticated, it adds the session to the headers\nconst createAuthMiddleware =\n\t(options: MiddlewareOptions = {}) =>\n\tasync (req: NextRequest) => {\n\t\tconsole.debug('Auth middleware starts');\n\n\t\tconst jwt = getSessionJwt(req);\n\n\t\t// check if the user is authenticated\n\t\tlet session: AuthenticationInfo | undefined;\n\t\ttry {\n\t\t\tsession = await getGlobalSdk({\n\t\t\t\tprojectId: options.projectId,\n\t\t\t\tbaseUrl: options.baseUrl\n\t\t\t}).validateJwt(jwt);\n\t\t} catch (err) {\n\t\t\tconsole.debug('Auth middleware, Failed to validate JWT', err);\n\t\t\tif (!isPublicRoute(req, options)) {\n\t\t\t\tconst redirectUrl = options.redirectUrl || DEFAULT_PUBLIC_ROUTES.signIn;\n\t\t\t\tconst url = req.nextUrl.clone();\n\t\t\t\t// Create a URL object for redirectUrl. 'http://example.com' is just a placeholder.\n\t\t\t\tconst parsedRedirectUrl = new URL(redirectUrl, 'http://example.com');\n\t\t\t\turl.pathname = parsedRedirectUrl.pathname;\n\n\t\t\t\tconst searchParams = mergeSearchParams(\n\t\t\t\t\turl.search,\n\t\t\t\t\tparsedRedirectUrl.search\n\t\t\t\t);\n\t\t\t\tif (searchParams) {\n\t\t\t\t\turl.search = searchParams;\n\t\t\t\t}\n\t\t\t\tconsole.debug(`Auth middleware, Redirecting to ${redirectUrl}`);\n\t\t\t\treturn NextResponse.redirect(url);\n\t\t\t}\n\t\t}\n\n\t\tconsole.debug('Auth middleware finishes');\n\t\t// add the session to the request, if it exists\n\t\tconst headers = addSessionToHeadersIfExists(req.headers, session);\n\t\treturn NextResponse.next({\n\t\t\trequest: {\n\t\t\t\theaders\n\t\t\t}\n\t\t});\n\t};\n\nexport default createAuthMiddleware;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authMiddleware.js","sources":["../../../src/server/authMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport descopeSdk from '@descope/node-sdk';\nimport type { AuthenticationInfo } from '@descope/node-sdk';\nimport { DEFAULT_PUBLIC_ROUTES, DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk } from './sdk';\nimport { mergeSearchParams } from './utils';\nimport { LogLevel } from '../types';\nimport { logger, setLogger } from './logger';\n\ntype MiddlewareOptions = {\n\t// The Descope project ID to use for authentication\n\t// Defaults to process.env.DESCOPE_PROJECT_ID\n\tprojectId?: string;\n\n\t// The base URL to use for authentication\n\t// Defaults to process.env.DESCOPE_BASE_URL\n\tbaseUrl?: string;\n\n\t// The URL to redirect to if the user is not authenticated\n\t// Defaults to process.env.SIGN_IN_ROUTE or '/sign-in' if not provided\n\t// NOTE: In case it contains query parameters that exist in the original URL, they will override the original query parameters. e.g. if the original URL is /page?param1=1&param2=2 and the redirect URL is /sign-in?param1=3, the final redirect URL will be /sign-in?param1=3&param2=2\n\tredirectUrl?: string;\n\n\t// An array of public routes that do not require authentication\n\t// In addition to the default public routes:\n\t// - process.env.SIGN_IN_ROUTE or /sign-in if not provided\n\t// - process.env.SIGN_UP_ROUTE or /sign-up if not provided\n\tpublicRoutes?: string[];\n\n\t// An array of private routes that require authentication\n\t// If privateRoutes is defined, routes not listed in this array will default to public routes\n\tprivateRoutes?: string[];\n\n\t// The log level to use for the middleware\n\t// Defaults to 'info'\n\tlogLevel?: LogLevel;\n};\n\nconst getSessionJwt = (req: NextRequest): string | undefined => {\n\tlet jwt = req.headers?.get('Authorization')?.split(' ')[1];\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\n\tjwt = req.cookies?.get(descopeSdk.SessionTokenCookieName)?.value;\n\tif (jwt) {\n\t\treturn jwt;\n\t}\n\treturn undefined;\n};\n\nconst matchWildcardRoute = (route: string, path: string) => {\n\tlet regexPattern = route.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n\t// Convert wildcard (*) to match path segments only\n\tregexPattern = regexPattern.replace(/\\*/g, '[^/]*');\n\tconst regex = new RegExp(`^${regexPattern}$`);\n\n\treturn regex.test(path);\n};\n\nconst isPublicRoute = (req: NextRequest, options: MiddlewareOptions) => {\n\t// Ensure publicRoutes and privateRoutes are arrays, defaulting to empty arrays if not defined\n\tconst { publicRoutes = [], privateRoutes = [] } = options;\n\tconst { pathname } = req.nextUrl;\n\n\tconst isDefaultPublicRoute = Object.values(DEFAULT_PUBLIC_ROUTES).includes(\n\t\tpathname\n\t);\n\n\tif (publicRoutes.length > 0) {\n\t\tif (privateRoutes.length > 0) {\n\t\t\tlogger.warn(\n\t\t\t\t'Both publicRoutes and privateRoutes are defined. Ignoring privateRoutes.'\n\t\t\t);\n\t\t}\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\tpublicRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\tif (privateRoutes.length > 0) {\n\t\treturn (\n\t\t\tisDefaultPublicRoute ||\n\t\t\t!privateRoutes.some((route) => matchWildcardRoute(route, pathname))\n\t\t);\n\t}\n\n\t// If no routes are provided, all routes are private\n\treturn isDefaultPublicRoute;\n};\n\nconst addSessionToHeadersIfExists = (\n\theaders: Headers,\n\tsession: AuthenticationInfo | undefined\n): Headers => {\n\tif (session) {\n\t\tconst requestHeaders = new Headers(headers);\n\t\trequestHeaders.set(\n\t\t\tDESCOPE_SESSION_HEADER,\n\t\t\tBuffer.from(JSON.stringify(session)).toString('base64')\n\t\t);\n\t\treturn requestHeaders;\n\t}\n\treturn headers;\n};\n\n// returns a Middleware that checks if the user is authenticated\n// if the user is not authenticated, it redirects to the redirectUrl\n// if the user is authenticated, it adds the session to the headers\nconst createAuthMiddleware =\n\t(options: MiddlewareOptions = {}) =>\n\tasync (req: NextRequest) => {\n\t\tsetLogger(options.logLevel);\n\t\tlogger.debug('Auth middleware starts');\n\n\t\tconst jwt = getSessionJwt(req);\n\n\t\t// check if the user is authenticated\n\t\tlet session: AuthenticationInfo | undefined;\n\t\ttry {\n\t\t\tsession = await getGlobalSdk({\n\t\t\t\tprojectId: options.projectId,\n\t\t\t\tbaseUrl: options.baseUrl\n\t\t\t}).validateJwt(jwt);\n\t\t} catch (err) {\n\t\t\tlogger.debug('Auth middleware, Failed to validate JWT', err);\n\t\t\tif (!isPublicRoute(req, options)) {\n\t\t\t\tconst redirectUrl = options.redirectUrl || DEFAULT_PUBLIC_ROUTES.signIn;\n\t\t\t\tconst url = req.nextUrl.clone();\n\t\t\t\t// Create a URL object for redirectUrl. 'http://example.com' is just a placeholder.\n\t\t\t\tconst parsedRedirectUrl = new URL(redirectUrl, 'http://example.com');\n\t\t\t\turl.pathname = parsedRedirectUrl.pathname;\n\n\t\t\t\tconst searchParams = mergeSearchParams(\n\t\t\t\t\turl.search,\n\t\t\t\t\tparsedRedirectUrl.search\n\t\t\t\t);\n\t\t\t\tif (searchParams) {\n\t\t\t\t\turl.search = searchParams;\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Auth middleware, Redirecting to ${redirectUrl}`);\n\t\t\t\treturn NextResponse.redirect(url);\n\t\t\t}\n\t\t}\n\n\t\tlogger.debug('Auth middleware finishes');\n\t\t// add the session to the request, if it exists\n\t\tconst headers = addSessionToHeadersIfExists(req.headers, session);\n\t\treturn NextResponse.next({\n\t\t\trequest: {\n\t\t\t\theaders\n\t\t\t}\n\t\t});\n\t};\n\nexport default createAuthMiddleware;\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  const DESCOPE_SESSION_HEADER = 'x-descope-session';
2
2
  const baseHeaders = {
3
3
  'x-descope-sdk-name': 'nextjs',
4
- 'x-descope-sdk-version': "0.9.0"
4
+ 'x-descope-sdk-version': "0.11.0"
5
5
  };
6
6
  const DEFAULT_PUBLIC_ROUTES = {
7
7
  signIn: process.env.SIGN_IN_ROUTE || '/sign-in',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../src/server/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\nexport const DESCOPE_SESSION_HEADER = 'x-descope-session';\n\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n\nexport const DEFAULT_PUBLIC_ROUTES = {\n\tsignIn: process.env.SIGN_IN_ROUTE || '/sign-in',\n\tsignUp: process.env.SIGN_UP_ROUTE || '/sign-up'\n};\n"],"names":[],"mappings":"AAGO,MAAM,sBAAsB,GAAG,oBAAoB;AAE7C,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,OAAa;EACrC;AAEW,MAAA,qBAAqB,GAAG;AACpC,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;AAC/C,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../src/server/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\nexport const DESCOPE_SESSION_HEADER = 'x-descope-session';\n\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n\nexport const DEFAULT_PUBLIC_ROUTES = {\n\tsignIn: process.env.SIGN_IN_ROUTE || '/sign-in',\n\tsignUp: process.env.SIGN_UP_ROUTE || '/sign-up'\n};\n"],"names":[],"mappings":"AAGO,MAAM,sBAAsB,GAAG,oBAAoB;AAE7C,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,QAAa;EACrC;AAEW,MAAA,qBAAqB,GAAG;AACpC,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;AAC/C,IAAA,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,UAAU;;;;;"}
@@ -0,0 +1,25 @@
1
+ // order of levels is important
2
+ const levels = ['debug', 'info', 'warn', 'error'];
3
+ const logger = {
4
+ debug: console.debug,
5
+ info: console.info,
6
+ log: console.log,
7
+ warn: console.warn,
8
+ error: console.error
9
+ };
10
+ const noop = () => { };
11
+ // override global logger according to the level
12
+ const setLogger = (level = 'info') => {
13
+ Object.keys(logger).forEach((key) => {
14
+ const keyToCompare = key === 'log' ? 'info' : key; // log is an alias for info
15
+ if (levels.indexOf(keyToCompare) < levels.indexOf(level)) {
16
+ logger[key] = noop;
17
+ }
18
+ else {
19
+ logger[key] = console[key];
20
+ }
21
+ });
22
+ };
23
+
24
+ export { logger, setLogger };
25
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sources":["../../../src/server/logger.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport { LogLevel } from '../types';\n\n// order of levels is important\nconst levels = ['debug', 'info', 'warn', 'error'];\n\nconst logger = {\n\tdebug: console.debug,\n\tinfo: console.info,\n\tlog: console.log,\n\twarn: console.warn,\n\terror: console.error\n};\n\nconst noop = () => {};\n\n// override global logger according to the level\nexport const setLogger = (level: LogLevel = 'info') => {\n\tObject.keys(logger).forEach((key) => {\n\t\tconst keyToCompare = key === 'log' ? 'info' : key; // log is an alias for info\n\t\tif (levels.indexOf(keyToCompare) < levels.indexOf(level)) {\n\t\t\tlogger[key] = noop;\n\t\t} else {\n\t\t\tlogger[key] = console[key];\n\t\t}\n\t});\n};\n\nexport { logger };\n"],"names":[],"mappings":"AAGA;AACA,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD,MAAM,MAAM,GAAG;IACd,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,GAAG,EAAE,OAAO,CAAC,GAAG;IAChB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,KAAK,EAAE,OAAO,CAAC,KAAK;EACnB;AAEF,MAAM,IAAI,GAAG,MAAK,GAAG,CAAC;AAEtB;MACa,SAAS,GAAG,CAAC,KAAkB,GAAA,MAAM,KAAI;IACrD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,KAAI;AACnC,QAAA,MAAM,YAAY,GAAG,GAAG,KAAK,KAAK,GAAG,MAAM,GAAG,GAAG,CAAC;AAClD,QAAA,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACzD,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;SACnB;aAAM;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;SAC3B;AACF,KAAC,CAAC,CAAC;AACJ;;;;"}
@@ -2,8 +2,8 @@ import descopeSdk from '@descope/node-sdk';
2
2
  import { headers, cookies } from 'next/headers.js';
3
3
  import { DESCOPE_SESSION_HEADER } from './constants.js';
4
4
  import { getGlobalSdk } from './sdk.js';
5
+ import { setLogger, logger } from './logger.js';
5
6
 
6
- /* eslint-disable no-console */
7
7
  const extractSession = (descopeSession) => {
8
8
  if (!descopeSession) {
9
9
  return undefined;
@@ -17,18 +17,18 @@ const extractSession = (descopeSession) => {
17
17
  }
18
18
  };
19
19
  const getSessionFromCookie = async (config) => {
20
- console.debug('attempting to get session from cookie');
20
+ logger.debug('attempting to get session from cookie');
21
21
  try {
22
22
  const sessionCookie = (await cookies()).get(descopeSdk.SessionTokenCookieName);
23
23
  if (!sessionCookie?.value) {
24
- console.debug('Session cookie not found');
24
+ logger.debug('Session cookie not found');
25
25
  return undefined;
26
26
  }
27
27
  const sdk = getGlobalSdk(config);
28
28
  return await sdk.validateJwt(sessionCookie.value);
29
29
  }
30
30
  catch (err) {
31
- console.debug('Error getting session from cookie', err);
31
+ logger.debug('Error getting session from cookie', err);
32
32
  return undefined;
33
33
  }
34
34
  };
@@ -43,13 +43,17 @@ const extractOrGetSession = async (sessionHeader, config) => {
43
43
  };
44
44
  // returns the session token if it exists in the headers
45
45
  const session = async (config) => {
46
+ setLogger(config?.logLevel);
46
47
  // first attempt to get the session from the headers
47
48
  const reqHeaders = await headers();
48
49
  const sessionHeader = reqHeaders.get(DESCOPE_SESSION_HEADER);
49
50
  return extractOrGetSession(sessionHeader, config);
50
51
  };
51
52
  // returns the session token if it exists in the request headers
52
- const getSession = async (req, config) => extractOrGetSession(req.headers[DESCOPE_SESSION_HEADER.toLowerCase()], config);
53
+ const getSession = async (req, config) => {
54
+ setLogger(config?.logLevel);
55
+ return extractOrGetSession(req.headers[DESCOPE_SESSION_HEADER.toLowerCase()], config);
56
+ };
53
57
 
54
58
  export { getSession, session };
55
59
  //# sourceMappingURL=session.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session.js","sources":["../../../src/server/session.ts"],"sourcesContent":["/* eslint-disable no-console */\nimport descopeSdk, { AuthenticationInfo } from '@descope/node-sdk';\nimport { NextApiRequest } from 'next';\nimport { cookies, headers } from 'next/headers';\nimport { DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk, CreateSdkParams } from './sdk';\n\nconst extractSession = (\n\tdescopeSession?: string\n): AuthenticationInfo | undefined => {\n\tif (!descopeSession) {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\tconst authInfo = JSON.parse(\n\t\t\tBuffer.from(descopeSession, 'base64').toString()\n\t\t) as AuthenticationInfo;\n\t\treturn authInfo;\n\t} catch (err) {\n\t\treturn undefined;\n\t}\n};\n\nconst getSessionFromCookie = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n console.debug('attempting to get session from cookie');\n\ttry {\n\t\tconst sessionCookie = (await cookies()).get(\n\t\t\tdescopeSdk.SessionTokenCookieName\n\t\t);\n\t\tif (!sessionCookie?.value) {\n\t\t\tconsole.debug('Session cookie not found');\n\t\t\treturn undefined;\n\t\t}\n\t\tconst sdk = getGlobalSdk(config);\n\t\treturn await sdk.validateJwt(sessionCookie.value);\n\t} catch (err) {\n\t\tconsole.debug('Error getting session from cookie', err);\n\t\treturn undefined;\n\t}\n};\n\n// tries to extract the session header,\n// if it doesn't exist, it will attempt to get the session from the cookie\nconst extractOrGetSession = async (\n\tsessionHeader?: string,\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\tconst session = extractSession(sessionHeader);\n\tif (session) {\n\t\treturn session;\n\t}\n\n\treturn getSessionFromCookie(config);\n};\n\n// returns the session token if it exists in the headers\nexport const session = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\t// first attempt to get the session from the headers\n\tconst reqHeaders = await headers();\n\tconst sessionHeader = reqHeaders.get(DESCOPE_SESSION_HEADER);\n\treturn extractOrGetSession(sessionHeader, config);\n};\n\n// returns the session token if it exists in the request headers\nexport const getSession = async (\n\treq: NextApiRequest,\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> =>\n\textractOrGetSession(\n\t\treq.headers[DESCOPE_SESSION_HEADER.toLowerCase()] as string,\n\t\tconfig\n\t);\n"],"names":[],"mappings":";;;;;AAAA;AAOA,MAAM,cAAc,GAAG,CACtB,cAAuB,KACY;IACnC,IAAI,CAAC,cAAc,EAAE;AACpB,QAAA,OAAO,SAAS,CAAC;KACjB;AACD,IAAA,IAAI;AACH,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAC1B,CAAC;AACxB,QAAA,OAAO,QAAQ,CAAC;KAChB;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,OAC5B,MAAwB,KACoB;AAC3C,IAAA,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACxD,IAAA,IAAI;AACH,QAAA,MAAM,aAAa,GAAG,CAAC,MAAM,OAAO,EAAE,EAAE,GAAG,CAC1C,UAAU,CAAC,sBAAsB,CACjC,CAAC;AACF,QAAA,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE;AAC1B,YAAA,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC1C,YAAA,OAAO,SAAS,CAAC;SACjB;AACD,QAAA,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;KAClD;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;AACxD,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF;AACA;AACA,MAAM,mBAAmB,GAAG,OAC3B,aAAsB,EACtB,MAAwB,KACoB;AAC5C,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE;AACZ,QAAA,OAAO,OAAO,CAAC;KACf;AAED,IAAA,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF;MACa,OAAO,GAAG,OACtB,MAAwB,KACoB;;AAE5C,IAAA,MAAM,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;IACnC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAC7D,IAAA,OAAO,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACnD,EAAE;AAEF;AACa,MAAA,UAAU,GAAG,OACzB,GAAmB,EACnB,MAAwB,KAExB,mBAAmB,CAClB,GAAG,CAAC,OAAO,CAAC,sBAAsB,CAAC,WAAW,EAAE,CAAW,EAC3D,MAAM;;;;"}
1
+ {"version":3,"file":"session.js","sources":["../../../src/server/session.ts"],"sourcesContent":["import descopeSdk, { AuthenticationInfo } from '@descope/node-sdk';\nimport { NextApiRequest } from 'next';\nimport { cookies, headers } from 'next/headers';\nimport { DESCOPE_SESSION_HEADER } from './constants';\nimport { getGlobalSdk, CreateSdkParams } from './sdk';\nimport { LogLevel } from '../types';\nimport { logger, setLogger } from './logger';\n\ntype SessionConfig = CreateSdkParams & {\n\t// The log level to use for the middleware\n\t// Defaults to 'info'\n\tlogLevel?: LogLevel;\n};\n\nconst extractSession = (\n\tdescopeSession?: string\n): AuthenticationInfo | undefined => {\n\tif (!descopeSession) {\n\t\treturn undefined;\n\t}\n\ttry {\n\t\tconst authInfo = JSON.parse(\n\t\t\tBuffer.from(descopeSession, 'base64').toString()\n\t\t) as AuthenticationInfo;\n\t\treturn authInfo;\n\t} catch (err) {\n\t\treturn undefined;\n\t}\n};\n\nconst getSessionFromCookie = async (\n\tconfig?: CreateSdkParams\n): Promise<AuthenticationInfo | undefined> => {\n\tlogger.debug('attempting to get session from cookie');\n\ttry {\n\t\tconst sessionCookie = (await cookies()).get(\n\t\t\tdescopeSdk.SessionTokenCookieName\n\t\t);\n\t\tif (!sessionCookie?.value) {\n\t\t\tlogger.debug('Session cookie not found');\n\t\t\treturn undefined;\n\t\t}\n\t\tconst sdk = getGlobalSdk(config);\n\t\treturn await sdk.validateJwt(sessionCookie.value);\n\t} catch (err) {\n\t\tlogger.debug('Error getting session from cookie', err);\n\t\treturn undefined;\n\t}\n};\n\n// tries to extract the session header,\n// if it doesn't exist, it will attempt to get the session from the cookie\nconst extractOrGetSession = async (\n\tsessionHeader?: string,\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tconst session = extractSession(sessionHeader);\n\tif (session) {\n\t\treturn session;\n\t}\n\n\treturn getSessionFromCookie(config);\n};\n\n// returns the session token if it exists in the headers\nexport const session = async (\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tsetLogger(config?.logLevel);\n\t// first attempt to get the session from the headers\n\tconst reqHeaders = await headers();\n\tconst sessionHeader = reqHeaders.get(DESCOPE_SESSION_HEADER);\n\treturn extractOrGetSession(sessionHeader, config);\n};\n\n// returns the session token if it exists in the request headers\nexport const getSession = async (\n\treq: NextApiRequest,\n\tconfig?: SessionConfig\n): Promise<AuthenticationInfo | undefined> => {\n\tsetLogger(config?.logLevel);\n\treturn extractOrGetSession(\n\t\treq.headers[DESCOPE_SESSION_HEADER.toLowerCase()] as string,\n\t\tconfig\n\t);\n};\n"],"names":[],"mappings":";;;;;;AAcA,MAAM,cAAc,GAAG,CACtB,cAAuB,KACY;IACnC,IAAI,CAAC,cAAc,EAAE;AACpB,QAAA,OAAO,SAAS,CAAC;KACjB;AACD,IAAA,IAAI;AACH,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAC1B,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,CAC1B,CAAC;AACxB,QAAA,OAAO,QAAQ,CAAC;KAChB;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,OAC5B,MAAwB,KACoB;AAC5C,IAAA,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACtD,IAAA,IAAI;AACH,QAAA,MAAM,aAAa,GAAG,CAAC,MAAM,OAAO,EAAE,EAAE,GAAG,CAC1C,UAAU,CAAC,sBAAsB,CACjC,CAAC;AACF,QAAA,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE;AAC1B,YAAA,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;AACzC,YAAA,OAAO,SAAS,CAAC;SACjB;AACD,QAAA,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;KAClD;IAAC,OAAO,GAAG,EAAE;AACb,QAAA,MAAM,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;AACvD,QAAA,OAAO,SAAS,CAAC;KACjB;AACF,CAAC,CAAC;AAEF;AACA;AACA,MAAM,mBAAmB,GAAG,OAC3B,aAAsB,EACtB,MAAsB,KACsB;AAC5C,IAAA,MAAM,OAAO,GAAG,cAAc,CAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE;AACZ,QAAA,OAAO,OAAO,CAAC;KACf;AAED,IAAA,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF;MACa,OAAO,GAAG,OACtB,MAAsB,KACsB;AAC5C,IAAA,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;;AAE5B,IAAA,MAAM,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;IACnC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AAC7D,IAAA,OAAO,mBAAmB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AACnD,EAAE;AAEF;AACa,MAAA,UAAU,GAAG,OACzB,GAAmB,EACnB,MAAsB,KACsB;AAC5C,IAAA,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC5B,IAAA,OAAO,mBAAmB,CACzB,GAAG,CAAC,OAAO,CAAC,sBAAsB,CAAC,WAAW,EAAE,CAAW,EAC3D,MAAM,CACN,CAAC;AACH;;;;"}
@@ -1,7 +1,7 @@
1
1
  // eslint-disable-next-line import/prefer-default-export
2
2
  const baseHeaders = {
3
3
  'x-descope-sdk-name': 'nextjs',
4
- 'x-descope-sdk-version': "0.9.0"
4
+ 'x-descope-sdk-version': "0.11.0"
5
5
  };
6
6
 
7
7
  export { baseHeaders };
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sources":["../../../src/shared/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\n// eslint-disable-next-line import/prefer-default-export\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n"],"names":[],"mappings":"AAGA;AACa,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,OAAa;;;;;"}
1
+ {"version":3,"file":"constants.js","sources":["../../../src/shared/constants.ts"],"sourcesContent":["// Replaced in build time\ndeclare const BUILD_VERSION: string;\n\n// eslint-disable-next-line import/prefer-default-export\nexport const baseHeaders = {\n\t'x-descope-sdk-name': 'nextjs',\n\t'x-descope-sdk-version': BUILD_VERSION\n};\n"],"names":[],"mappings":"AAGA;AACa,MAAA,WAAW,GAAG;AAC1B,IAAA,oBAAoB,EAAE,QAAQ;AAC9B,IAAA,uBAAuB,EAAE,QAAa;;;;;"}
@@ -1,10 +1,12 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
+ import { LogLevel } from '../types';
2
3
  type MiddlewareOptions = {
3
4
  projectId?: string;
4
5
  baseUrl?: string;
5
6
  redirectUrl?: string;
6
7
  publicRoutes?: string[];
7
8
  privateRoutes?: string[];
9
+ logLevel?: LogLevel;
8
10
  };
9
11
  declare const createAuthMiddleware: (options?: MiddlewareOptions) => (req: NextRequest) => Promise<NextResponse<unknown>>;
10
12
  export default createAuthMiddleware;
@@ -0,0 +1,25 @@
1
+ import { LogLevel } from '../types';
2
+ declare const logger: {
3
+ debug: {
4
+ (...data: any[]): void;
5
+ (message?: any, ...optionalParams: any[]): void;
6
+ };
7
+ info: {
8
+ (...data: any[]): void;
9
+ (message?: any, ...optionalParams: any[]): void;
10
+ };
11
+ log: {
12
+ (...data: any[]): void;
13
+ (message?: any, ...optionalParams: any[]): void;
14
+ };
15
+ warn: {
16
+ (...data: any[]): void;
17
+ (message?: any, ...optionalParams: any[]): void;
18
+ };
19
+ error: {
20
+ (...data: any[]): void;
21
+ (message?: any, ...optionalParams: any[]): void;
22
+ };
23
+ };
24
+ export declare const setLogger: (level?: LogLevel) => void;
25
+ export { logger };
@@ -1,5 +1,10 @@
1
1
  import { AuthenticationInfo } from '@descope/node-sdk';
2
2
  import { NextApiRequest } from 'next';
3
3
  import { CreateSdkParams } from './sdk';
4
- export declare const session: (config?: CreateSdkParams) => Promise<AuthenticationInfo | undefined>;
5
- export declare const getSession: (req: NextApiRequest, config?: CreateSdkParams) => Promise<AuthenticationInfo | undefined>;
4
+ import { LogLevel } from '../types';
5
+ type SessionConfig = CreateSdkParams & {
6
+ logLevel?: LogLevel;
7
+ };
8
+ export declare const session: (config?: SessionConfig) => Promise<AuthenticationInfo | undefined>;
9
+ export declare const getSession: (req: NextApiRequest, config?: SessionConfig) => Promise<AuthenticationInfo | undefined>;
10
+ export {};
@@ -33,6 +33,7 @@ export declare const Descope: React.ComponentType<{
33
33
  form?: Record<string, any>;
34
34
  client?: Record<string, any>;
35
35
  styleId?: string;
36
+ dismissScreenErrorOnInput?: boolean;
36
37
  onScreenUpdate?: (screenName: string, context: Record<string, any>, next: (interactionId: string, form: Record<string, any>) => Promise<unknown>, ref: HTMLElement) => boolean | Promise<boolean>;
37
38
  children?: _1.ReactNode;
38
39
  } & _1.RefAttributes<HTMLElement> & AdditionalProps>;
@@ -64,6 +65,7 @@ export declare const SignInFlow: React.ComponentType<{
64
65
  }) => string;
65
66
  client?: Record<string, any>;
66
67
  styleId?: string;
68
+ dismissScreenErrorOnInput?: boolean;
67
69
  onScreenUpdate?: (screenName: string, context: Record<string, any>, next: (interactionId: string, form: Record<string, any>) => Promise<unknown>, ref: HTMLElement) => boolean | Promise<boolean>;
68
70
  } & AdditionalProps>;
69
71
  export declare const SignUpFlow: React.ComponentType<{
@@ -94,6 +96,7 @@ export declare const SignUpFlow: React.ComponentType<{
94
96
  }) => string;
95
97
  client?: Record<string, any>;
96
98
  styleId?: string;
99
+ dismissScreenErrorOnInput?: boolean;
97
100
  onScreenUpdate?: (screenName: string, context: Record<string, any>, next: (interactionId: string, form: Record<string, any>) => Promise<unknown>, ref: HTMLElement) => boolean | Promise<boolean>;
98
101
  } & AdditionalProps>;
99
102
  export declare const SignUpOrInFlow: React.ComponentType<{
@@ -124,6 +127,7 @@ export declare const SignUpOrInFlow: React.ComponentType<{
124
127
  }) => string;
125
128
  client?: Record<string, any>;
126
129
  styleId?: string;
130
+ dismissScreenErrorOnInput?: boolean;
127
131
  onScreenUpdate?: (screenName: string, context: Record<string, any>, next: (interactionId: string, form: Record<string, any>) => Promise<unknown>, ref: HTMLElement) => boolean | Promise<boolean>;
128
132
  } & AdditionalProps>;
129
133
  export {};
@@ -1 +1 @@
1
- export type TempType = {};
1
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descope/nextjs-sdk",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Descope NextJS SDK",
5
5
  "author": "Descope Team <info@descope.com>",
6
6
  "homepage": "https://github.com/descope/descope-js",
@@ -64,9 +64,9 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@descope/node-sdk": "1.6.13",
67
- "@descope/react-sdk": "2.9.0",
68
67
  "@descope/core-js-sdk": "2.38.0",
69
- "@descope/web-component": "3.38.2"
68
+ "@descope/web-component": "3.39.1",
69
+ "@descope/react-sdk": "2.11.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@babel/core": "7.26.0",