@monocloud/auth-nextjs 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["req: NextRequest","req: NextApiRequest","res: NextResponse","NextResponse","res: NextApiResponse","cookie","e: any","NextRequest","NextResponse","request: IMonoCloudCookieRequest","response: IMonoCloudCookieResponse","IncomingMessage","ServerResponse","MonoCloudValidationError","MonoCloudCoreClient","request: MonoCloudRequest","response: MonoCloudResponse","customProps: any","customProps","NextResponse","req: NextRequest | undefined","evt: NextFetchEvent | undefined","options: MonoCloudMiddlewareOptions | undefined","allowedGroups: string[] | undefined","request: IMonoCloudCookieRequest","response: IMonoCloudCookieResponse","MonoCloudValidationError","options: GetTokensOptions | undefined","IncomingMessage","ServerResponse","path: string","request: IMonoCloudCookieRequest | undefined","response: IMonoCloudCookieResponse | undefined","groups: string[] | undefined","options: IsUserInGroupOptions | undefined"],"sources":["../src/requests/monocloud-app-router-request.ts","../src/requests/monocloud-page-router-request.ts","../src/responses/monocloud-app-router-response.ts","../src/responses/monocloud-page-router-response.ts","../src/responses/monocloud-cookie-response.ts","../src/requests/monocloud-cookie-request.ts","../src/utils.ts","../src/monocloud-next-client.ts"],"sourcesContent":["import type { MonoCloudRequest } from '@monocloud/auth-node-core';\n// eslint-disable-next-line import/extensions\nimport type { NextRequest } from 'next/server.js';\n\nexport default class MonoCloudAppRouterRequest implements MonoCloudRequest {\n constructor(public readonly req: NextRequest) {}\n\n getQuery(parameter: string): string | string[] | undefined {\n const url = new URL(this.req.url);\n return url.searchParams.get(parameter) ?? undefined;\n }\n\n getCookie(name: string): Promise<string | undefined> {\n return Promise.resolve(this.req.cookies.get(name)?.value);\n }\n\n async getRawRequest(): Promise<{\n method: string;\n url: string;\n body: Record<string, string> | string;\n }> {\n return {\n method: this.req.method,\n url: this.req.url,\n body: await this.req.text(),\n };\n }\n\n getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n this.req.cookies.getAll().forEach(x => {\n values.set(x.name, x.value);\n });\n return Promise.resolve(values);\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport type { MonoCloudRequest } from '@monocloud/auth-node-core';\nimport type { NextApiRequest } from 'next';\n\nexport default class MonoCloudPageRouterRequest implements MonoCloudRequest {\n constructor(public readonly req: NextApiRequest) {}\n\n /* v8 ignore next */\n getQuery(parameter: string): string | string[] | undefined {\n return this.req.query[parameter];\n }\n\n /* v8 ignore next */\n getCookie(name: string): Promise<string | undefined> {\n return Promise.resolve(this.req.cookies[name]);\n }\n\n /* v8 ignore next */\n getRawRequest(): Promise<{\n method: string;\n url: string;\n body: Record<string, string> | string;\n }> {\n return Promise.resolve({\n method: this.req.method!,\n url: this.req.url!,\n body: this.req.body,\n });\n }\n\n getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n const { cookies } = this.req;\n Object.keys(cookies).forEach(x => {\n const val = cookies[x];\n /* v8 ignore else -- @preserve */\n if (typeof x === 'string' && typeof val === 'string') {\n values.set(x, val);\n }\n });\n return Promise.resolve(values);\n }\n}\n","import type {\n CookieOptions,\n MonoCloudResponse,\n} from '@monocloud/auth-node-core';\n// eslint-disable-next-line import/extensions\nimport { NextResponse } from 'next/server.js';\n\nexport default class MonoCloudAppRouterResponse implements MonoCloudResponse {\n constructor(public res: NextResponse) {}\n\n setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n this.res.cookies.set(cookieName, value, options);\n return Promise.resolve();\n }\n\n redirect(url: string, statusCode: number | undefined = 302): void {\n const { headers } = this.res;\n this.res = NextResponse.redirect(url, { status: statusCode, headers });\n }\n\n sendJson(data: any, statusCode?: number): void {\n const { headers } = this.res;\n this.res = NextResponse.json(data, { status: statusCode, headers });\n }\n\n /* v8 ignore next */\n notFound(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 404, headers });\n }\n\n internalServerError(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 500, headers });\n }\n\n noContent(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 204, headers });\n }\n\n methodNotAllowed(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 405, headers });\n }\n\n setNoCache(): void {\n this.res.headers.set('Cache-Control', 'no-cache no-store');\n this.res.headers.set('Pragma', 'no-cache');\n }\n\n done(): any {\n return this.res;\n }\n}\n","import type {\n CookieOptions,\n MonoCloudResponse,\n} from '@monocloud/auth-node-core';\nimport type { NextApiResponse } from 'next';\nimport { serialize } from 'cookie';\n\nexport default class MonoCloudPageRouterResponse implements MonoCloudResponse {\n constructor(public readonly res: NextApiResponse) {}\n\n setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n let cookies = this.res.getHeader('Set-Cookie') ?? [];\n\n /* v8 ignore if -- @preserve */\n if (!Array.isArray(cookies)) {\n cookies = [cookies as string];\n }\n\n this.res.setHeader('Set-Cookie', [\n ...cookies.filter(cookie => !cookie.startsWith(`${cookieName}=`)),\n serialize(cookieName, value, options),\n ]);\n\n return Promise.resolve();\n }\n\n /* v8 ignore next */\n redirect(url: string, statusCode?: number): void {\n this.res.redirect(statusCode ?? 302, url);\n }\n\n /* v8 ignore next */\n sendJson(data: any, statusCode?: number): void {\n this.res.status(statusCode ?? 200);\n this.res.json(data);\n }\n\n /* v8 ignore next */\n notFound(): void {\n this.res.status(404);\n }\n\n /* v8 ignore next */\n internalServerError(): void {\n this.res.status(500);\n }\n\n /* v8 ignore next */\n noContent(): void {\n this.res.status(204);\n }\n\n /* v8 ignore next */\n methodNotAllowed(): void {\n this.res.status(405);\n }\n\n /* v8 ignore next */\n setNoCache(): void {\n this.res.setHeader('Cache-Control', 'no-cache no-store');\n this.res.setHeader('Pragma', 'no-cache');\n }\n\n /* v8 ignore next */\n done(): any {\n this.res.end();\n }\n}\n","/* eslint-disable no-console */\nimport type {\n CookieOptions,\n IMonoCloudCookieResponse,\n} from '@monocloud/auth-node-core';\n\nlet isWarned = false;\n\nexport default class MonoCloudCookieResponse implements IMonoCloudCookieResponse {\n async setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n (await cookies()).set(cookieName, value, options);\n } catch (e: any) {\n if (!isWarned) {\n console.warn(e.message);\n isWarned = true;\n }\n }\n }\n}\n","import type { IMonoCloudCookieRequest } from '@monocloud/auth-node-core';\n\nexport default class MonoCloudCookieRequest implements IMonoCloudCookieRequest {\n /* v8 ignore next */\n async getCookie(name: string): Promise<string | undefined> {\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n return (await cookies()).get(name)?.value;\n }\n\n async getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n (await cookies()).getAll().forEach((x: any) => {\n values.set(x.name, x.value);\n });\n return values;\n }\n}\n","// eslint-disable-next-line import/extensions\nimport { NextRequest, NextResponse } from 'next/server.js';\nimport type { NextApiRequest, NextApiResponse } from 'next/types';\nimport {\n MonoCloudValidationError,\n type IMonoCloudCookieRequest,\n type IMonoCloudCookieResponse,\n} from '@monocloud/auth-node-core';\nimport { AppRouterContext } from './types';\nimport MonoCloudAppRouterRequest from './requests/monocloud-app-router-request';\nimport MonoCloudPageRouterRequest from './requests/monocloud-page-router-request';\nimport MonoCloudAppRouterResponse from './responses/monocloud-app-router-response';\nimport MonoCloudPageRouterResponse from './responses/monocloud-page-router-response';\nimport MonoCloudCookieResponse from './responses/monocloud-cookie-response';\nimport MonoCloudCookieRequest from './requests/monocloud-cookie-request';\nimport { IncomingMessage, ServerResponse } from 'node:http';\n\nexport const isMonoCloudRequest = (\n req: unknown\n): req is IMonoCloudCookieRequest =>\n req instanceof MonoCloudAppRouterRequest ||\n req instanceof MonoCloudPageRouterRequest ||\n req instanceof MonoCloudCookieRequest;\n\nexport const isMonoCloudResponse = (\n res: unknown\n): res is IMonoCloudCookieResponse =>\n res instanceof MonoCloudAppRouterResponse ||\n res instanceof MonoCloudPageRouterResponse ||\n res instanceof MonoCloudCookieResponse;\n\nexport const isAppRouter = (req: unknown): boolean =>\n req instanceof Request ||\n (req as Request).headers instanceof Headers ||\n typeof (req as Request).bodyUsed === 'boolean';\n\nexport const getNextRequest = (req: Request | NextRequest): NextRequest => {\n if (req instanceof NextRequest) {\n return req;\n }\n\n return new NextRequest(req);\n};\n\nexport const getNextResponse = (\n res: Response | NextResponse | AppRouterContext\n): NextResponse => {\n if (res instanceof NextResponse) {\n return res;\n }\n\n if (res instanceof Response) {\n return new NextResponse(res.body, res);\n }\n\n return new NextResponse();\n};\n\nexport const getMonoCloudCookieReqRes = (\n req: unknown,\n resOrCtx: unknown\n): {\n request: IMonoCloudCookieRequest;\n response: IMonoCloudCookieResponse;\n} => {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (isAppRouter(req)) {\n request = new MonoCloudAppRouterRequest(getNextRequest(req as Request));\n\n response =\n resOrCtx instanceof Response\n ? new MonoCloudAppRouterResponse(getNextResponse(resOrCtx))\n : new MonoCloudCookieResponse();\n } else {\n if (\n !(req instanceof IncomingMessage) ||\n !(resOrCtx instanceof ServerResponse)\n ) {\n throw new MonoCloudValidationError(\n 'Invalid pages router request and response'\n );\n }\n request = new MonoCloudPageRouterRequest(req as NextApiRequest);\n response = new MonoCloudPageRouterResponse(resOrCtx as NextApiResponse);\n }\n\n return { request, response };\n};\n\nexport const mergeResponse = (responses: NextResponse[]): NextResponse => {\n const resp = responses.pop();\n\n if (!resp) {\n return new NextResponse();\n }\n\n responses.forEach(response => {\n response.headers.forEach((v, k) => {\n if ((k === 'location' && !resp.headers.has(k)) || k !== 'location') {\n resp.headers.set(k, v);\n }\n });\n\n response.cookies.getAll().forEach(c => {\n const { name, value, ...cookieOpt } = c;\n resp.cookies.set(name, value, cookieOpt);\n });\n });\n\n return resp;\n};\n","/* eslint-disable import/extensions */\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {\n NextFetchEvent,\n NextRequest,\n NextResponse,\n NextMiddleware,\n NextProxy,\n} from 'next/server.js';\nimport type {\n NextApiHandler,\n NextApiRequest,\n NextApiResponse,\n} from 'next/types';\nimport {\n ensureLeadingSlash,\n isAbsoluteUrl,\n} from '@monocloud/auth-node-core/internal';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport type {\n GetTokensOptions,\n IMonoCloudCookieRequest,\n IMonoCloudCookieResponse,\n MonoCloudOptions,\n MonoCloudRequest,\n MonoCloudResponse,\n MonoCloudTokens,\n MonoCloudSession,\n OnError,\n} from '@monocloud/auth-node-core';\nimport {\n MonoCloudCoreClient,\n MonoCloudValidationError,\n MonoCloudOidcClient,\n} from '@monocloud/auth-node-core';\nimport {\n AppRouterApiHandlerFn,\n AppRouterContext,\n AppRouterPageHandler,\n IsUserInGroupOptions,\n MonoCloudAuthHandler,\n MonoCloudAuthOptions,\n MonoCloudMiddlewareOptions,\n NextMiddlewareResult,\n ProtectApiAppOptions,\n ProtectApiPageOptions,\n ProtectAppPageOptions,\n ProtectedAppServerComponent,\n ProtectOptions,\n ProtectPagePageOptions,\n ProtectPagePageReturnType,\n RedirectToSignInOptions,\n RedirectToSignOutOptions,\n} from './types';\nimport {\n getMonoCloudCookieReqRes,\n getNextRequest,\n getNextResponse,\n isAppRouter,\n isMonoCloudRequest,\n isMonoCloudResponse,\n mergeResponse,\n} from './utils';\nimport MonoCloudCookieRequest from './requests/monocloud-cookie-request';\nimport MonoCloudCookieResponse from './responses/monocloud-cookie-response';\nimport MonoCloudAppRouterRequest from './requests/monocloud-app-router-request';\nimport MonoCloudAppRouterResponse from './responses/monocloud-app-router-response';\nimport { JSX } from 'react';\nimport { ParsedUrlQuery } from 'node:querystring';\nimport { IncomingMessage, ServerResponse } from 'node:http';\nimport MonoCloudPageRouterRequest from './requests/monocloud-page-router-request';\nimport MonoCloudPageRouterResponse from './responses/monocloud-page-router-response';\n\n/**\n * The MonoCloud Next.js Client.\n *\n * @example Using Environment Variables (Recommended)\n *\n * 1. Add following variables to your `.env`.\n *\n * ```bash\n * MONOCLOUD_AUTH_TENANT_DOMAIN=<tenant-domain>\n * MONOCLOUD_AUTH_CLIENT_ID=<client-id>\n * MONOCLOUD_AUTH_CLIENT_SECRET=<client-secret>\n * MONOCLOUD_AUTH_SCOPES=openid profile email # Default\n * MONOCLOUD_AUTH_APP_URL=http://localhost:3000\n * MONOCLOUD_AUTH_COOKIE_SECRET=<cookie-secret>\n * ```\n *\n * 2. Instantiate the client in a shared file (e.g., lib/monocloud.ts)\n *\n * ```typescript\n * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';\n *\n * export const monoCloud = new MonoCloudNextClient();\n * ```\n *\n * 3. Add MonoCloud middleware/proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Using Constructor Options\n *\n * ⚠️ Security Note: Never commit your credentials to version control. Load them from environment variables.\n *\n * 1. Instantiate the client in a shared file (e.g., lib/monocloud.ts)\n *\n * ```typescript\n * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';\n *\n * export const monoCloud = new MonoCloudNextClient({\n * tenantDomain: '<tenant-domain>',\n * clientId: '<client-id>',\n * clientSecret: '<client-secret>',\n * scopes: 'openid profile email', // Default\n * appUrl: 'http://localhost:3000',\n * cookieSecret: '<cookie-secret>'\n * });\n * ```\n * 2. Add MonoCloud middleware/proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * <details>\n * <summary>All Environment Variables</summary>\n * <h4>Core Configuration (Required)</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_CLIENT_ID : </strong>Unique identifier for your application/client.</li>\n * <li><strong>MONOCLOUD_AUTH_CLIENT_SECRET : </strong>Application/client secret.</li>\n * <li><strong>MONOCLOUD_AUTH_TENANT_DOMAIN : </strong>The domain of your MonoCloud tenant (e.g., https://your-tenant.us.monocloud.com).</li>\n * <li><strong>MONOCLOUD_AUTH_APP_URL : </strong>The base URL where your application is hosted.</li>\n * <li><strong>MONOCLOUD_AUTH_COOKIE_SECRET : </strong>A long, random string used to encrypt and sign session cookies.</li>\n * </ul>\n *\n * <h4>Authentication &amp; Security</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_SCOPES : </strong>A space-separated list of OIDC scopes to request (e.g., openid profile email).</li>\n * <li><strong>MONOCLOUD_AUTH_RESOURCE : </strong>The default resource/audience identifier for access tokens.</li>\n * <li><strong>MONOCLOUD_AUTH_USE_PAR : </strong>Enables Pushed Authorization Requests.</li>\n * <li><strong>MONOCLOUD_AUTH_CLOCK_SKEW : </strong>The allowed clock drift in seconds when validating token timestamps.</li>\n * <li><strong>MONOCLOUD_AUTH_FEDERATED_SIGNOUT : </strong>If true, signs the user out of MonoCloud (SSO sign-out) when they sign out of the app.</li>\n * <li><strong>MONOCLOUD_AUTH_RESPONSE_TIMEOUT : </strong>The maximum time in milliseconds to wait for a response.</li>\n * <li><strong>MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES : </strong>Allows dynamic overrides of auth parameters via URL query strings.</li>\n * <li><strong>MONOCLOUD_AUTH_POST_LOGOUT_REDIRECT_URI : </strong>The URL users are sent to after a successful logout.</li>\n * <li><strong>MONOCLOUD_AUTH_USER_INFO : </strong>Determines if user profile data from the UserInfo endpoint should be fetched after authorization code exchange.</li>\n * <li><strong>MONOCLOUD_AUTH_REFETCH_USER_INFO : </strong>If true, re-fetches user information on every request to userinfo endpoint or when calling getTokens()</li>\n * <li><strong>MONOCLOUD_AUTH_ID_TOKEN_SIGNING_ALG : </strong>The expected algorithm for signing ID tokens (e.g., RS256).</li>\n * <li><strong>MONOCLOUD_AUTH_FILTERED_ID_TOKEN_CLAIMS : </strong>A space-separated list of claims to exclude from the session object.</li>\n * </ul>\n *\n * <h4>Routes</h4>\n *\n * <aside>\n * <strong>⚠️ Important: Modifying Default Routes</strong>\n * <p>If you choose to customize any of the default route paths, you must adhere to the following requirements:</p>\n * <ul>\n * <li>\n * <strong>Client-Side Synchronization:</strong> You must also define a corresponding <code>NEXT_PUBLIC_</code> version of the environment variable (e.g., <code>NEXT_PUBLIC_MONOCLOUD_AUTH_CALLBACK_URL</code>). This ensures that client-side components like <code>&lt;SignIn /&gt;</code>, <code>&lt;SignOut /&gt;</code>, and the <code>useAuth()</code> hook can correctly identify your custom endpoints.\n * </li>\n * <li>\n * <strong>Dashboard Configuration:</strong> Changing these URLs will alter the endpoints required by MonoCloud. You must update the <strong>Application URLs</strong> section in your MonoCloud Dashboard to match these new paths.\n * </li>\n * </ul>\n * <p><em>Example:</em></p>\n * <code>\n * MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback<br />\n * NEXT_PUBLIC_MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback\n * </code>\n * <p>In this case, the Redirect URI in your dashboard should be set to: <code>http://localhost:3000/api/custom_callback</code> (assuming local development).</p>\n * </aside>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_CALLBACK_URL : </strong>The application path where MonoCloud sends the user after authentication.</li>\n * <li><strong>MONOCLOUD_AUTH_SIGNIN_URL : </strong>The internal route path to trigger the sign-in.</li>\n * <li><strong>MONOCLOUD_AUTH_SIGNOUT_URL : </strong>The internal route path to trigger the sign-out.</li>\n * <li><strong>MONOCLOUD_AUTH_USER_INFO_URL : </strong>The route that exposes the current user's profile from userinfo endpoint.</li>\n * </ul>\n *\n * <h4>Session Cookie Settings</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_NAME : </strong>The name of the cookie used to store the user session.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PATH : </strong>The scope path for the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_DOMAIN : </strong>The domain scope for the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_HTTP_ONLY : </strong>Prevents client-side scripts from accessing the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SECURE : </strong>Ensures the session cookie is only sent over HTTPS.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SAME_SITE : </strong>The SameSite policy for the session cookie (Lax, Strict, or None).</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PERSISTENT : </strong>If true, the session survives browser restarts.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_SLIDING : </strong>If true, the session will be a sliding session instead of absolute.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_DURATION : </strong>The session lifetime in seconds.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_MAX_DURATION : </strong>The absolute maximum lifetime of a session in seconds.</li>\n * </ul>\n *\n * <h4>State Cookie Settings</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_NAME : </strong>The name of the cookie used to store OpenID state/nonce.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PATH : </strong>The scope path for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_DOMAIN : </strong>The domain scope for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SECURE : </strong>Ensures the state cookie is only sent over HTTPS</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SAME_SITE : </strong>The SameSite policy for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PERSISTENT : </strong>Whether the state cookie is persistent.</li>\n * </ul>\n *\n * <h4>Caching</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_JWKS_CACHE_DURATION : </strong>Duration in seconds to cache the JSON Web Key Set.</li>\n * <li><strong>MONOCLOUD_AUTH_METADATA_CACHE_DURATION : </strong>Duration in seconds to cache the OpenID discovery metadata.</li>\n * </ul>\n * </details>\n *\n *\n */\nexport class MonoCloudNextClient {\n /**\n * The underlying MonoCloud Node Core Client instance.\n *\n * This property exposes the framework-agnostic node core client used by the Next.js client.\n * You can access this to use low-level methods not directly exposed by the Next.js wrapper.\n *\n * @example Manually destroy session\n * ```typescript\n * // req and res must implement IMonoCloudCookieRequest/Response\n * await monoCloud.coreClient.destroySession(request, response);\n * ```\n */\n public readonly coreClient: MonoCloudCoreClient;\n\n /**\n * The underlying OIDC client instance used for low-level OpenID Connect operations.\n *\n * @example\n * // Manually revoke an access token\n * await client.oidcClient.revokeToken(accessToken, 'access_token');\n */\n public get oidcClient(): MonoCloudOidcClient {\n return this.coreClient.oidcClient;\n }\n\n /**\n * @param options Configuration options including domain, client ID, and secret.\n */\n constructor(options?: MonoCloudOptions) {\n const opt = {\n ...(options ?? {}),\n userAgent: options?.userAgent ?? `${SDK_NAME}@${SDK_VERSION}`,\n debugger: options?.debugger ?? SDK_DEBUGGER_NAME,\n };\n\n this.registerPublicEnvVariables();\n this.coreClient = new MonoCloudCoreClient(opt);\n }\n\n /**\n * Creates a **Next.js API route handler** (for both Pages Router and App Router)\n * that processes all MonoCloud authentication endpoints\n * (`/signin`, `/callback`, `/userinfo`, `/signout`).\n *\n * @param options Authentication configuration routes.\n *\n * **Note:** If you are already using `authMiddleware()`, you typically do **not**\n * need this API route handler. This function is intended for applications where\n * middleware cannot be used—such as statically generated (SSG) deployments that still\n * require server-side authentication flows.\n *\n * @example App Router\n *\n * ```typescript\n * // app/api/auth/[...monocloud]/route.ts\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = monoCloud.monoCloudAuth();\n *```\n *\n * @example App Router with Response\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export const GET = (req: NextRequest) => {\n * const authHandler = monoCloud.monoCloudAuth();\n *\n * const res = new NextResponse();\n *\n * res.cookies.set(\"last_auth_requested\", `${Date.now()}`);\n *\n * return authHandler(req, res);\n * };\n * ```\n *\n * @example Pages Router\n *\n * ```typescript\n * // pages/api/auth/[...monocloud].ts\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.monoCloudAuth();\n *```\n *\n * @example Page Router with Response\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default function handler(req: NextApiRequest, res: NextApiResponse) {\n * const authHandler = monoCloud.monoCloudAuth();\n *\n * res.setHeader(\"last_auth_requested\", `${Date.now()}`);\n *\n * return authHandler(req, res);\n * }\n * ```\n *\n */\n public monoCloudAuth(options?: MonoCloudAuthOptions): MonoCloudAuthHandler {\n return (req, resOrCtx) => {\n const { routes, appUrl } = this.getOptions();\n\n let { url = '' } = req;\n\n if (!isAbsoluteUrl(url)) {\n url = new URL(url, appUrl).toString();\n }\n\n const route = new URL(url);\n\n let onError;\n if (typeof options?.onError === 'function') {\n onError = (\n error: Error\n ): void | NextResponse | Promise<void | NextResponse<unknown>> =>\n options.onError!(req as any, resOrCtx as any, error);\n }\n\n let request: MonoCloudRequest;\n let response: MonoCloudResponse;\n\n if (isAppRouter(req)) {\n request = new MonoCloudAppRouterRequest(getNextRequest(req as Request));\n response = new MonoCloudAppRouterResponse(\n getNextResponse(resOrCtx as Response)\n );\n } else {\n request = new MonoCloudPageRouterRequest(req as NextApiRequest);\n response = new MonoCloudPageRouterResponse(resOrCtx as NextApiResponse);\n }\n\n return this.handleAuthRoutes(\n request,\n response,\n route.pathname,\n routes,\n onError\n );\n };\n }\n\n /**\n *\n * ## App Router\n *\n * Restricts access to server-rendered pages in your Next.js App Router application, ensures that only authenticated (and optionally authorized) users can view the page.\n *\n * **Note⚠️ - When using groups to protect a page, 'Access Denied' is rendered by default when the user does not have\n * enough permissions. To display a custom component, pass the `onAccessDenied` parameter.**\n *\n * @param component The App Router server component that protectPage wraps and secures\n * @param options App Router `protectPage()` configuration options\n *\n * @returns A protected page handler.\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.protectPage(async function Home({ user }) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * });\n * ```\n *\n * @example App Router with options\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.protectPage(\n * async function Home({ user }) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * },\n * {\n * returnUrl: \"/dashboard\",\n * groups: [\"admin\"],\n * }\n * );\n * ```\n */\n protectPage(\n component: ProtectedAppServerComponent,\n options?: ProtectAppPageOptions\n ): AppRouterPageHandler;\n\n /**\n * ## Pages Router\n *\n * Restricts access to server-rendered pages in your Next.js Pages Router application, ensures that only authenticated (and optionally authorized) users can view the page.\n *\n * **Note⚠️ - When using groups to protect a page, the page will be rendered even if the user does not have\n * enough permissions. You should check the props for `accessDenied` boolean value to determine whether the user is\n * allowed to accesss the page. Alternatively, you can pass `onAccessDenied` parameter to return custom props.**\n *\n * @param options Pages Router `protectPage()` configuration options\n *\n * @typeParam P - The type of parameters accepted by the page handler.\n * @typeParam Q - The type of query parameters parsed from the URL.\n *\n * @returns A protected page handler.\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { InferGetServerSidePropsType } from \"next\";\n *\n * export default function Home({\n * user,\n * }: InferGetServerSidePropsType<typeof getServerSideProps>) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * }\n *\n * export const getServerSideProps = monoCloud.protectPage();\n * ```\n *\n * @example Pages Router with options\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { GetServerSidePropsContext, InferGetServerSidePropsType } from \"next\";\n *\n * export default function Home({\n * user,\n * url,\n * }: InferGetServerSidePropsType<typeof getServerSideProps>) {\n * console.log(url);\n * return <div>Hi {user?.email}. You accessed a protected page.</div>;\n * }\n *\n * export const getServerSideProps = monoCloud.protectPage({\n * returnUrl: \"/dashboard\",\n * groups: [\"admin\"],\n * getServerSideProps: async (context: GetServerSidePropsContext) => ({\n * props: { url: context.resolvedUrl },\n * }),\n * });\n * ```\n */\n protectPage<\n P extends Record<string, any> = Record<string, any>,\n Q extends ParsedUrlQuery = ParsedUrlQuery,\n >(options?: ProtectPagePageOptions<P, Q>): ProtectPagePageReturnType<P, Q>;\n\n public protectPage(...args: unknown[]): any {\n if (typeof args[0] === 'function') {\n return this.protectAppPage(\n args[0] as AppRouterPageHandler,\n args[1] as ProtectAppPageOptions\n ) as any;\n }\n\n return this.protectPagePage(\n args[0] as ProtectPagePageOptions\n ) as ProtectPagePageReturnType<any, any>;\n }\n\n private protectAppPage(\n component: ProtectedAppServerComponent,\n options?: ProtectAppPageOptions\n ): AppRouterPageHandler {\n return async params => {\n const session = await this.getSession();\n\n if (!session) {\n if (options?.onAccessDenied) {\n return options.onAccessDenied({ ...params });\n }\n\n const { routes, appUrl } = this.getOptions();\n\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n const path = (await headers()).get('x-monocloud-path');\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n options?.returnUrl ?? path ?? '/'\n );\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.acrValues) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set(\n 'ui_locales',\n options.authParams.uiLocales\n );\n }\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set(\n 'login_hint',\n options.authParams.loginHint\n );\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n return redirect(signInRoute.toString());\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n return options.onAccessDenied({ ...params, user: session.user });\n }\n\n return 'Access Denied' as unknown as JSX.Element;\n }\n\n return component({ ...params, user: session.user });\n };\n }\n\n private protectPagePage<\n P extends Record<string, any> = Record<string, any>,\n Q extends ParsedUrlQuery = ParsedUrlQuery,\n >(options?: ProtectPagePageOptions<P, Q>): ProtectPagePageReturnType<P, Q> {\n return async context => {\n const session = await this.getSession(\n context.req as any,\n context.res as any\n );\n\n if (!session) {\n if (options?.onAccessDenied) {\n const customProps: any = await options.onAccessDenied({\n ...context,\n });\n\n const props = {\n ...(customProps ?? {}),\n props: { ...(customProps?.props ?? {}) },\n };\n\n return props;\n }\n\n const { routes, appUrl } = this.getOptions();\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n options?.returnUrl ?? context.resolvedUrl\n );\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.acrValues) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set(\n 'ui_locales',\n options.authParams.uiLocales\n );\n }\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set(\n 'login_hint',\n options.authParams.loginHint\n );\n }\n\n return {\n redirect: {\n destination: signInRoute.toString(),\n permanent: false,\n },\n };\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const customProps: any = (await options.onAccessDenied?.({\n ...context,\n user: session.user,\n })) ?? { props: { accessDenied: true } };\n\n const props = {\n ...customProps,\n props: { ...(customProps.props ?? {}) },\n };\n\n return props;\n }\n\n const customProps: any = options?.getServerSideProps\n ? await options.getServerSideProps(context)\n : {};\n\n const promiseProp = customProps.props;\n\n if (promiseProp instanceof Promise) {\n return {\n ...customProps,\n props: promiseProp.then((props: any) => ({\n user: session.user,\n ...props,\n })),\n };\n }\n\n return {\n ...customProps,\n props: { user: session.user, ...customProps.props },\n };\n };\n }\n\n /**\n * ## App Router\n *\n * Secures Next.js App Router APIs. It ensures only authenticated (and optionally authorized) requests can access the route.\n *\n * @param handler The api route handler function to protect\n * @param options App Router `protectApi()` configuration options\n *\n * @returns Protected route handler\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export const GET = monoCloud.protectApi(async () => {\n * return NextResponse.json({\n * message: \"You accessed a protected endpoint\",\n * });\n * });\n * ```\n */\n protectApi(\n handler: AppRouterApiHandlerFn,\n options?: ProtectApiAppOptions\n ): AppRouterApiHandlerFn;\n\n /**\n * ## Pages Router\n *\n * Secures Next.js Pages Router APIs. It ensures only authenticated (and optionally authorized) requests can access the route.\n *\n * @param handler The api route handler function to protect\n * @param options Pages Router `protectApi()` configuration options\n *\n * @returns Protected route handler\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default monoCloud.protectApi(\n * async (req: NextApiRequest, res: NextApiResponse) => {\n * return res.json({\n * message: \"You accessed a protected endpoint\",\n * });\n * }\n * );\n * ```\n */\n protectApi(\n handler: NextApiHandler,\n options?: ProtectApiPageOptions\n ): NextApiHandler;\n\n public protectApi(\n handler: AppRouterApiHandlerFn | NextApiHandler,\n options?: ProtectApiAppOptions | ProtectApiPageOptions\n ): AppRouterApiHandlerFn | NextApiHandler {\n return (\n req: NextRequest | NextApiRequest,\n resOrCtx: AppRouterContext | NextApiResponse\n ) => {\n if (isAppRouter(req)) {\n return this.protectAppApi(\n req as NextRequest,\n resOrCtx as AppRouterContext,\n handler as AppRouterApiHandlerFn,\n options as ProtectApiAppOptions\n );\n }\n return this.protectPageApi(\n req as NextApiRequest,\n resOrCtx as NextApiResponse,\n handler as NextApiHandler,\n options as ProtectApiPageOptions\n );\n };\n }\n\n private async protectAppApi(\n req: NextRequest,\n ctx: AppRouterContext,\n handler: AppRouterApiHandlerFn,\n options?: ProtectApiAppOptions\n ): Promise<NextResponse> {\n const res = new NextResponse();\n\n const session = await this.getSession(req, res);\n\n if (!session) {\n if (options?.onAccessDenied) {\n const result = await options.onAccessDenied(req, ctx);\n\n if (result instanceof NextResponse) {\n return mergeResponse([res, result]);\n }\n\n return mergeResponse([res, new NextResponse(result.body, result)]);\n }\n\n return mergeResponse([\n res,\n NextResponse.json({ message: 'unauthorized' }, { status: 401 }),\n ]);\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n const result = await options.onAccessDenied(req, ctx);\n\n if (result instanceof NextResponse) {\n return mergeResponse([res, result]);\n }\n\n return mergeResponse([res, new NextResponse(result.body, result)]);\n }\n\n return mergeResponse([\n res,\n NextResponse.json({ message: 'forbidden' }, { status: 403 }),\n ]);\n }\n\n const resp = await handler(req, ctx);\n\n if (resp instanceof NextResponse) {\n return mergeResponse([res, resp]);\n }\n\n return mergeResponse([res, new NextResponse(resp.body, resp)]);\n }\n\n private async protectPageApi(\n req: NextApiRequest,\n res: NextApiResponse,\n handler: NextApiHandler,\n options?: ProtectApiPageOptions\n ): Promise<unknown> {\n const session = await this.getSession(req, res);\n\n if (!session) {\n if (options?.onAccessDenied) {\n return options.onAccessDenied(req, res);\n }\n\n return res.status(401).json({\n message: 'unauthorized',\n });\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n return options.onAccessDenied(req, res, session.user);\n }\n\n return res.status(403).json({\n message: 'forbidden',\n });\n }\n\n return handler(req, res);\n }\n\n /**\n * A middleware/proxy that protects pages and APIs and handles authentication.\n *\n * @param options Middleware configuration options\n *\n * @returns A Next.js middleware/proxy function.\n *\n * @example Protect All Routes\n *\n * - Default behavior: protect all routes matched by `config.matcher`\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect Selected Routes\n *\n * - Protect only the routes listed in `protectedRoutes`\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: [\"/api/admin\", \"^/api/protected(/.*)?$\"],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n *```\n *\n * @example Make All Routes Public\n *\n * - Do not protect any routes; MonoCloud still handles auth endpoints\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: [],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect Routes Dynamically\n *\n * - Decide at runtime which routes to protect\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: (req) => {\n * return req.nextUrl.pathname.startsWith(\"/api/protected\");\n * },\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect routes based on groups\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * // group names or IDs\n * protectedRoutes: [\n * {\n * groups: [\"admin\", \"editor\", \"537e7c3d-a442-4b5b-b308-30837aa045a4\"],\n * routes: [\"/internal\", \"/api/internal(.*)\"],\n * },\n * ],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n */\n authMiddleware(\n options?: MonoCloudMiddlewareOptions\n ): NextMiddleware | NextProxy;\n\n /**\n * A middleware that protects pages and APIs and handles authentication.\n *\n * @param request The Next.js fetch event object.\n * @param event The associated fetch event [Docs](https://nextjs.org/docs/app/api-reference/file-conventions/proxy#waituntil-and-nextfetchevent).\n *\n * @returns A promise resolving to a Next.js middleware result or a Next.js middleware result.\n *\n * @example Nest Custom Middleware\n *\n * - Use your own middleware wrapper and call MonoCloud only for specific routes\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextFetchEvent, NextRequest, NextResponse } from \"next/server\";\n *\n * export default function customMiddleware(req: NextRequest, evt: NextFetchEvent) {\n * if (req.nextUrl.pathname.startsWith(\"/api/protected\")) {\n * return monoCloud.authMiddleware(req, evt);\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n */\n authMiddleware(\n request: NextRequest,\n event: NextFetchEvent\n ): Promise<NextMiddlewareResult> | NextMiddlewareResult;\n\n public authMiddleware(\n ...args: unknown[]\n ):\n | NextMiddleware\n | NextProxy\n | Promise<NextMiddlewareResult>\n | NextMiddlewareResult {\n let req: NextRequest | undefined;\n let evt: NextFetchEvent | undefined;\n let options: MonoCloudMiddlewareOptions | undefined;\n\n /* v8 ignore else -- @preserve */\n if (Array.isArray(args)) {\n if (args.length === 2) {\n /* v8 ignore else -- @preserve */\n if (isAppRouter(args[0])) {\n req = args[0] as NextRequest;\n evt = args[1] as NextFetchEvent;\n }\n }\n\n if (args.length === 1) {\n options = args[0] as MonoCloudMiddlewareOptions;\n }\n }\n\n if (req && evt) {\n return this.authMiddlewareHandler(req, evt, options) as any;\n }\n\n return (request: NextRequest, nxtEvt: NextFetchEvent) => {\n return this.authMiddlewareHandler(request, nxtEvt, options);\n };\n }\n\n private async authMiddlewareHandler(\n req: NextRequest,\n evt: NextFetchEvent,\n options?: MonoCloudMiddlewareOptions\n ): Promise<NextMiddlewareResult> {\n // eslint-disable-next-line no-param-reassign\n req = getNextRequest(req);\n\n if (req.headers.has('x-middleware-subrequest')) {\n return NextResponse.json({ message: 'forbidden' }, { status: 403 });\n }\n\n const { routes, appUrl } = this.getOptions();\n\n if (\n Object.values(routes!)\n .map(x => ensureLeadingSlash(x))\n .includes(req.nextUrl.pathname)\n ) {\n let onError;\n if (typeof options?.onError === 'function') {\n onError = (\n error: Error\n ):\n | Promise<void | NextResponse<unknown>>\n | void\n | NextResponse<unknown> => options.onError!(req, evt, error);\n }\n\n const request = new MonoCloudAppRouterRequest(req);\n const response = new MonoCloudAppRouterResponse(new NextResponse());\n\n return this.handleAuthRoutes(\n request,\n response,\n req.nextUrl.pathname,\n routes,\n onError\n );\n }\n\n const nxtResp = new NextResponse();\n\n nxtResp.headers.set(\n 'x-monocloud-path',\n req.nextUrl.pathname + req.nextUrl.search\n );\n\n let isRouteProtected = true;\n let allowedGroups: string[] | undefined;\n\n if (typeof options?.protectedRoutes === 'function') {\n isRouteProtected = await options.protectedRoutes(req);\n } else if (\n typeof options?.protectedRoutes !== 'undefined' &&\n Array.isArray(options.protectedRoutes)\n ) {\n isRouteProtected = options.protectedRoutes.some(route => {\n if (typeof route === 'string' || route instanceof RegExp) {\n return new RegExp(route).test(req.nextUrl.pathname);\n }\n\n return route.routes.some(groupRoute => {\n const result = new RegExp(groupRoute).test(req.nextUrl.pathname);\n\n if (result) {\n allowedGroups = route.groups;\n }\n\n return result;\n });\n });\n }\n\n if (!isRouteProtected) {\n return NextResponse.next({\n headers: {\n 'x-monocloud-path': req.nextUrl.pathname + req.nextUrl.search,\n },\n });\n }\n\n const session = await this.getSession(req, nxtResp);\n\n if (!session) {\n if (options?.onAccessDenied) {\n const result = await options.onAccessDenied(req, evt);\n\n if (result instanceof NextResponse) {\n return mergeResponse([nxtResp, result]);\n }\n\n if (result) {\n return mergeResponse([\n nxtResp,\n new NextResponse(result.body, result),\n ]);\n }\n\n return NextResponse.next(nxtResp);\n }\n\n if (req.nextUrl.pathname.startsWith('/api')) {\n return mergeResponse([\n nxtResp,\n NextResponse.json({ message: 'unauthorized' }, { status: 401 }),\n ]);\n }\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n req.nextUrl.pathname + req.nextUrl.search\n );\n\n return mergeResponse([nxtResp, NextResponse.redirect(signInRoute)]);\n }\n\n const groupsClaim =\n options?.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM;\n\n const onAccessDenied = options?.onAccessDenied;\n\n if (\n allowedGroups &&\n !isUserInGroup(session.user, allowedGroups, groupsClaim)\n ) {\n if (onAccessDenied) {\n const result = await onAccessDenied(req, evt, session.user);\n\n if (result instanceof NextResponse) {\n return mergeResponse([nxtResp, result]);\n }\n\n if (result) {\n return mergeResponse([\n nxtResp,\n new NextResponse(result.body, result),\n ]);\n }\n\n return NextResponse.next(nxtResp);\n }\n\n if (req.nextUrl.pathname.startsWith('/api')) {\n return mergeResponse([\n nxtResp,\n NextResponse.json({ message: 'forbidden' }, { status: 403 }),\n ]);\n }\n\n return new NextResponse(`forbidden`, {\n status: 403,\n });\n }\n\n return NextResponse.next(nxtResp);\n }\n\n private handleAuthRoutes(\n request: MonoCloudRequest,\n response: MonoCloudResponse,\n path: string,\n routes: MonoCloudOptions['routes'],\n onError?: OnError\n ): Promise<any> {\n switch (path) {\n case ensureLeadingSlash(routes!.signIn):\n return this.coreClient.signIn(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.callback):\n return this.coreClient.callback(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.userInfo):\n return this.coreClient.userInfo(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.signOut):\n return this.coreClient.signOut(request, response, {\n onError,\n });\n\n default:\n response.notFound();\n return response.done();\n }\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * return NextResponse.json({ name: session?.user.name });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const session = await monoCloud.getSession();\n *\n * return <div>{session?.user.name}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getUserAction() {\n * const session = await monoCloud.getSession();\n *\n * return { name: session?.user.name };\n * }\n * ```\n *\n */\n public getSession(): Promise<MonoCloudSession | undefined>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response; otherwise, omit this parameter.\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const session = await monoCloud.getSession(req);\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Middleware/Proxy (Custom Response)\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const session = await monoCloud.getSession(req, res);\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * res.headers.set(\"x-auth-status\", \"active\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const session = await monoCloud.getSession(req);\n *\n * return NextResponse.json({ name: session?.user.name });\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"YOUR CUSTOM RESPONSE\");\n *\n * const session = await monoCloud.getSession(req, res);\n *\n * if (session?.user) {\n * res.cookies.set(\"something\", \"important\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public getSession(\n req: NextRequest | Request,\n res?: NextResponse | Response\n ): Promise<MonoCloudSession | undefined>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @param req NextApiRequest\n * @param res NextApiResponse\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * type Data = {\n * name?: string;\n * };\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse<Data>\n * ) {\n * const session = await monoCloud.getSession(req, res);\n *\n * res.status(200).json({ name: session?.user.name });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ session }: HomeProps) {\n * return <pre>Session: {JSON.stringify(session, null, 2)}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const session = await monoCloud.getSession(context.req, context.res);\n *\n * return {\n * props: {\n * session: session ?? null,\n * },\n * };\n * };\n * ```\n */\n public getSession(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>\n ): Promise<MonoCloudSession | undefined>;\n\n async getSession(...args: any[]): Promise<MonoCloudSession | undefined> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n /* v8 ignore next -- @preserve */\n if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to getSession()'\n );\n }\n\n return await this.coreClient.getSession(request, response);\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const tokens = await monoCloud.getTokens();\n *\n * if (tokens.isExpired) {\n * return new NextResponse(\"Tokens expired\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens();\n *\n * return NextResponse.json({ expired: tokens.isExpired });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const tokens = await monoCloud.getTokens();\n *\n * return <div>Expired: {tokens.isExpired.toString()}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getExpiredAction() {\n * const tokens = await monoCloud.getTokens();\n *\n * return { expired: tokens.isExpired };\n * }\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens({ forceRefresh: true });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens({\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens({\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n */\n public getTokens(options?: GetTokensOptions): Promise<MonoCloudTokens>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const tokens = await monoCloud.getTokens(req);\n *\n * if (tokens.isExpired) {\n * return new NextResponse(\"Tokens expired\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req);\n *\n * return NextResponse.json({ expired: tokens?.isExpired });\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, { forceRefresh: true });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n */\n public getTokens(\n req: NextRequest | Request,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n /**\n * ## Middleware/Proxy or Route Handlers (Custom Response)\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens and updates the provided response object.\n *\n * **Use Case:**\n * - Middleware (when modifying the response).\n * - App Router Route Handlers (when a NextResponse is already initialized).\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response and want token updates (e.g., refreshing) to be applied to it.\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n *```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * res.headers.set(\"x-tokens-expired\", tokens.isExpired.toString());\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, res, { forceRefresh: true });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public getTokens(\n req: NextRequest | Request,\n res: NextResponse | Response,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * @param req The `NextApiRequest` or `IncomingMessage`.\n * @param res The `NextApiResponse` or `ServerResponse`.\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example API Route\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ tokens }: HomeProps) {\n * return <pre>Tokens: {JSON.stringify(tokens, null, 2)}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const tokens = await monoCloud.getTokens(context.req, context.res);\n *\n * return {\n * props: {\n * tokens: tokens ?? null,\n * },\n * };\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, res, { forceRefresh: true });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n */\n public getTokens(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n async getTokens(...args: any[]): Promise<MonoCloudTokens> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n let options: GetTokensOptions | undefined;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else if (args.length === 1) {\n if (args[0] instanceof Request) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n } else {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n options = args[0];\n }\n } else if (args.length === 2 && args[0] instanceof Request) {\n if (args[1] instanceof Response) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n\n options = args[1] as GetTokensOptions;\n }\n } else if (\n args.length === 2 &&\n args[0] instanceof IncomingMessage &&\n args[1] instanceof ServerResponse\n ) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n\n options = args[2] as GetTokensOptions;\n }\n\n if (\n !isMonoCloudRequest(request) ||\n !isMonoCloudResponse(response) ||\n (options && typeof options !== 'object')\n ) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to getTokens()'\n );\n }\n\n return await this.coreClient.getTokens(request, response, options);\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Checks if the current user is authenticated.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return NextResponse.json({ authenticated });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return <div>Authenticated: {authenticated.toString()}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function checkAuthAction() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return { authenticated };\n * }\n * ```\n */\n public isAuthenticated(): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Checks if the current user is authenticated.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response; otherwise, omit this parameter.\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const authenticated = await monoCloud.isAuthenticated(req);\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Middleware/Proxy (Custom Response)\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * res.headers.set(\"x-authenticated\", \"true\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const authenticated = await monoCloud.isAuthenticated(req);\n *\n * return NextResponse.json({ authenticated });\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"YOUR CUSTOM RESPONSE\");\n *\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * if (authenticated) {\n * res.cookies.set(\"something\", \"important\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public isAuthenticated(\n req: NextRequest | Request,\n res?: NextResponse | Response\n ): Promise<boolean>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Checks if the current user is authenticated.\n *\n * @param req NextApiRequest\n * @param res NextApiResponse\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * type Data = {\n * authenticated: boolean;\n * };\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse<Data>\n * ) {\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * res.status(200).json({ authenticated });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ authenticated }: HomeProps) {\n * return <pre>User is {authenticated ? \"logged in\" : \"guest\"}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const authenticated = await monoCloud.isAuthenticated(\n * context.req,\n * context.res\n * );\n *\n * return {\n * props: {\n * authenticated,\n * },\n * };\n * };\n * ```\n */\n public isAuthenticated(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>\n ): Promise<boolean>;\n\n async isAuthenticated(...args: any[]): Promise<boolean> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n /* v8 ignore next -- @preserve */\n if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to isAuthenticated()'\n );\n }\n\n return await this.coreClient.isAuthenticated(request, response);\n }\n\n /**\n * Redirects the user to the sign-in flow if they are not authenticated.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign-in.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * await monoCloud.protect();\n *\n * return <>You are signed in.</>;\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * await monoCloud.protect();\n *\n * return NextResponse.json({ secret: \"ssshhhh!!!\" });\n * };\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getMessage() {\n * await monoCloud.protect();\n *\n * return { secret: \"sssshhhhh!!!\" };\n * }\n * ```\n */\n public async protect(options?: ProtectOptions): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n let path: string;\n try {\n const session = await this.getSession();\n\n if (session && !options?.groups) {\n return;\n }\n\n if (\n session &&\n options &&\n options.groups &&\n isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n return;\n }\n\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n path = (await headers()).get('x-monocloud-path') ?? '/';\n } catch {\n throw new Error(\n 'protect() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signInRoute = new URL(`${appUrl}${routes.signIn}`);\n\n signInRoute.searchParams.set('return_url', options?.returnUrl ?? path);\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set('ui_locales', options.authParams.uiLocales);\n }\n\n if (Array.isArray(options?.authParams?.acrValues)) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set('login_hint', options.authParams.loginHint);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signInRoute.toString());\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const isAdmin = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const allowed = await monoCloud.isUserInGroup([\"admin\", \"editor\"]);\n *\n * if (!allowed) {\n * return new NextResponse(\"Forbidden\", { status: 403 });\n * }\n *\n * return NextResponse.json({ status: \"success\" });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function AdminPanel() {\n * const isAdmin = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!isAdmin) {\n * return <div>Access Denied</div>;\n * }\n *\n * return <div>Admin Control Panel</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function deletePostAction() {\n * const canDelete = await monoCloud.isUserInGroup([\"admin\", \"editor\"]);\n *\n * if (!canDelete) {\n * return { success: false };\n * }\n *\n * return { success: true };\n * }\n * ```\n */\n isUserInGroup(\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const isAdmin = await monoCloud.isUserInGroup(req, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const isMember = await monoCloud.isUserInGroup(req, [\"admin\", \"editor\"]);\n *\n * return NextResponse.json({ isMember });\n * };\n * ```\n */\n isUserInGroup(\n req: NextRequest | Request,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers (Custom Response)\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - Middleware (when modifying the response).\n * - App Router Route Handlers (when a NextResponse is already initialized).\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response and want token updates to be applied to it.\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const isAdmin = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * res.headers.set(\"x-user\", \"admin\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Restricted Content\");\n *\n * const allowed = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!allowed) {\n * return new NextResponse(\"Not Allowed\", res);\n * }\n *\n * return res;\n * };\n * ```\n */\n isUserInGroup(\n req: NextRequest | Request,\n res: NextResponse | Response,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * @param req The `NextApiRequest` or `IncomingMessage`.\n * @param res The `NextApiResponse` or `ServerResponse`.\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example API Route\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const isAdmin = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return res.status(403).json({ error: \"Forbidden\" });\n * }\n *\n * res.status(200).json({ message: \"Welcome Admin\" });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ isAdmin }: HomeProps) {\n * return <div>User is admin: {isAdmin.toString()}</div>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const isAdmin = await monoCloud.isUserInGroup(context.req, context.res, [\n * \"admin\",\n * ]);\n *\n * return {\n * props: {\n * isAdmin,\n * },\n * };\n * };\n * ```\n */\n isUserInGroup(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n public async isUserInGroup(...args: any[]): Promise<boolean> {\n let request: IMonoCloudCookieRequest | undefined;\n let response: IMonoCloudCookieResponse | undefined;\n let groups: string[] | undefined;\n let options: IsUserInGroupOptions | undefined;\n\n if (args.length === 4) {\n groups = args[2];\n options = args[3];\n\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n if (args.length === 3) {\n if (args[0] instanceof Request) {\n if (args[1] instanceof Response) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n groups = args[2];\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(\n args[0],\n undefined\n ));\n groups = args[1];\n options = args[2];\n }\n }\n\n if (\n args[0] instanceof IncomingMessage &&\n args[1] instanceof ServerResponse\n ) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n groups = args[2];\n }\n }\n\n if (args.length === 2) {\n if (args[0] instanceof Request) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n groups = args[1];\n }\n\n if (Array.isArray(args[0])) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n\n groups = args[0];\n options = args[1];\n }\n }\n\n if (args.length === 1) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n\n groups = args[0];\n }\n\n if (\n !Array.isArray(groups) ||\n !isMonoCloudRequest(request) ||\n !isMonoCloudResponse(response) ||\n (options && typeof options !== 'object')\n ) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to isUserInGroup()'\n );\n }\n\n const result = await this.coreClient.isUserInGroup(\n request,\n response,\n groups,\n options?.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options?.matchAll\n );\n\n return result;\n }\n\n /**\n * Redirects the user to the sign-in flow.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign-in.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const allowed = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!allowed) {\n * await monoCloud.redirectToSignIn({ returnUrl: \"/home\" });\n * }\n *\n * return <>You are signed in.</>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function protectedAction() {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * await monoCloud.redirectToSignIn();\n * }\n *\n * return { data: \"Sensitive Data\" };\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * await monoCloud.redirectToSignIn({\n * returnUrl: \"/dashboard\",\n * });\n * }\n *\n * return NextResponse.json({ data: \"Protected content\" });\n * };\n * ```\n */\n public async redirectToSignIn(\n options?: RedirectToSignInOptions\n ): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n await headers();\n } catch {\n throw new Error(\n 'redirectToSignIn() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signInRoute = new URL(`${appUrl}${routes.signIn}`);\n\n if (options?.returnUrl) {\n signInRoute.searchParams.set('return_url', options.returnUrl);\n }\n\n if (options?.maxAge) {\n signInRoute.searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authenticatorHint\n );\n }\n\n if (Array.isArray(options?.scopes)) {\n signInRoute.searchParams.set('scope', options.scopes.join(' '));\n }\n\n if (Array.isArray(options?.resource)) {\n signInRoute.searchParams.set('resource', options.resource.join(' '));\n }\n\n if (options?.display) {\n signInRoute.searchParams.set('display', options.display);\n }\n\n if (options?.uiLocales) {\n signInRoute.searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (Array.isArray(options?.acrValues)) {\n signInRoute.searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.loginHint) {\n signInRoute.searchParams.set('login_hint', options.loginHint);\n }\n\n if (options?.prompt) {\n signInRoute.searchParams.set('prompt', options.prompt);\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signInRoute.toString());\n }\n\n /**\n * Redirects the user to the sign-out flow.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign out.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Page() {\n * const session = await monoCloud.getSession();\n *\n * // Example: Force sign-out if a specific condition is met (e.g., account suspended)\n * if (session?.user.isSuspended) {\n * await monoCloud.redirectToSignOut();\n * }\n *\n * return <>Welcome User</>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function signOutAction() {\n * const session = await monoCloud.getSession();\n *\n * if (session) {\n * await monoCloud.redirectToSignOut();\n * }\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * if (session) {\n * await monoCloud.redirectToSignOut({\n * postLogoutRedirectUri: \"/goodbye\",\n * });\n * }\n *\n * return NextResponse.json({ status: \"already_signed_out\" });\n * };\n * ```\n */\n public async redirectToSignOut(\n options?: RedirectToSignOutOptions\n ): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n await headers();\n } catch {\n throw new Error(\n 'redirectToSignOut() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signOutRoute = new URL(`${appUrl}${routes.signOut}`);\n\n if (options?.postLogoutRedirectUri?.trim().length) {\n signOutRoute.searchParams.set(\n 'post_logout_url',\n options.postLogoutRedirectUri\n );\n }\n\n if (typeof options?.federated === 'boolean') {\n signOutRoute.searchParams.set('federated', options.federated.toString());\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signOutRoute.toString());\n }\n\n private getOptions(): MonoCloudOptions {\n return this.coreClient.getOptions();\n }\n\n private registerPublicEnvVariables(): void {\n Object.keys(process.env)\n .filter(key => key.startsWith('NEXT_PUBLIC_MONOCLOUD_AUTH'))\n .forEach(publicKey => {\n const [, privateKey] = publicKey.split('NEXT_PUBLIC_');\n process.env[privateKey] = process.env[publicKey];\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["req: NextRequest","req: NextApiRequest","res: NextResponse","NextResponse","res: NextApiResponse","cookie","e: any","NextRequest","NextResponse","request: IMonoCloudCookieRequest","response: IMonoCloudCookieResponse","IncomingMessage","ServerResponse","MonoCloudValidationError","MonoCloudCoreClient","request: MonoCloudRequest","response: MonoCloudResponse","customProps: any","customProps","NextResponse","req: NextRequest | undefined","evt: NextFetchEvent | undefined","options: MonoCloudMiddlewareOptions | undefined","allowedGroups: string[] | undefined","request: IMonoCloudCookieRequest","response: IMonoCloudCookieResponse","MonoCloudValidationError","options: GetTokensOptions | undefined","IncomingMessage","ServerResponse","path: string","request: IMonoCloudCookieRequest | undefined","response: IMonoCloudCookieResponse | undefined","groups: string[] | undefined","options: IsUserInGroupOptions | undefined"],"sources":["../src/requests/monocloud-app-router-request.ts","../src/requests/monocloud-page-router-request.ts","../src/responses/monocloud-app-router-response.ts","../src/responses/monocloud-page-router-response.ts","../src/responses/monocloud-cookie-response.ts","../src/requests/monocloud-cookie-request.ts","../src/utils.ts","../src/monocloud-next-client.ts"],"sourcesContent":["import type { MonoCloudRequest } from '@monocloud/auth-node-core';\n// eslint-disable-next-line import/extensions\nimport type { NextRequest } from 'next/server.js';\n\nexport default class MonoCloudAppRouterRequest implements MonoCloudRequest {\n constructor(public readonly req: NextRequest) {}\n\n getQuery(parameter: string): string | string[] | undefined {\n const url = new URL(this.req.url);\n return url.searchParams.get(parameter) ?? undefined;\n }\n\n getCookie(name: string): Promise<string | undefined> {\n return Promise.resolve(this.req.cookies.get(name)?.value);\n }\n\n async getRawRequest(): Promise<{\n method: string;\n url: string;\n body: Record<string, string> | string;\n }> {\n return {\n method: this.req.method,\n url: this.req.url,\n body: await this.req.text(),\n };\n }\n\n getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n this.req.cookies.getAll().forEach(x => {\n values.set(x.name, x.value);\n });\n return Promise.resolve(values);\n }\n}\n","/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport type { MonoCloudRequest } from '@monocloud/auth-node-core';\nimport type { NextApiRequest } from 'next';\n\nexport default class MonoCloudPageRouterRequest implements MonoCloudRequest {\n constructor(public readonly req: NextApiRequest) {}\n\n /* v8 ignore next */\n getQuery(parameter: string): string | string[] | undefined {\n return this.req.query[parameter];\n }\n\n /* v8 ignore next */\n getCookie(name: string): Promise<string | undefined> {\n return Promise.resolve(this.req.cookies[name]);\n }\n\n /* v8 ignore next */\n getRawRequest(): Promise<{\n method: string;\n url: string;\n body: Record<string, string> | string;\n }> {\n return Promise.resolve({\n method: this.req.method!,\n url: this.req.url!,\n body: this.req.body,\n });\n }\n\n getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n const { cookies } = this.req;\n Object.keys(cookies).forEach(x => {\n const val = cookies[x];\n /* v8 ignore else -- @preserve */\n if (typeof x === 'string' && typeof val === 'string') {\n values.set(x, val);\n }\n });\n return Promise.resolve(values);\n }\n}\n","import type {\n CookieOptions,\n MonoCloudResponse,\n} from '@monocloud/auth-node-core';\n// eslint-disable-next-line import/extensions\nimport { NextResponse } from 'next/server.js';\n\nexport default class MonoCloudAppRouterResponse implements MonoCloudResponse {\n constructor(public res: NextResponse) {}\n\n setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n this.res.cookies.set(cookieName, value, options);\n return Promise.resolve();\n }\n\n redirect(url: string, statusCode: number | undefined = 302): void {\n const { headers } = this.res;\n this.res = NextResponse.redirect(url, { status: statusCode, headers });\n }\n\n sendJson(data: any, statusCode?: number): void {\n const { headers } = this.res;\n this.res = NextResponse.json(data, { status: statusCode, headers });\n }\n\n /* v8 ignore next */\n notFound(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 404, headers });\n }\n\n internalServerError(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 500, headers });\n }\n\n noContent(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 204, headers });\n }\n\n methodNotAllowed(): void {\n const { headers } = this.res;\n this.res = new NextResponse(null, { status: 405, headers });\n }\n\n setNoCache(): void {\n this.res.headers.set('Cache-Control', 'no-cache no-store');\n this.res.headers.set('Pragma', 'no-cache');\n }\n\n done(): any {\n return this.res;\n }\n}\n","import type {\n CookieOptions,\n MonoCloudResponse,\n} from '@monocloud/auth-node-core';\nimport type { NextApiResponse } from 'next';\nimport { serialize } from 'cookie';\n\nexport default class MonoCloudPageRouterResponse implements MonoCloudResponse {\n constructor(public readonly res: NextApiResponse) {}\n\n setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n let cookies = this.res.getHeader('Set-Cookie') ?? [];\n\n /* v8 ignore if -- @preserve */\n if (!Array.isArray(cookies)) {\n cookies = [cookies as string];\n }\n\n this.res.setHeader('Set-Cookie', [\n ...cookies.filter(cookie => !cookie.startsWith(`${cookieName}=`)),\n serialize(cookieName, value, options),\n ]);\n\n return Promise.resolve();\n }\n\n /* v8 ignore next */\n redirect(url: string, statusCode?: number): void {\n this.res.redirect(statusCode ?? 302, url);\n }\n\n /* v8 ignore next */\n sendJson(data: any, statusCode?: number): void {\n this.res.status(statusCode ?? 200);\n this.res.json(data);\n }\n\n /* v8 ignore next */\n notFound(): void {\n this.res.status(404);\n }\n\n /* v8 ignore next */\n internalServerError(): void {\n this.res.status(500);\n }\n\n /* v8 ignore next */\n noContent(): void {\n this.res.status(204);\n }\n\n /* v8 ignore next */\n methodNotAllowed(): void {\n this.res.status(405);\n }\n\n /* v8 ignore next */\n setNoCache(): void {\n this.res.setHeader('Cache-Control', 'no-cache no-store');\n this.res.setHeader('Pragma', 'no-cache');\n }\n\n /* v8 ignore next */\n done(): any {\n this.res.end();\n }\n}\n","/* eslint-disable no-console */\nimport type {\n CookieOptions,\n IMonoCloudCookieResponse,\n} from '@monocloud/auth-node-core';\n\nlet isWarned = false;\n\nexport default class MonoCloudCookieResponse implements IMonoCloudCookieResponse {\n async setCookie(\n cookieName: string,\n value: string,\n options: CookieOptions\n ): Promise<void> {\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n (await cookies()).set(cookieName, value, options);\n } catch (e: any) {\n if (!isWarned) {\n console.warn(e.message);\n isWarned = true;\n }\n }\n }\n}\n","import type { IMonoCloudCookieRequest } from '@monocloud/auth-node-core';\n\nexport default class MonoCloudCookieRequest implements IMonoCloudCookieRequest {\n /* v8 ignore next */\n async getCookie(name: string): Promise<string | undefined> {\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n return (await cookies()).get(name)?.value;\n }\n\n async getAllCookies(): Promise<Map<string, string>> {\n const values = new Map<string, string>();\n // @ts-expect-error Cannot find module 'next/headers'\n const { cookies } = await import('next/headers');\n\n (await cookies()).getAll().forEach((x: any) => {\n values.set(x.name, x.value);\n });\n return values;\n }\n}\n","// eslint-disable-next-line import/extensions\nimport { NextRequest, NextResponse } from 'next/server.js';\nimport type { NextApiRequest, NextApiResponse } from 'next/types';\nimport {\n MonoCloudValidationError,\n type IMonoCloudCookieRequest,\n type IMonoCloudCookieResponse,\n} from '@monocloud/auth-node-core';\nimport { AppRouterContext } from './types';\nimport MonoCloudAppRouterRequest from './requests/monocloud-app-router-request';\nimport MonoCloudPageRouterRequest from './requests/monocloud-page-router-request';\nimport MonoCloudAppRouterResponse from './responses/monocloud-app-router-response';\nimport MonoCloudPageRouterResponse from './responses/monocloud-page-router-response';\nimport MonoCloudCookieResponse from './responses/monocloud-cookie-response';\nimport MonoCloudCookieRequest from './requests/monocloud-cookie-request';\nimport { IncomingMessage, ServerResponse } from 'node:http';\nimport { isPresent } from '@monocloud/auth-node-core/internal';\n\nexport const isMonoCloudRequest = (\n req: unknown\n): req is IMonoCloudCookieRequest =>\n req instanceof MonoCloudAppRouterRequest ||\n req instanceof MonoCloudPageRouterRequest ||\n req instanceof MonoCloudCookieRequest;\n\nexport const isMonoCloudResponse = (\n res: unknown\n): res is IMonoCloudCookieResponse =>\n res instanceof MonoCloudAppRouterResponse ||\n res instanceof MonoCloudPageRouterResponse ||\n res instanceof MonoCloudCookieResponse;\n\nexport const isAppRouter = (req: unknown): boolean =>\n req instanceof Request ||\n (req as Request).headers instanceof Headers ||\n typeof (req as Request).bodyUsed === 'boolean';\n\nexport const getNextRequest = (req: Request | NextRequest): NextRequest => {\n if (req instanceof NextRequest) {\n return req;\n }\n\n return new NextRequest(req.url, {\n method: req.method,\n headers: req.headers,\n body: req.body,\n /* v8 ignore next -- @preserve */\n duplex: (req as any).duplex ?? 'half',\n });\n};\n\nexport const getNextResponse = (\n res: Response | NextResponse | AppRouterContext\n): NextResponse => {\n if (res instanceof NextResponse) {\n return res;\n }\n\n if (res instanceof Response) {\n const nextResponse = new NextResponse(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers: res.headers,\n url: res.url,\n });\n\n try {\n /* v8 ignore else -- @preserve */\n if (!isPresent(nextResponse.url)) {\n (nextResponse as any).url = res.url;\n }\n } catch {\n // ignore\n }\n\n return nextResponse;\n }\n\n return new NextResponse();\n};\n\nexport const getMonoCloudCookieReqRes = (\n req: unknown,\n resOrCtx: unknown\n): {\n request: IMonoCloudCookieRequest;\n response: IMonoCloudCookieResponse;\n} => {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (isAppRouter(req)) {\n request = new MonoCloudAppRouterRequest(getNextRequest(req as Request));\n\n response =\n resOrCtx instanceof Response\n ? new MonoCloudAppRouterResponse(getNextResponse(resOrCtx))\n : new MonoCloudCookieResponse();\n } else {\n if (\n !(req instanceof IncomingMessage) ||\n !(resOrCtx instanceof ServerResponse)\n ) {\n throw new MonoCloudValidationError(\n 'Invalid pages router request and response'\n );\n }\n request = new MonoCloudPageRouterRequest(req as NextApiRequest);\n response = new MonoCloudPageRouterResponse(resOrCtx as NextApiResponse);\n }\n\n return { request, response };\n};\n\nexport const mergeResponse = (responses: NextResponse[]): NextResponse => {\n const resp = responses.pop();\n\n if (!resp) {\n return new NextResponse();\n }\n\n responses.forEach(response => {\n response.headers.forEach((v, k) => {\n if ((k === 'location' && !resp.headers.has(k)) || k !== 'location') {\n resp.headers.set(k, v);\n }\n });\n\n response.cookies.getAll().forEach(c => {\n const { name, value, ...cookieOpt } = c;\n resp.cookies.set(name, value, cookieOpt);\n });\n });\n\n return resp;\n};\n","/* eslint-disable import/extensions */\n/* eslint-disable @typescript-eslint/no-non-null-assertion */\nimport {\n NextFetchEvent,\n NextRequest,\n NextResponse,\n NextMiddleware,\n NextProxy,\n} from 'next/server.js';\nimport type {\n NextApiHandler,\n NextApiRequest,\n NextApiResponse,\n} from 'next/types';\nimport {\n ensureLeadingSlash,\n isAbsoluteUrl,\n} from '@monocloud/auth-node-core/internal';\nimport { isUserInGroup } from '@monocloud/auth-node-core/utils';\nimport type {\n GetTokensOptions,\n IMonoCloudCookieRequest,\n IMonoCloudCookieResponse,\n MonoCloudOptions,\n MonoCloudRequest,\n MonoCloudResponse,\n MonoCloudTokens,\n MonoCloudSession,\n OnError,\n} from '@monocloud/auth-node-core';\nimport {\n MonoCloudCoreClient,\n MonoCloudValidationError,\n MonoCloudOidcClient,\n} from '@monocloud/auth-node-core';\nimport {\n AppRouterApiHandlerFn,\n AppRouterContext,\n AppRouterPageHandler,\n IsUserInGroupOptions,\n MonoCloudAuthHandler,\n MonoCloudAuthOptions,\n MonoCloudMiddlewareOptions,\n NextMiddlewareResult,\n ProtectApiAppOptions,\n ProtectApiPageOptions,\n ProtectAppPageOptions,\n ProtectedAppServerComponent,\n ProtectOptions,\n ProtectPagePageOptions,\n ProtectPagePageReturnType,\n RedirectToSignInOptions,\n RedirectToSignOutOptions,\n} from './types';\nimport {\n getMonoCloudCookieReqRes,\n getNextRequest,\n getNextResponse,\n isAppRouter,\n isMonoCloudRequest,\n isMonoCloudResponse,\n mergeResponse,\n} from './utils';\nimport MonoCloudCookieRequest from './requests/monocloud-cookie-request';\nimport MonoCloudCookieResponse from './responses/monocloud-cookie-response';\nimport MonoCloudAppRouterRequest from './requests/monocloud-app-router-request';\nimport MonoCloudAppRouterResponse from './responses/monocloud-app-router-response';\nimport { JSX } from 'react';\nimport { ParsedUrlQuery } from 'node:querystring';\nimport { IncomingMessage, ServerResponse } from 'node:http';\nimport MonoCloudPageRouterRequest from './requests/monocloud-page-router-request';\nimport MonoCloudPageRouterResponse from './responses/monocloud-page-router-response';\n\n/**\n * The MonoCloud Next.js Client.\n *\n * @example Using Environment Variables (Recommended)\n *\n * 1. Add following variables to your `.env`.\n *\n * ```bash\n * MONOCLOUD_AUTH_TENANT_DOMAIN=<tenant-domain>\n * MONOCLOUD_AUTH_CLIENT_ID=<client-id>\n * MONOCLOUD_AUTH_CLIENT_SECRET=<client-secret>\n * MONOCLOUD_AUTH_SCOPES=openid profile email # Default\n * MONOCLOUD_AUTH_APP_URL=http://localhost:3000\n * MONOCLOUD_AUTH_COOKIE_SECRET=<cookie-secret>\n * ```\n *\n * 2. Instantiate the client in a shared file (e.g., lib/monocloud.ts)\n *\n * ```typescript\n * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';\n *\n * export const monoCloud = new MonoCloudNextClient();\n * ```\n *\n * 3. Add MonoCloud middleware/proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Using Constructor Options\n *\n * ⚠️ Security Note: Never commit your credentials to version control. Load them from environment variables.\n *\n * 1. Instantiate the client in a shared file (e.g., lib/monocloud.ts)\n *\n * ```typescript\n * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';\n *\n * export const monoCloud = new MonoCloudNextClient({\n * tenantDomain: '<tenant-domain>',\n * clientId: '<client-id>',\n * clientSecret: '<client-secret>',\n * scopes: 'openid profile email', // Default\n * appUrl: 'http://localhost:3000',\n * cookieSecret: '<cookie-secret>'\n * });\n * ```\n * 2. Add MonoCloud middleware/proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * <details>\n * <summary>All Environment Variables</summary>\n * <h4>Core Configuration (Required)</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_CLIENT_ID : </strong>Unique identifier for your application/client.</li>\n * <li><strong>MONOCLOUD_AUTH_CLIENT_SECRET : </strong>Application/client secret.</li>\n * <li><strong>MONOCLOUD_AUTH_TENANT_DOMAIN : </strong>The domain of your MonoCloud tenant (e.g., https://your-tenant.us.monocloud.com).</li>\n * <li><strong>MONOCLOUD_AUTH_APP_URL : </strong>The base URL where your application is hosted.</li>\n * <li><strong>MONOCLOUD_AUTH_COOKIE_SECRET : </strong>A long, random string used to encrypt and sign session cookies.</li>\n * </ul>\n *\n * <h4>Authentication &amp; Security</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_SCOPES : </strong>A space-separated list of OIDC scopes to request (e.g., openid profile email).</li>\n * <li><strong>MONOCLOUD_AUTH_RESOURCE : </strong>The default resource/audience identifier for access tokens.</li>\n * <li><strong>MONOCLOUD_AUTH_USE_PAR : </strong>Enables Pushed Authorization Requests.</li>\n * <li><strong>MONOCLOUD_AUTH_CLOCK_SKEW : </strong>The allowed clock drift in seconds when validating token timestamps.</li>\n * <li><strong>MONOCLOUD_AUTH_FEDERATED_SIGNOUT : </strong>If true, signs the user out of MonoCloud (SSO sign-out) when they sign out of the app.</li>\n * <li><strong>MONOCLOUD_AUTH_RESPONSE_TIMEOUT : </strong>The maximum time in milliseconds to wait for a response.</li>\n * <li><strong>MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES : </strong>Allows dynamic overrides of auth parameters via URL query strings.</li>\n * <li><strong>MONOCLOUD_AUTH_POST_LOGOUT_REDIRECT_URI : </strong>The URL users are sent to after a successful logout.</li>\n * <li><strong>MONOCLOUD_AUTH_USER_INFO : </strong>Determines if user profile data from the UserInfo endpoint should be fetched after authorization code exchange.</li>\n * <li><strong>MONOCLOUD_AUTH_REFETCH_USER_INFO : </strong>If true, re-fetches user information on every request to userinfo endpoint or when calling getTokens()</li>\n * <li><strong>MONOCLOUD_AUTH_ID_TOKEN_SIGNING_ALG : </strong>The expected algorithm for signing ID tokens (e.g., RS256).</li>\n * <li><strong>MONOCLOUD_AUTH_FILTERED_ID_TOKEN_CLAIMS : </strong>A space-separated list of claims to exclude from the session object.</li>\n * </ul>\n *\n * <h4>Routes</h4>\n *\n * <aside>\n * <strong>⚠️ Important: Modifying Default Routes</strong>\n * <p>If you choose to customize any of the default route paths, you must adhere to the following requirements:</p>\n * <ul>\n * <li>\n * <strong>Client-Side Synchronization:</strong> You must also define a corresponding <code>NEXT_PUBLIC_</code> version of the environment variable (e.g., <code>NEXT_PUBLIC_MONOCLOUD_AUTH_CALLBACK_URL</code>). This ensures that client-side components like <code>&lt;SignIn /&gt;</code>, <code>&lt;SignOut /&gt;</code>, and the <code>useAuth()</code> hook can correctly identify your custom endpoints.\n * </li>\n * <li>\n * <strong>Dashboard Configuration:</strong> Changing these URLs will alter the endpoints required by MonoCloud. You must update the <strong>Application URLs</strong> section in your MonoCloud Dashboard to match these new paths.\n * </li>\n * </ul>\n * <p><em>Example:</em></p>\n * <code>\n * MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback<br />\n * NEXT_PUBLIC_MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback\n * </code>\n * <p>In this case, the Redirect URI in your dashboard should be set to: <code>http://localhost:3000/api/custom_callback</code> (assuming local development).</p>\n * </aside>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_CALLBACK_URL : </strong>The application path where MonoCloud sends the user after authentication.</li>\n * <li><strong>MONOCLOUD_AUTH_SIGNIN_URL : </strong>The internal route path to trigger the sign-in.</li>\n * <li><strong>MONOCLOUD_AUTH_SIGNOUT_URL : </strong>The internal route path to trigger the sign-out.</li>\n * <li><strong>MONOCLOUD_AUTH_USER_INFO_URL : </strong>The route that exposes the current user's profile from userinfo endpoint.</li>\n * </ul>\n *\n * <h4>Session Cookie Settings</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_NAME : </strong>The name of the cookie used to store the user session.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PATH : </strong>The scope path for the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_DOMAIN : </strong>The domain scope for the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_HTTP_ONLY : </strong>Prevents client-side scripts from accessing the session cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SECURE : </strong>Ensures the session cookie is only sent over HTTPS.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SAME_SITE : </strong>The SameSite policy for the session cookie (Lax, Strict, or None).</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PERSISTENT : </strong>If true, the session survives browser restarts.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_SLIDING : </strong>If true, the session will be a sliding session instead of absolute.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_DURATION : </strong>The session lifetime in seconds.</li>\n * <li><strong>MONOCLOUD_AUTH_SESSION_MAX_DURATION : </strong>The absolute maximum lifetime of a session in seconds.</li>\n * </ul>\n *\n * <h4>State Cookie Settings</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_NAME : </strong>The name of the cookie used to store OpenID state/nonce.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PATH : </strong>The scope path for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_DOMAIN : </strong>The domain scope for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SECURE : </strong>Ensures the state cookie is only sent over HTTPS</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SAME_SITE : </strong>The SameSite policy for the state cookie.</li>\n * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PERSISTENT : </strong>Whether the state cookie is persistent.</li>\n * </ul>\n *\n * <h4>Caching</h4>\n *\n * <ul>\n * <li><strong>MONOCLOUD_AUTH_JWKS_CACHE_DURATION : </strong>Duration in seconds to cache the JSON Web Key Set.</li>\n * <li><strong>MONOCLOUD_AUTH_METADATA_CACHE_DURATION : </strong>Duration in seconds to cache the OpenID discovery metadata.</li>\n * </ul>\n * </details>\n *\n *\n */\nexport class MonoCloudNextClient {\n /**\n * The underlying MonoCloud Node Core Client instance.\n *\n * This property exposes the framework-agnostic node core client used by the Next.js client.\n * You can access this to use low-level methods not directly exposed by the Next.js wrapper.\n *\n * @example Manually destroy session\n * ```typescript\n * // req and res must implement IMonoCloudCookieRequest/Response\n * await monoCloud.coreClient.destroySession(request, response);\n * ```\n */\n public readonly coreClient: MonoCloudCoreClient;\n\n /**\n * The underlying OIDC client instance used for low-level OpenID Connect operations.\n *\n * @example\n * // Manually revoke an access token\n * await client.oidcClient.revokeToken(accessToken, 'access_token');\n */\n public get oidcClient(): MonoCloudOidcClient {\n return this.coreClient.oidcClient;\n }\n\n /**\n * @param options Configuration options including domain, client ID, and secret.\n */\n constructor(options?: MonoCloudOptions) {\n const opt = {\n ...(options ?? {}),\n userAgent: options?.userAgent ?? `${SDK_NAME}@${SDK_VERSION}`,\n debugger: options?.debugger ?? SDK_DEBUGGER_NAME,\n };\n\n this.registerPublicEnvVariables();\n this.coreClient = new MonoCloudCoreClient(opt);\n }\n\n /**\n * Creates a **Next.js API route handler** (for both Pages Router and App Router)\n * that processes all MonoCloud authentication endpoints\n * (`/signin`, `/callback`, `/userinfo`, `/signout`).\n *\n * @param options Authentication configuration routes.\n *\n * **Note:** If you are already using `authMiddleware()`, you typically do **not**\n * need this API route handler. This function is intended for applications where\n * middleware cannot be used—such as statically generated (SSG) deployments that still\n * require server-side authentication flows.\n *\n * @example App Router\n *\n * ```typescript\n * // app/api/auth/[...monocloud]/route.ts\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = monoCloud.monoCloudAuth();\n *```\n *\n * @example App Router with Response\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export const GET = (req: NextRequest) => {\n * const authHandler = monoCloud.monoCloudAuth();\n *\n * const res = new NextResponse();\n *\n * res.cookies.set(\"last_auth_requested\", `${Date.now()}`);\n *\n * return authHandler(req, res);\n * };\n * ```\n *\n * @example Pages Router\n *\n * ```typescript\n * // pages/api/auth/[...monocloud].ts\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.monoCloudAuth();\n *```\n *\n * @example Page Router with Response\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default function handler(req: NextApiRequest, res: NextApiResponse) {\n * const authHandler = monoCloud.monoCloudAuth();\n *\n * res.setHeader(\"last_auth_requested\", `${Date.now()}`);\n *\n * return authHandler(req, res);\n * }\n * ```\n *\n */\n public monoCloudAuth(options?: MonoCloudAuthOptions): MonoCloudAuthHandler {\n return (req, resOrCtx) => {\n const { routes, appUrl } = this.getOptions();\n\n let { url = '' } = req;\n\n if (!isAbsoluteUrl(url)) {\n url = new URL(url, appUrl).toString();\n }\n\n const route = new URL(url);\n\n let onError;\n if (typeof options?.onError === 'function') {\n onError = (\n error: Error\n ): void | NextResponse | Promise<void | NextResponse<unknown>> =>\n options.onError!(req as any, resOrCtx as any, error);\n }\n\n let request: MonoCloudRequest;\n let response: MonoCloudResponse;\n\n if (isAppRouter(req)) {\n request = new MonoCloudAppRouterRequest(getNextRequest(req as Request));\n response = new MonoCloudAppRouterResponse(\n getNextResponse(resOrCtx as Response)\n );\n } else {\n request = new MonoCloudPageRouterRequest(req as NextApiRequest);\n response = new MonoCloudPageRouterResponse(resOrCtx as NextApiResponse);\n }\n\n return this.handleAuthRoutes(\n request,\n response,\n route.pathname,\n routes,\n onError\n );\n };\n }\n\n /**\n *\n * ## App Router\n *\n * Restricts access to server-rendered pages in your Next.js App Router application, ensures that only authenticated (and optionally authorized) users can view the page.\n *\n * **Note⚠️ - When using groups to protect a page, 'Access Denied' is rendered by default when the user does not have\n * enough permissions. To display a custom component, pass the `onAccessDenied` parameter.**\n *\n * @param component The App Router server component that protectPage wraps and secures\n * @param options App Router `protectPage()` configuration options\n *\n * @returns A protected page handler.\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.protectPage(async function Home({ user }) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * });\n * ```\n *\n * @example App Router with options\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.protectPage(\n * async function Home({ user }) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * },\n * {\n * returnUrl: \"/dashboard\",\n * groups: [\"admin\"],\n * }\n * );\n * ```\n */\n protectPage(\n component: ProtectedAppServerComponent,\n options?: ProtectAppPageOptions\n ): AppRouterPageHandler;\n\n /**\n * ## Pages Router\n *\n * Restricts access to server-rendered pages in your Next.js Pages Router application, ensures that only authenticated (and optionally authorized) users can view the page.\n *\n * **Note⚠️ - When using groups to protect a page, the page will be rendered even if the user does not have\n * enough permissions. You should check the props for `accessDenied` boolean value to determine whether the user is\n * allowed to accesss the page. Alternatively, you can pass `onAccessDenied` parameter to return custom props.**\n *\n * @param options Pages Router `protectPage()` configuration options\n *\n * @typeParam P - The type of parameters accepted by the page handler.\n * @typeParam Q - The type of query parameters parsed from the URL.\n *\n * @returns A protected page handler.\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { InferGetServerSidePropsType } from \"next\";\n *\n * export default function Home({\n * user,\n * }: InferGetServerSidePropsType<typeof getServerSideProps>) {\n * return <>Hi {user.email}. You accessed a protected page.</>;\n * }\n *\n * export const getServerSideProps = monoCloud.protectPage();\n * ```\n *\n * @example Pages Router with options\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { GetServerSidePropsContext, InferGetServerSidePropsType } from \"next\";\n *\n * export default function Home({\n * user,\n * url,\n * }: InferGetServerSidePropsType<typeof getServerSideProps>) {\n * console.log(url);\n * return <div>Hi {user?.email}. You accessed a protected page.</div>;\n * }\n *\n * export const getServerSideProps = monoCloud.protectPage({\n * returnUrl: \"/dashboard\",\n * groups: [\"admin\"],\n * getServerSideProps: async (context: GetServerSidePropsContext) => ({\n * props: { url: context.resolvedUrl },\n * }),\n * });\n * ```\n */\n protectPage<\n P extends Record<string, any> = Record<string, any>,\n Q extends ParsedUrlQuery = ParsedUrlQuery,\n >(options?: ProtectPagePageOptions<P, Q>): ProtectPagePageReturnType<P, Q>;\n\n public protectPage(...args: unknown[]): any {\n if (typeof args[0] === 'function') {\n return this.protectAppPage(\n args[0] as AppRouterPageHandler,\n args[1] as ProtectAppPageOptions\n ) as any;\n }\n\n return this.protectPagePage(\n args[0] as ProtectPagePageOptions\n ) as ProtectPagePageReturnType<any, any>;\n }\n\n private protectAppPage(\n component: ProtectedAppServerComponent,\n options?: ProtectAppPageOptions\n ): AppRouterPageHandler {\n return async params => {\n const session = await this.getSession();\n\n if (!session) {\n if (options?.onAccessDenied) {\n return options.onAccessDenied({ ...params });\n }\n\n const { routes, appUrl } = this.getOptions();\n\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n const path = (await headers()).get('x-monocloud-path');\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n options?.returnUrl ?? path ?? '/'\n );\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.acrValues) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set(\n 'ui_locales',\n options.authParams.uiLocales\n );\n }\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set(\n 'login_hint',\n options.authParams.loginHint\n );\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n return redirect(signInRoute.toString());\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n return options.onAccessDenied({ ...params, user: session.user });\n }\n\n return 'Access Denied' as unknown as JSX.Element;\n }\n\n return component({ ...params, user: session.user });\n };\n }\n\n private protectPagePage<\n P extends Record<string, any> = Record<string, any>,\n Q extends ParsedUrlQuery = ParsedUrlQuery,\n >(options?: ProtectPagePageOptions<P, Q>): ProtectPagePageReturnType<P, Q> {\n return async context => {\n const session = await this.getSession(\n context.req as any,\n context.res as any\n );\n\n if (!session) {\n if (options?.onAccessDenied) {\n const customProps: any = await options.onAccessDenied({\n ...context,\n });\n\n const props = {\n ...(customProps ?? {}),\n props: { ...(customProps?.props ?? {}) },\n };\n\n return props;\n }\n\n const { routes, appUrl } = this.getOptions();\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n options?.returnUrl ?? context.resolvedUrl\n );\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.acrValues) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set(\n 'ui_locales',\n options.authParams.uiLocales\n );\n }\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set(\n 'login_hint',\n options.authParams.loginHint\n );\n }\n\n return {\n redirect: {\n destination: signInRoute.toString(),\n permanent: false,\n },\n };\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n const customProps: any = (await options.onAccessDenied?.({\n ...context,\n user: session.user,\n })) ?? { props: { accessDenied: true } };\n\n const props = {\n ...customProps,\n props: { ...(customProps.props ?? {}) },\n };\n\n return props;\n }\n\n const customProps: any = options?.getServerSideProps\n ? await options.getServerSideProps(context)\n : {};\n\n const promiseProp = customProps.props;\n\n if (promiseProp instanceof Promise) {\n return {\n ...customProps,\n props: promiseProp.then((props: any) => ({\n user: session.user,\n ...props,\n })),\n };\n }\n\n return {\n ...customProps,\n props: { user: session.user, ...customProps.props },\n };\n };\n }\n\n /**\n * ## App Router\n *\n * Secures Next.js App Router APIs. It ensures only authenticated (and optionally authorized) requests can access the route.\n *\n * @param handler The api route handler function to protect\n * @param options App Router `protectApi()` configuration options\n *\n * @returns Protected route handler\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export const GET = monoCloud.protectApi(async () => {\n * return NextResponse.json({\n * message: \"You accessed a protected endpoint\",\n * });\n * });\n * ```\n */\n protectApi(\n handler: AppRouterApiHandlerFn,\n options?: ProtectApiAppOptions\n ): AppRouterApiHandlerFn;\n\n /**\n * ## Pages Router\n *\n * Secures Next.js Pages Router APIs. It ensures only authenticated (and optionally authorized) requests can access the route.\n *\n * @param handler The api route handler function to protect\n * @param options Pages Router `protectApi()` configuration options\n *\n * @returns Protected route handler\n *\n * @example\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default monoCloud.protectApi(\n * async (req: NextApiRequest, res: NextApiResponse) => {\n * return res.json({\n * message: \"You accessed a protected endpoint\",\n * });\n * }\n * );\n * ```\n */\n protectApi(\n handler: NextApiHandler,\n options?: ProtectApiPageOptions\n ): NextApiHandler;\n\n public protectApi(\n handler: AppRouterApiHandlerFn | NextApiHandler,\n options?: ProtectApiAppOptions | ProtectApiPageOptions\n ): AppRouterApiHandlerFn | NextApiHandler {\n return (\n req: NextRequest | NextApiRequest,\n resOrCtx: AppRouterContext | NextApiResponse\n ) => {\n if (isAppRouter(req)) {\n return this.protectAppApi(\n req as NextRequest,\n resOrCtx as AppRouterContext,\n handler as AppRouterApiHandlerFn,\n options as ProtectApiAppOptions\n );\n }\n return this.protectPageApi(\n req as NextApiRequest,\n resOrCtx as NextApiResponse,\n handler as NextApiHandler,\n options as ProtectApiPageOptions\n );\n };\n }\n\n private async protectAppApi(\n req: NextRequest,\n ctx: AppRouterContext,\n handler: AppRouterApiHandlerFn,\n options?: ProtectApiAppOptions\n ): Promise<NextResponse> {\n const res = new NextResponse();\n\n const session = await this.getSession(req, res);\n\n if (!session) {\n if (options?.onAccessDenied) {\n const result = await options.onAccessDenied(req, ctx);\n\n if (result instanceof NextResponse) {\n return mergeResponse([res, result]);\n }\n\n return mergeResponse([res, new NextResponse(result.body, result)]);\n }\n\n return mergeResponse([\n res,\n NextResponse.json({ message: 'unauthorized' }, { status: 401 }),\n ]);\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n const result = await options.onAccessDenied(req, ctx);\n\n if (result instanceof NextResponse) {\n return mergeResponse([res, result]);\n }\n\n return mergeResponse([res, new NextResponse(result.body, result)]);\n }\n\n return mergeResponse([\n res,\n NextResponse.json({ message: 'forbidden' }, { status: 403 }),\n ]);\n }\n\n const resp = await handler(req, ctx);\n\n if (resp instanceof NextResponse) {\n return mergeResponse([res, resp]);\n }\n\n return mergeResponse([res, new NextResponse(resp.body, resp)]);\n }\n\n private async protectPageApi(\n req: NextApiRequest,\n res: NextApiResponse,\n handler: NextApiHandler,\n options?: ProtectApiPageOptions\n ): Promise<unknown> {\n const session = await this.getSession(req, res);\n\n if (!session) {\n if (options?.onAccessDenied) {\n return options.onAccessDenied(req, res);\n }\n\n return res.status(401).json({\n message: 'unauthorized',\n });\n }\n\n if (\n options?.groups &&\n !isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n if (options.onAccessDenied) {\n return options.onAccessDenied(req, res, session.user);\n }\n\n return res.status(403).json({\n message: 'forbidden',\n });\n }\n\n return handler(req, res);\n }\n\n /**\n * A middleware/proxy that protects pages and APIs and handles authentication.\n *\n * @param options Middleware configuration options\n *\n * @returns A Next.js middleware/proxy function.\n *\n * @example Protect All Routes\n *\n * - Default behavior: protect all routes matched by `config.matcher`\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware();\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect Selected Routes\n *\n * - Protect only the routes listed in `protectedRoutes`\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: [\"/api/admin\", \"^/api/protected(/.*)?$\"],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n *```\n *\n * @example Make All Routes Public\n *\n * - Do not protect any routes; MonoCloud still handles auth endpoints\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: [],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect Routes Dynamically\n *\n * - Decide at runtime which routes to protect\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * protectedRoutes: (req) => {\n * return req.nextUrl.pathname.startsWith(\"/api/protected\");\n * },\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Protect routes based on groups\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default monoCloud.authMiddleware({\n * // group names or IDs\n * protectedRoutes: [\n * {\n * groups: [\"admin\", \"editor\", \"537e7c3d-a442-4b5b-b308-30837aa045a4\"],\n * routes: [\"/internal\", \"/api/internal(.*)\"],\n * },\n * ],\n * });\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n */\n authMiddleware(\n options?: MonoCloudMiddlewareOptions\n ): NextMiddleware | NextProxy;\n\n /**\n * A middleware that protects pages and APIs and handles authentication.\n *\n * @param request The Next.js fetch event object.\n * @param event The associated fetch event [Docs](https://nextjs.org/docs/app/api-reference/file-conventions/proxy#waituntil-and-nextfetchevent).\n *\n * @returns A promise resolving to a Next.js middleware result or a Next.js middleware result.\n *\n * @example Nest Custom Middleware\n *\n * - Use your own middleware wrapper and call MonoCloud only for specific routes\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextFetchEvent, NextRequest, NextResponse } from \"next/server\";\n *\n * export default function customMiddleware(req: NextRequest, evt: NextFetchEvent) {\n * if (req.nextUrl.pathname.startsWith(\"/api/protected\")) {\n * return monoCloud.authMiddleware(req, evt);\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n */\n authMiddleware(\n request: NextRequest,\n event: NextFetchEvent\n ): Promise<NextMiddlewareResult> | NextMiddlewareResult;\n\n public authMiddleware(\n ...args: unknown[]\n ):\n | NextMiddleware\n | NextProxy\n | Promise<NextMiddlewareResult>\n | NextMiddlewareResult {\n let req: NextRequest | undefined;\n let evt: NextFetchEvent | undefined;\n let options: MonoCloudMiddlewareOptions | undefined;\n\n /* v8 ignore else -- @preserve */\n if (Array.isArray(args)) {\n if (args.length === 2) {\n /* v8 ignore else -- @preserve */\n if (isAppRouter(args[0])) {\n req = args[0] as NextRequest;\n evt = args[1] as NextFetchEvent;\n }\n }\n\n if (args.length === 1) {\n options = args[0] as MonoCloudMiddlewareOptions;\n }\n }\n\n if (req && evt) {\n return this.authMiddlewareHandler(req, evt, options) as any;\n }\n\n return (request: NextRequest, nxtEvt: NextFetchEvent) => {\n return this.authMiddlewareHandler(request, nxtEvt, options);\n };\n }\n\n private async authMiddlewareHandler(\n req: NextRequest,\n evt: NextFetchEvent,\n options?: MonoCloudMiddlewareOptions\n ): Promise<NextMiddlewareResult> {\n // eslint-disable-next-line no-param-reassign\n req = getNextRequest(req);\n\n if (req.headers.has('x-middleware-subrequest')) {\n return NextResponse.json({ message: 'forbidden' }, { status: 403 });\n }\n\n const { routes, appUrl } = this.getOptions();\n\n if (\n Object.values(routes!)\n .map(x => ensureLeadingSlash(x))\n .includes(req.nextUrl.pathname)\n ) {\n let onError;\n if (typeof options?.onError === 'function') {\n onError = (\n error: Error\n ):\n | Promise<void | NextResponse<unknown>>\n | void\n | NextResponse<unknown> => options.onError!(req, evt, error);\n }\n\n const request = new MonoCloudAppRouterRequest(req);\n const response = new MonoCloudAppRouterResponse(new NextResponse());\n\n return this.handleAuthRoutes(\n request,\n response,\n req.nextUrl.pathname,\n routes,\n onError\n );\n }\n\n const nxtResp = new NextResponse();\n\n nxtResp.headers.set(\n 'x-monocloud-path',\n req.nextUrl.pathname + req.nextUrl.search\n );\n\n let isRouteProtected = true;\n let allowedGroups: string[] | undefined;\n\n if (typeof options?.protectedRoutes === 'function') {\n isRouteProtected = await options.protectedRoutes(req);\n } else if (\n typeof options?.protectedRoutes !== 'undefined' &&\n Array.isArray(options.protectedRoutes)\n ) {\n isRouteProtected = options.protectedRoutes.some(route => {\n if (typeof route === 'string' || route instanceof RegExp) {\n return new RegExp(route).test(req.nextUrl.pathname);\n }\n\n return route.routes.some(groupRoute => {\n const result = new RegExp(groupRoute).test(req.nextUrl.pathname);\n\n if (result) {\n allowedGroups = route.groups;\n }\n\n return result;\n });\n });\n }\n\n if (!isRouteProtected) {\n return NextResponse.next({\n headers: {\n 'x-monocloud-path': req.nextUrl.pathname + req.nextUrl.search,\n },\n });\n }\n\n const session = await this.getSession(req, nxtResp);\n\n if (!session) {\n if (options?.onAccessDenied) {\n const result = await options.onAccessDenied(req, evt);\n\n if (result instanceof NextResponse) {\n return mergeResponse([nxtResp, result]);\n }\n\n if (result) {\n return mergeResponse([\n nxtResp,\n new NextResponse(result.body, result),\n ]);\n }\n\n return NextResponse.next(nxtResp);\n }\n\n if (req.nextUrl.pathname.startsWith('/api')) {\n return mergeResponse([\n nxtResp,\n NextResponse.json({ message: 'unauthorized' }, { status: 401 }),\n ]);\n }\n\n const signInRoute = new URL(\n `${appUrl}${ensureLeadingSlash(routes!.signIn)}`\n );\n\n signInRoute.searchParams.set(\n 'return_url',\n req.nextUrl.pathname + req.nextUrl.search\n );\n\n return mergeResponse([nxtResp, NextResponse.redirect(signInRoute)]);\n }\n\n const groupsClaim =\n options?.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM;\n\n const onAccessDenied = options?.onAccessDenied;\n\n if (\n allowedGroups &&\n !isUserInGroup(session.user, allowedGroups, groupsClaim)\n ) {\n if (onAccessDenied) {\n const result = await onAccessDenied(req, evt, session.user);\n\n if (result instanceof NextResponse) {\n return mergeResponse([nxtResp, result]);\n }\n\n if (result) {\n return mergeResponse([\n nxtResp,\n new NextResponse(result.body, result),\n ]);\n }\n\n return NextResponse.next(nxtResp);\n }\n\n if (req.nextUrl.pathname.startsWith('/api')) {\n return mergeResponse([\n nxtResp,\n NextResponse.json({ message: 'forbidden' }, { status: 403 }),\n ]);\n }\n\n return new NextResponse(`forbidden`, {\n status: 403,\n });\n }\n\n return NextResponse.next(nxtResp);\n }\n\n private handleAuthRoutes(\n request: MonoCloudRequest,\n response: MonoCloudResponse,\n path: string,\n routes: MonoCloudOptions['routes'],\n onError?: OnError\n ): Promise<any> {\n switch (path) {\n case ensureLeadingSlash(routes!.signIn):\n return this.coreClient.signIn(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.callback):\n return this.coreClient.callback(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.userInfo):\n return this.coreClient.userInfo(request, response, {\n onError,\n });\n\n case ensureLeadingSlash(routes!.signOut):\n return this.coreClient.signOut(request, response, {\n onError,\n });\n\n default:\n response.notFound();\n return response.done();\n }\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * return NextResponse.json({ name: session?.user.name });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const session = await monoCloud.getSession();\n *\n * return <div>{session?.user.name}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getUserAction() {\n * const session = await monoCloud.getSession();\n *\n * return { name: session?.user.name };\n * }\n * ```\n *\n */\n public getSession(): Promise<MonoCloudSession | undefined>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response; otherwise, omit this parameter.\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const session = await monoCloud.getSession(req);\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Middleware/Proxy (Custom Response)\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const session = await monoCloud.getSession(req, res);\n *\n * if (!session) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * res.headers.set(\"x-auth-status\", \"active\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const session = await monoCloud.getSession(req);\n *\n * return NextResponse.json({ name: session?.user.name });\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"YOUR CUSTOM RESPONSE\");\n *\n * const session = await monoCloud.getSession(req, res);\n *\n * if (session?.user) {\n * res.cookies.set(\"something\", \"important\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public getSession(\n req: NextRequest | Request,\n res?: NextResponse | Response\n ): Promise<MonoCloudSession | undefined>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Retrieves the session object for the currently authenticated user on the server.\n *\n * *Note: If the session cannot be resolved or an underlying error occurs, the promise rejects with an error.*\n *\n * @param req NextApiRequest\n * @param res NextApiResponse\n *\n * @returns `MonoCloudSession` if found, or `undefined`.\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * type Data = {\n * name?: string;\n * };\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse<Data>\n * ) {\n * const session = await monoCloud.getSession(req, res);\n *\n * res.status(200).json({ name: session?.user.name });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ session }: HomeProps) {\n * return <pre>Session: {JSON.stringify(session, null, 2)}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const session = await monoCloud.getSession(context.req, context.res);\n *\n * return {\n * props: {\n * session: session ?? null,\n * },\n * };\n * };\n * ```\n */\n public getSession(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>\n ): Promise<MonoCloudSession | undefined>;\n\n async getSession(...args: any[]): Promise<MonoCloudSession | undefined> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n /* v8 ignore next -- @preserve */\n if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to getSession()'\n );\n }\n\n return await this.coreClient.getSession(request, response);\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const tokens = await monoCloud.getTokens();\n *\n * if (tokens.isExpired) {\n * return new NextResponse(\"Tokens expired\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens();\n *\n * return NextResponse.json({ expired: tokens.isExpired });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const tokens = await monoCloud.getTokens();\n *\n * return <div>Expired: {tokens.isExpired.toString()}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getExpiredAction() {\n * const tokens = await monoCloud.getTokens();\n *\n * return { expired: tokens.isExpired };\n * }\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens({ forceRefresh: true });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens({\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const tokens = await monoCloud.getTokens({\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n */\n public getTokens(options?: GetTokensOptions): Promise<MonoCloudTokens>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const tokens = await monoCloud.getTokens(req);\n *\n * if (tokens.isExpired) {\n * return new NextResponse(\"Tokens expired\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req);\n *\n * return NextResponse.json({ expired: tokens?.isExpired });\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, { forceRefresh: true });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const tokens = await monoCloud.getTokens(req, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * return NextResponse.json({ accessToken: tokens?.accessToken });\n * };\n * ```\n */\n public getTokens(\n req: NextRequest | Request,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n /**\n * ## Middleware/Proxy or Route Handlers (Custom Response)\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens and updates the provided response object.\n *\n * **Use Case:**\n * - Middleware (when modifying the response).\n * - App Router Route Handlers (when a NextResponse is already initialized).\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response and want token updates (e.g., refreshing) to be applied to it.\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example Middleware/Proxy\n *\n *```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * res.headers.set(\"x-tokens-expired\", tokens.isExpired.toString());\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, res, { forceRefresh: true });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Custom Body\");\n *\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * if (!tokens.isExpired) {\n * res.headers.set(\"x-auth-status\", \"active\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public getTokens(\n req: NextRequest | Request,\n res: NextResponse | Response,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Retrieves the tokens for the currently signed-in user. Optionally refreshes/fetches new tokens.\n *\n * @param req The `NextApiRequest` or `IncomingMessage`.\n * @param res The `NextApiResponse` or `ServerResponse`.\n * @param options Configuration options for token retrieval.\n *\n * @returns\n *\n * @throws {@link MonoCloudValidationError} If session is not found\n *\n * @example API Route\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res);\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ tokens }: HomeProps) {\n * return <pre>Tokens: {JSON.stringify(tokens, null, 2)}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const tokens = await monoCloud.getTokens(context.req, context.res);\n *\n * return {\n * props: {\n * tokens: tokens ?? null,\n * },\n * };\n * };\n * ```\n *\n * @example Refresh Default Token\n *\n * The default token is an access token with scopes set through `MONOCLOUD_AUTH_SCOPES` or\n * `options.defaultAuthParams.scopes`, and resources set through `MONOCLOUD_AUTH_RESOURCE` or\n * `options.defaultAuthParams.resource`. This token is refreshed when calling getTokens without parameters.\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * // Although the token refreshes automatically upon expiration, we are manually refreshing it here.\n * const tokens = await monoCloud.getTokens(req, res, { forceRefresh: true });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example Request new access token for resource(s)\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * The following example shows how to request a new token scoped to two non-exclusive resources.\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://first.example.com https://second.example.com\",\n * scopes: \"read:first read:second shared\",\n * });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n *\n * @example Request an exclusive token\n *\n * **Note: Ensure that the resources and scopes are included in the initial authorization flow**\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const tokens = await monoCloud.getTokens(req, res, {\n * resource: \"https://exclusive.example.com\",\n * scopes: \"read:exclusive shared\",\n * });\n *\n * res.status(200).json({ accessToken: tokens?.accessToken });\n * }\n * ```\n */\n public getTokens(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>,\n options?: GetTokensOptions\n ): Promise<MonoCloudTokens>;\n\n async getTokens(...args: any[]): Promise<MonoCloudTokens> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n let options: GetTokensOptions | undefined;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else if (args.length === 1) {\n if (args[0] instanceof Request) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n } else {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n options = args[0];\n }\n } else if (args.length === 2 && args[0] instanceof Request) {\n if (args[1] instanceof Response) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n\n options = args[1] as GetTokensOptions;\n }\n } else if (\n args.length === 2 &&\n args[0] instanceof IncomingMessage &&\n args[1] instanceof ServerResponse\n ) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n\n options = args[2] as GetTokensOptions;\n }\n\n if (\n !isMonoCloudRequest(request) ||\n !isMonoCloudResponse(response) ||\n (options && typeof options !== 'object')\n ) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to getTokens()'\n );\n }\n\n return await this.coreClient.getTokens(request, response, options);\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Checks if the current user is authenticated.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return NextResponse.json({ authenticated });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return <div>Authenticated: {authenticated.toString()}</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function checkAuthAction() {\n * const authenticated = await monoCloud.isAuthenticated();\n *\n * return { authenticated };\n * }\n * ```\n */\n public isAuthenticated(): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Checks if the current user is authenticated.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response; otherwise, omit this parameter.\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const authenticated = await monoCloud.isAuthenticated(req);\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example Middleware/Proxy (Custom Response)\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * if (!authenticated) {\n * return new NextResponse(\"User not signed in\", { status: 401 });\n * }\n *\n * res.headers.set(\"x-authenticated\", \"true\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const authenticated = await monoCloud.isAuthenticated(req);\n *\n * return NextResponse.json({ authenticated });\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"YOUR CUSTOM RESPONSE\");\n *\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * if (authenticated) {\n * res.cookies.set(\"something\", \"important\");\n * }\n *\n * return res;\n * };\n * ```\n */\n public isAuthenticated(\n req: NextRequest | Request,\n res?: NextResponse | Response\n ): Promise<boolean>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Checks if the current user is authenticated.\n *\n * @param req NextApiRequest\n * @param res NextApiResponse\n *\n * @returns `true` if the user is authenticated, otherwise `false`.\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * type Data = {\n * authenticated: boolean;\n * };\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse<Data>\n * ) {\n * const authenticated = await monoCloud.isAuthenticated(req, res);\n *\n * res.status(200).json({ authenticated });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ authenticated }: HomeProps) {\n * return <pre>User is {authenticated ? \"logged in\" : \"guest\"}</pre>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const authenticated = await monoCloud.isAuthenticated(\n * context.req,\n * context.res\n * );\n *\n * return {\n * props: {\n * authenticated,\n * },\n * };\n * };\n * ```\n */\n public isAuthenticated(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>\n ): Promise<boolean>;\n\n async isAuthenticated(...args: any[]): Promise<boolean> {\n let request: IMonoCloudCookieRequest;\n let response: IMonoCloudCookieResponse;\n\n if (args.length === 0) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n /* v8 ignore next -- @preserve */\n if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to isAuthenticated()'\n );\n }\n\n return await this.coreClient.isAuthenticated(request, response);\n }\n\n /**\n * Redirects the user to the sign-in flow if they are not authenticated.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign-in.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * await monoCloud.protect();\n *\n * return <>You are signed in.</>;\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * await monoCloud.protect();\n *\n * return NextResponse.json({ secret: \"ssshhhh!!!\" });\n * };\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function getMessage() {\n * await monoCloud.protect();\n *\n * return { secret: \"sssshhhhh!!!\" };\n * }\n * ```\n */\n public async protect(options?: ProtectOptions): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n let path: string;\n try {\n const session = await this.getSession();\n\n if (session && !options?.groups) {\n return;\n }\n\n if (\n session &&\n options &&\n options.groups &&\n isUserInGroup(\n session.user,\n options.groups,\n options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options.matchAll\n )\n ) {\n return;\n }\n\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n path = (await headers()).get('x-monocloud-path') ?? '/';\n } catch {\n throw new Error(\n 'protect() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signInRoute = new URL(`${appUrl}${routes.signIn}`);\n\n signInRoute.searchParams.set('return_url', options?.returnUrl ?? path);\n\n if (options?.authParams?.maxAge) {\n signInRoute.searchParams.set(\n 'max_age',\n options.authParams.maxAge.toString()\n );\n }\n\n if (options?.authParams?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authParams.authenticatorHint\n );\n }\n\n if (options?.authParams?.scopes) {\n signInRoute.searchParams.set('scope', options.authParams.scopes);\n }\n\n if (options?.authParams?.resource) {\n signInRoute.searchParams.set('resource', options.authParams.resource);\n }\n\n if (options?.authParams?.display) {\n signInRoute.searchParams.set('display', options.authParams.display);\n }\n\n if (options?.authParams?.uiLocales) {\n signInRoute.searchParams.set('ui_locales', options.authParams.uiLocales);\n }\n\n if (Array.isArray(options?.authParams?.acrValues)) {\n signInRoute.searchParams.set(\n 'acr_values',\n options.authParams.acrValues.join(' ')\n );\n }\n\n if (options?.authParams?.loginHint) {\n signInRoute.searchParams.set('login_hint', options.authParams.loginHint);\n }\n\n if (options?.authParams?.prompt) {\n signInRoute.searchParams.set('prompt', options.authParams.prompt);\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signInRoute.toString());\n }\n\n /**\n * ## SSR Components, Actions, Middleware or API Handlers\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - App Router Server Components (RSC).\n * - Server Actions\n * - Route Handlers (App Router only).\n * - Middleware (App Router and Pages Router).\n *\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export default async function middleware() {\n * const isAdmin = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const allowed = await monoCloud.isUserInGroup([\"admin\", \"editor\"]);\n *\n * if (!allowed) {\n * return new NextResponse(\"Forbidden\", { status: 403 });\n * }\n *\n * return NextResponse.json({ status: \"success\" });\n * };\n * ```\n *\n * @example React Server Components\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function AdminPanel() {\n * const isAdmin = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!isAdmin) {\n * return <div>Access Denied</div>;\n * }\n *\n * return <div>Admin Control Panel</div>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function deletePostAction() {\n * const canDelete = await monoCloud.isUserInGroup([\"admin\", \"editor\"]);\n *\n * if (!canDelete) {\n * return { success: false };\n * }\n *\n * return { success: true };\n * }\n * ```\n */\n isUserInGroup(\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - Middleware (for both App and Pages Router).\n * - App Router Route Handlers (API routes).\n * - Edge functions.\n *\n * @param req NextRequest\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const isAdmin = await monoCloud.isUserInGroup(req, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * return NextResponse.next();\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example App Router API Handler\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const isMember = await monoCloud.isUserInGroup(req, [\"admin\", \"editor\"]);\n *\n * return NextResponse.json({ isMember });\n * };\n * ```\n */\n isUserInGroup(\n req: NextRequest | Request,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Middleware/Proxy or Route Handlers (Custom Response)\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * **Use Case:**\n * - Middleware (when modifying the response).\n * - App Router Route Handlers (when a NextResponse is already initialized).\n *\n * @param req NextRequest\n * @param res An optional `NextResponse` instance. Pass this if you have already initialized a response and want token updates to be applied to it.\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example Middleware/Proxy\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextRequest, NextResponse } from \"next/server\";\n *\n * export default async function middleware(req: NextRequest) {\n * const res = NextResponse.next();\n *\n * const isAdmin = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return new NextResponse(\"User is not admin\", { status: 403 });\n * }\n *\n * res.headers.set(\"x-user\", \"admin\");\n *\n * return res;\n * }\n *\n * export const config = {\n * matcher: [\n * \"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)\",\n * ],\n * };\n * ```\n *\n * @example API Handler with NextResponse\n *\n * ```typescript\n * import { NextRequest, NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async (req: NextRequest) => {\n * const res = new NextResponse(\"Restricted Content\");\n *\n * const allowed = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!allowed) {\n * return new NextResponse(\"Not Allowed\", res);\n * }\n *\n * return res;\n * };\n * ```\n */\n isUserInGroup(\n req: NextRequest | Request,\n res: NextResponse | Response,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n /**\n * ## Pages Router (Node.js Runtime)\n *\n * Checks if the currently authenticated user is a member of any of the specified groups.\n *\n * @param req The `NextApiRequest` or `IncomingMessage`.\n * @param res The `NextApiResponse` or `ServerResponse`.\n * @param groups A list of group names or IDs to check against the user's group memberships.\n * @param options Configuration options.\n *\n * @returns\n *\n * @example API Route\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { NextApiRequest, NextApiResponse } from \"next\";\n *\n * export default async function handler(\n * req: NextApiRequest,\n * res: NextApiResponse\n * ) {\n * const isAdmin = await monoCloud.isUserInGroup(req, res, [\"admin\"]);\n *\n * if (!isAdmin) {\n * return res.status(403).json({ error: \"Forbidden\" });\n * }\n *\n * res.status(200).json({ message: \"Welcome Admin\" });\n * }\n * ```\n *\n * @example SSR Component\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import type { GetServerSideProps, InferGetServerSidePropsType } from \"next\";\n *\n * type HomeProps = InferGetServerSidePropsType<typeof getServerSideProps>;\n *\n * export default function Home({ isAdmin }: HomeProps) {\n * return <div>User is admin: {isAdmin.toString()}</div>;\n * }\n *\n * export const getServerSideProps: GetServerSideProps = async (context) => {\n * const isAdmin = await monoCloud.isUserInGroup(context.req, context.res, [\n * \"admin\",\n * ]);\n *\n * return {\n * props: {\n * isAdmin,\n * },\n * };\n * };\n * ```\n */\n isUserInGroup(\n req: NextApiRequest | IncomingMessage,\n res: NextApiResponse | ServerResponse<IncomingMessage>,\n groups: string[],\n options?: IsUserInGroupOptions\n ): Promise<boolean>;\n\n public async isUserInGroup(...args: any[]): Promise<boolean> {\n let request: IMonoCloudCookieRequest | undefined;\n let response: IMonoCloudCookieResponse | undefined;\n let groups: string[] | undefined;\n let options: IsUserInGroupOptions | undefined;\n\n if (args.length === 4) {\n groups = args[2];\n options = args[3];\n\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n }\n\n if (args.length === 3) {\n if (args[0] instanceof Request) {\n if (args[1] instanceof Response) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n groups = args[2];\n } else {\n ({ request, response } = getMonoCloudCookieReqRes(\n args[0],\n undefined\n ));\n groups = args[1];\n options = args[2];\n }\n }\n\n if (\n args[0] instanceof IncomingMessage &&\n args[1] instanceof ServerResponse\n ) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], args[1]));\n groups = args[2];\n }\n }\n\n if (args.length === 2) {\n if (args[0] instanceof Request) {\n ({ request, response } = getMonoCloudCookieReqRes(args[0], undefined));\n groups = args[1];\n }\n\n if (Array.isArray(args[0])) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n\n groups = args[0];\n options = args[1];\n }\n }\n\n if (args.length === 1) {\n request = new MonoCloudCookieRequest();\n response = new MonoCloudCookieResponse();\n\n groups = args[0];\n }\n\n if (\n !Array.isArray(groups) ||\n !isMonoCloudRequest(request) ||\n !isMonoCloudResponse(response) ||\n (options && typeof options !== 'object')\n ) {\n throw new MonoCloudValidationError(\n 'Invalid parameters passed to isUserInGroup()'\n );\n }\n\n const result = await this.coreClient.isUserInGroup(\n request,\n response,\n groups,\n options?.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM,\n options?.matchAll\n );\n\n return result;\n }\n\n /**\n * Redirects the user to the sign-in flow.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign-in.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Home() {\n * const allowed = await monoCloud.isUserInGroup([\"admin\"]);\n *\n * if (!allowed) {\n * await monoCloud.redirectToSignIn({ returnUrl: \"/home\" });\n * }\n *\n * return <>You are signed in.</>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function protectedAction() {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * await monoCloud.redirectToSignIn();\n * }\n *\n * return { data: \"Sensitive Data\" };\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { NextResponse } from \"next/server\";\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * if (!session) {\n * await monoCloud.redirectToSignIn({\n * returnUrl: \"/dashboard\",\n * });\n * }\n *\n * return NextResponse.json({ data: \"Protected content\" });\n * };\n * ```\n */\n public async redirectToSignIn(\n options?: RedirectToSignInOptions\n ): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n await headers();\n } catch {\n throw new Error(\n 'redirectToSignIn() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signInRoute = new URL(`${appUrl}${routes.signIn}`);\n\n if (options?.returnUrl) {\n signInRoute.searchParams.set('return_url', options.returnUrl);\n }\n\n if (options?.maxAge) {\n signInRoute.searchParams.set('max_age', options.maxAge.toString());\n }\n\n if (options?.authenticatorHint) {\n signInRoute.searchParams.set(\n 'authenticator_hint',\n options.authenticatorHint\n );\n }\n\n if (Array.isArray(options?.scopes)) {\n signInRoute.searchParams.set('scope', options.scopes.join(' '));\n }\n\n if (Array.isArray(options?.resource)) {\n signInRoute.searchParams.set('resource', options.resource.join(' '));\n }\n\n if (options?.display) {\n signInRoute.searchParams.set('display', options.display);\n }\n\n if (options?.uiLocales) {\n signInRoute.searchParams.set('ui_locales', options.uiLocales);\n }\n\n if (Array.isArray(options?.acrValues)) {\n signInRoute.searchParams.set('acr_values', options.acrValues.join(' '));\n }\n\n if (options?.loginHint) {\n signInRoute.searchParams.set('login_hint', options.loginHint);\n }\n\n if (options?.prompt) {\n signInRoute.searchParams.set('prompt', options.prompt);\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signInRoute.toString());\n }\n\n /**\n * Redirects the user to the sign-out flow.\n *\n * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**\n *\n * @param options Options to customize the sign out.\n *\n * @returns\n *\n * @example React Server Component\n *\n * ```tsx\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export default async function Page() {\n * const session = await monoCloud.getSession();\n *\n * // Example: Force sign-out if a specific condition is met (e.g., account suspended)\n * if (session?.user.isSuspended) {\n * await monoCloud.redirectToSignOut();\n * }\n *\n * return <>Welcome User</>;\n * }\n * ```\n *\n * @example Server Action\n *\n * ```typescript\n * \"use server\";\n *\n * import { monoCloud } from \"@/lib/monocloud\";\n *\n * export async function signOutAction() {\n * const session = await monoCloud.getSession();\n *\n * if (session) {\n * await monoCloud.redirectToSignOut();\n * }\n * }\n * ```\n *\n * @example API Handler\n *\n * ```typescript\n * import { monoCloud } from \"@/lib/monocloud\";\n * import { NextResponse } from \"next/server\";\n *\n * export const GET = async () => {\n * const session = await monoCloud.getSession();\n *\n * if (session) {\n * await monoCloud.redirectToSignOut({\n * postLogoutRedirectUri: \"/goodbye\",\n * });\n * }\n *\n * return NextResponse.json({ status: \"already_signed_out\" });\n * };\n * ```\n */\n public async redirectToSignOut(\n options?: RedirectToSignOutOptions\n ): Promise<void> {\n const { routes, appUrl } = this.coreClient.getOptions();\n\n try {\n // @ts-expect-error Cannot find module 'next/headers'\n const { headers } = await import('next/headers');\n\n await headers();\n } catch {\n throw new Error(\n 'redirectToSignOut() can only be used in App Router server environments (RSC, route handlers, or server actions)'\n );\n }\n\n const signOutRoute = new URL(`${appUrl}${routes.signOut}`);\n\n if (options?.postLogoutRedirectUri?.trim().length) {\n signOutRoute.searchParams.set(\n 'post_logout_url',\n options.postLogoutRedirectUri\n );\n }\n\n if (typeof options?.federated === 'boolean') {\n signOutRoute.searchParams.set('federated', options.federated.toString());\n }\n\n // @ts-expect-error Cannot find module 'next/navigation'\n const { redirect } = await import('next/navigation');\n\n redirect(signOutRoute.toString());\n }\n\n private getOptions(): MonoCloudOptions {\n return this.coreClient.getOptions();\n }\n\n private registerPublicEnvVariables(): void {\n Object.keys(process.env)\n .filter(key => key.startsWith('NEXT_PUBLIC_MONOCLOUD_AUTH'))\n .forEach(publicKey => {\n const [, privateKey] = publicKey.split('NEXT_PUBLIC_');\n process.env[privateKey] = process.env[publicKey];\n });\n }\n}\n"],"mappings":"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"}