@monocloud/auth-nextjs 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,20 +1,14 @@
1
1
  import { MonoCloudAuthBaseError, MonoCloudCoreClient, MonoCloudHttpError, MonoCloudOPError, MonoCloudTokenError, MonoCloudValidationError, MonoCloudValidationError as MonoCloudValidationError$1 } from "@monocloud/auth-node-core";
2
- import { NextResponse } from "next/server";
3
- import { redirect } from "next/navigation";
2
+ import { NextRequest, NextResponse } from "next/server.js";
4
3
  import { ensureLeadingSlash, isAbsoluteUrl } from "@monocloud/auth-node-core/internal";
5
4
  import { isUserInGroup } from "@monocloud/auth-node-core/utils";
6
5
  import { serialize } from "cookie";
6
+ import { IncomingMessage, ServerResponse } from "node:http";
7
7
 
8
8
  //#region src/requests/monocloud-app-router-request.ts
9
9
  var MonoCloudAppRouterRequest = class {
10
- constructor(req, ctx) {
10
+ constructor(req) {
11
11
  this.req = req;
12
- this.ctx = ctx;
13
- }
14
- /* v8 ignore next */
15
- getRoute(parameter) {
16
- var _this$ctx$params;
17
- return (_this$ctx$params = this.ctx.params) === null || _this$ctx$params === void 0 ? void 0 : _this$ctx$params[parameter];
18
12
  }
19
13
  getQuery(parameter) {
20
14
  return new URL(this.req.url).searchParams.get(parameter) ?? void 0;
@@ -46,10 +40,6 @@ var MonoCloudPageRouterRequest = class {
46
40
  this.req = req;
47
41
  }
48
42
  /* v8 ignore next */
49
- getRoute(parameter) {
50
- return this.req.query[parameter];
51
- }
52
- /* v8 ignore next */
53
43
  getQuery(parameter) {
54
44
  return this.req.query[parameter];
55
45
  }
@@ -188,17 +178,64 @@ var MonoCloudPageRouterResponse = class {
188
178
  }
189
179
  };
190
180
 
181
+ //#endregion
182
+ //#region src/responses/monocloud-cookie-response.ts
183
+ let isWarned = false;
184
+ var MonoCloudCookieResponse = class {
185
+ async setCookie(cookieName, value, options) {
186
+ try {
187
+ const { cookies } = await import("next/headers");
188
+ (await cookies()).set(cookieName, value, options);
189
+ } catch (e) {
190
+ if (!isWarned) {
191
+ console.warn(e.message);
192
+ isWarned = true;
193
+ }
194
+ }
195
+ }
196
+ };
197
+
198
+ //#endregion
199
+ //#region src/requests/monocloud-cookie-request.ts
200
+ var MonoCloudCookieRequest = class {
201
+ /* v8 ignore next */
202
+ async getCookie(name) {
203
+ var _await$cookies$get;
204
+ const { cookies } = await import("next/headers");
205
+ return (_await$cookies$get = (await cookies()).get(name)) === null || _await$cookies$get === void 0 ? void 0 : _await$cookies$get.value;
206
+ }
207
+ async getAllCookies() {
208
+ const values = /* @__PURE__ */ new Map();
209
+ const { cookies } = await import("next/headers");
210
+ (await cookies()).getAll().forEach((x) => {
211
+ values.set(x.name, x.value);
212
+ });
213
+ return values;
214
+ }
215
+ };
216
+
191
217
  //#endregion
192
218
  //#region src/utils.ts
219
+ const isMonoCloudRequest = (req) => req instanceof MonoCloudAppRouterRequest || req instanceof MonoCloudPageRouterRequest || req instanceof MonoCloudCookieRequest;
220
+ const isMonoCloudResponse = (res) => res instanceof MonoCloudAppRouterResponse || res instanceof MonoCloudPageRouterResponse || res instanceof MonoCloudCookieResponse;
193
221
  const isAppRouter = (req) => req instanceof Request || req.headers instanceof Headers || typeof req.bodyUsed === "boolean";
194
- const getMonoCloudReqRes = (req, resOrCtx) => {
222
+ const getNextRequest = (req) => {
223
+ if (req instanceof NextRequest) return req;
224
+ return new NextRequest(req);
225
+ };
226
+ const getNextResponse = (res) => {
227
+ if (res instanceof NextResponse) return res;
228
+ if (res instanceof Response) return new NextResponse(res.body, res);
229
+ return new NextResponse();
230
+ };
231
+ const getMonoCloudCookieReqRes = (req, resOrCtx) => {
195
232
  let request;
196
233
  let response;
197
234
  if (isAppRouter(req)) {
198
- request = new MonoCloudAppRouterRequest(req, resOrCtx instanceof NextResponse ? { params: {} } : resOrCtx);
199
- response = new MonoCloudAppRouterResponse(resOrCtx instanceof NextResponse ? resOrCtx : new NextResponse());
235
+ request = new MonoCloudAppRouterRequest(getNextRequest(req));
236
+ response = resOrCtx instanceof Response ? new MonoCloudAppRouterResponse(getNextResponse(resOrCtx)) : new MonoCloudCookieResponse();
200
237
  } else {
201
- /* c8 ignore start */
238
+ if (!(req instanceof IncomingMessage) || !(resOrCtx instanceof ServerResponse)) throw new MonoCloudValidationError$1("Invalid pages router request and response");
202
239
  request = new MonoCloudPageRouterRequest(req);
203
240
  response = new MonoCloudPageRouterResponse(resOrCtx);
204
241
  }
@@ -222,214 +259,189 @@ const mergeResponse = (responses) => {
222
259
  return resp;
223
260
  };
224
261
 
225
- //#endregion
226
- //#region src/requests/monocloud-cookie-request.ts
227
- var MonoCloudCookieRequest = class {
228
- /* v8 ignore next */
229
- async getCookie(name) {
230
- var _await$cookies$get;
231
- const { cookies } = await import("next/headers");
232
- return (_await$cookies$get = (await cookies()).get(name)) === null || _await$cookies$get === void 0 ? void 0 : _await$cookies$get.value;
233
- }
234
- async getAllCookies() {
235
- const values = /* @__PURE__ */ new Map();
236
- const { cookies } = await import("next/headers");
237
- (await cookies()).getAll().forEach((x) => {
238
- values.set(x.name, x.value);
239
- });
240
- return values;
241
- }
242
- };
243
-
244
- //#endregion
245
- //#region src/responses/monocloud-cookie-response.ts
246
- let isWarned = false;
247
- var MonoCloudCookieResponse = class {
248
- async setCookie(cookieName, value, options) {
249
- try {
250
- const { cookies } = await import("next/headers");
251
- (await cookies()).set(cookieName, value, options);
252
- } catch (e) {
253
- if (!isWarned) {
254
- console.warn(e.message);
255
- isWarned = true;
256
- }
257
- }
258
- }
259
- };
260
-
261
262
  //#endregion
262
263
  //#region src/monocloud-next-client.ts
264
+ /**
265
+ * The MonoCloud Next.js Client.
266
+ *
267
+ * @example Using Environment Variables (Recommended)
268
+ *
269
+ * 1. Add following variables to your `.env`.
270
+ *
271
+ * ```bash
272
+ * MONOCLOUD_AUTH_TENANT_DOMAIN=<tenant-domain>
273
+ * MONOCLOUD_AUTH_CLIENT_ID=<client-id>
274
+ * MONOCLOUD_AUTH_CLIENT_SECRET=<client-secret>
275
+ * MONOCLOUD_AUTH_SCOPES=openid profile email # Default
276
+ * MONOCLOUD_AUTH_APP_URL=http://localhost:3000
277
+ * MONOCLOUD_AUTH_COOKIE_SECRET=<cookie-secret>
278
+ * ```
279
+ *
280
+ * 2. Instantiate the client in a shared file (e.g., lib/monocloud.ts)
281
+ *
282
+ * ```typescript
283
+ * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';
284
+ *
285
+ * export const monoCloud = new MonoCloudNextClient();
286
+ * ```
287
+ *
288
+ * 3. Add MonoCloud middleware/proxy
289
+ *
290
+ * ```typescript
291
+ * import { monoCloud } from "@/lib/monocloud";
292
+ *
293
+ * export default monoCloud.authMiddleware();
294
+ *
295
+ * export const config = {
296
+ * matcher: [
297
+ * "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
298
+ * ],
299
+ * };
300
+ * ```
301
+ *
302
+ * @example Using Constructor Options
303
+ *
304
+ * ⚠️ Security Note: Never commit your credentials to version control. Load them from environment variables.
305
+ *
306
+ * 1. Instantiate the client in a shared file (e.g., lib/monocloud.ts)
307
+ *
308
+ * ```typescript
309
+ * import { MonoCloudNextClient } from '@monocloud/auth-nextjs';
310
+ *
311
+ * export const monoCloud = new MonoCloudNextClient({
312
+ * tenantDomain: '<tenant-domain>',
313
+ * clientId: '<client-id>',
314
+ * clientSecret: '<client-secret>',
315
+ * scopes: 'openid profile email', // Default
316
+ * appUrl: 'http://localhost:3000',
317
+ * cookieSecret: '<cookie-secret>'
318
+ * });
319
+ * ```
320
+ * 2. Add MonoCloud middleware/proxy
321
+ *
322
+ * ```typescript
323
+ * import { monoCloud } from "@/lib/monocloud";
324
+ *
325
+ * export default monoCloud.authMiddleware();
326
+ *
327
+ * export const config = {
328
+ * matcher: [
329
+ * "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
330
+ * ],
331
+ * };
332
+ * ```
333
+ *
334
+ * <details>
335
+ * <summary>All Environment Variables</summary>
336
+ * <h4>Core Configuration (Required)</h4>
337
+ *
338
+ * <ul>
339
+ * <li><strong>MONOCLOUD_AUTH_CLIENT_ID : </strong>Unique identifier for your application/client.</li>
340
+ * <li><strong>MONOCLOUD_AUTH_CLIENT_SECRET : </strong>Application/client secret.</li>
341
+ * <li><strong>MONOCLOUD_AUTH_TENANT_DOMAIN : </strong>The domain of your MonoCloud tenant (e.g., https://your-tenant.us.monocloud.com).</li>
342
+ * <li><strong>MONOCLOUD_AUTH_APP_URL : </strong>The base URL where your application is hosted.</li>
343
+ * <li><strong>MONOCLOUD_AUTH_COOKIE_SECRET : </strong>A long, random string used to encrypt and sign session cookies.</li>
344
+ * </ul>
345
+ *
346
+ * <h4>Authentication &amp; Security</h4>
347
+ *
348
+ * <ul>
349
+ * <li><strong>MONOCLOUD_AUTH_SCOPES : </strong>A space-separated list of OIDC scopes to request (e.g., openid profile email).</li>
350
+ * <li><strong>MONOCLOUD_AUTH_RESOURCE : </strong>The default resource/audience identifier for access tokens.</li>
351
+ * <li><strong>MONOCLOUD_AUTH_USE_PAR : </strong>Enables Pushed Authorization Requests.</li>
352
+ * <li><strong>MONOCLOUD_AUTH_CLOCK_SKEW : </strong>The allowed clock drift in seconds when validating token timestamps.</li>
353
+ * <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>
354
+ * <li><strong>MONOCLOUD_AUTH_RESPONSE_TIMEOUT : </strong>The maximum time in milliseconds to wait for a response.</li>
355
+ * <li><strong>MONOCLOUD_AUTH_ALLOW_QUERY_PARAM_OVERRIDES : </strong>Allows dynamic overrides of auth parameters via URL query strings.</li>
356
+ * <li><strong>MONOCLOUD_AUTH_POST_LOGOUT_REDIRECT_URI : </strong>The URL users are sent to after a successful logout.</li>
357
+ * <li><strong>MONOCLOUD_AUTH_USER_INFO : </strong>Determines if user profile data from the UserInfo endpoint should be fetched after authorization code exchange.</li>
358
+ * <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>
359
+ * <li><strong>MONOCLOUD_AUTH_ID_TOKEN_SIGNING_ALG : </strong>The expected algorithm for signing ID tokens (e.g., RS256).</li>
360
+ * <li><strong>MONOCLOUD_AUTH_FILTERED_ID_TOKEN_CLAIMS : </strong>A space-separated list of claims to exclude from the session object.</li>
361
+ * </ul>
362
+ *
363
+ * <h4>Routes</h4>
364
+ *
365
+ * <aside>
366
+ * <strong>⚠️ Important: Modifying Default Routes</strong>
367
+ * <p>If you choose to customize any of the default route paths, you must adhere to the following requirements:</p>
368
+ * <ul>
369
+ * <li>
370
+ * <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.
371
+ * </li>
372
+ * <li>
373
+ * <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.
374
+ * </li>
375
+ * </ul>
376
+ * <p><em>Example:</em></p>
377
+ * <code>
378
+ * MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback<br />
379
+ * NEXT_PUBLIC_MONOCLOUD_AUTH_CALLBACK_URL=/api/custom_callback
380
+ * </code>
381
+ * <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>
382
+ * </aside>
383
+ *
384
+ * <ul>
385
+ * <li><strong>MONOCLOUD_AUTH_CALLBACK_URL : </strong>The application path where MonoCloud sends the user after authentication.</li>
386
+ * <li><strong>MONOCLOUD_AUTH_SIGNIN_URL : </strong>The internal route path to trigger the sign-in.</li>
387
+ * <li><strong>MONOCLOUD_AUTH_SIGNOUT_URL : </strong>The internal route path to trigger the sign-out.</li>
388
+ * <li><strong>MONOCLOUD_AUTH_USER_INFO_URL : </strong>The route that exposes the current user's profile from userinfo endpoint.</li>
389
+ * </ul>
390
+ *
391
+ * <h4>Session Cookie Settings</h4>
392
+ *
393
+ * <ul>
394
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_NAME : </strong>The name of the cookie used to store the user session.</li>
395
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PATH : </strong>The scope path for the session cookie.</li>
396
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_DOMAIN : </strong>The domain scope for the session cookie.</li>
397
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_HTTP_ONLY : </strong>Prevents client-side scripts from accessing the session cookie.</li>
398
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SECURE : </strong>Ensures the session cookie is only sent over HTTPS.</li>
399
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_SAME_SITE : </strong>The SameSite policy for the session cookie (Lax, Strict, or None).</li>
400
+ * <li><strong>MONOCLOUD_AUTH_SESSION_COOKIE_PERSISTENT : </strong>If true, the session survives browser restarts.</li>
401
+ * <li><strong>MONOCLOUD_AUTH_SESSION_SLIDING : </strong>If true, the session will be a sliding session instead of absolute.</li>
402
+ * <li><strong>MONOCLOUD_AUTH_SESSION_DURATION : </strong>The session lifetime in seconds.</li>
403
+ * <li><strong>MONOCLOUD_AUTH_SESSION_MAX_DURATION : </strong>The absolute maximum lifetime of a session in seconds.</li>
404
+ * </ul>
405
+ *
406
+ * <h4>State Cookie Settings</h4>
407
+ *
408
+ * <ul>
409
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_NAME : </strong>The name of the cookie used to store OpenID state/nonce.</li>
410
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PATH : </strong>The scope path for the state cookie.</li>
411
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_DOMAIN : </strong>The domain scope for the state cookie.</li>
412
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SECURE : </strong>Ensures the state cookie is only sent over HTTPS</li>
413
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_SAME_SITE : </strong>The SameSite policy for the state cookie.</li>
414
+ * <li><strong>MONOCLOUD_AUTH_STATE_COOKIE_PERSISTENT : </strong>Whether the state cookie is persistent.</li>
415
+ * </ul>
416
+ *
417
+ * <h4>Caching</h4>
418
+ *
419
+ * <ul>
420
+ * <li><strong>MONOCLOUD_AUTH_JWKS_CACHE_DURATION : </strong>Duration in seconds to cache the JSON Web Key Set.</li>
421
+ * <li><strong>MONOCLOUD_AUTH_METADATA_CACHE_DURATION : </strong>Duration in seconds to cache the OpenID discovery metadata.</li>
422
+ * </ul>
423
+ * </details>
424
+ *
425
+ *
426
+ */
263
427
  var MonoCloudNextClient = class {
264
- /* v8 ignore next -- @preserve */
428
+ /**
429
+ * The underlying OIDC client instance used for low-level OpenID Connect operations.
430
+ *
431
+ * @example
432
+ * // Manually revoke an access token
433
+ * await client.oidcClient.revokeToken(accessToken, 'access_token');
434
+ */
265
435
  get oidcClient() {
266
436
  return this.coreClient.oidcClient;
267
437
  }
438
+ /**
439
+ * @param options Configuration options including domain, client ID, and secret.
440
+ */
268
441
  constructor(options) {
269
- this.protectPage = (...args) => {
270
- if (typeof args[0] === "function") return this.protectAppPage(args[0], args[1]);
271
- return this.protectPagePage(args[0]);
272
- };
273
- this.protectAppPage = (component, options$1) => {
274
- return async (params) => {
275
- const session = await this.getSession();
276
- if (!session) {
277
- var _options$authParams, _options$authParams2, _options$authParams3, _options$authParams4, _options$authParams5, _options$authParams6, _options$authParams7, _options$authParams8, _options$authParams9;
278
- if (options$1 === null || options$1 === void 0 ? void 0 : options$1.onAccessDenied) return options$1.onAccessDenied({ ...params });
279
- const { routes, appUrl } = this.getOptions();
280
- const { headers } = await import("next/headers");
281
- const path = (await headers()).get("x-monocloud-path");
282
- const signInRoute = new URL(`${appUrl}${ensureLeadingSlash(routes.signIn)}`);
283
- signInRoute.searchParams.set("return_url", (options$1 === null || options$1 === void 0 ? void 0 : options$1.returnUrl) ?? path ?? "/");
284
- if (options$1 === null || options$1 === void 0 || (_options$authParams = options$1.authParams) === null || _options$authParams === void 0 ? void 0 : _options$authParams.scopes) signInRoute.searchParams.set("scope", options$1.authParams.scopes);
285
- if (options$1 === null || options$1 === void 0 || (_options$authParams2 = options$1.authParams) === null || _options$authParams2 === void 0 ? void 0 : _options$authParams2.resource) signInRoute.searchParams.set("resource", options$1.authParams.resource);
286
- if (options$1 === null || options$1 === void 0 || (_options$authParams3 = options$1.authParams) === null || _options$authParams3 === void 0 ? void 0 : _options$authParams3.acrValues) signInRoute.searchParams.set("acr_values", options$1.authParams.acrValues.join(" "));
287
- if (options$1 === null || options$1 === void 0 || (_options$authParams4 = options$1.authParams) === null || _options$authParams4 === void 0 ? void 0 : _options$authParams4.display) signInRoute.searchParams.set("display", options$1.authParams.display);
288
- if (options$1 === null || options$1 === void 0 || (_options$authParams5 = options$1.authParams) === null || _options$authParams5 === void 0 ? void 0 : _options$authParams5.prompt) signInRoute.searchParams.set("prompt", options$1.authParams.prompt);
289
- if (options$1 === null || options$1 === void 0 || (_options$authParams6 = options$1.authParams) === null || _options$authParams6 === void 0 ? void 0 : _options$authParams6.authenticatorHint) signInRoute.searchParams.set("authenticator_hint", options$1.authParams.authenticatorHint);
290
- if (options$1 === null || options$1 === void 0 || (_options$authParams7 = options$1.authParams) === null || _options$authParams7 === void 0 ? void 0 : _options$authParams7.uiLocales) signInRoute.searchParams.set("ui_locales", options$1.authParams.uiLocales);
291
- if (options$1 === null || options$1 === void 0 || (_options$authParams8 = options$1.authParams) === null || _options$authParams8 === void 0 ? void 0 : _options$authParams8.maxAge) signInRoute.searchParams.set("max_age", options$1.authParams.maxAge.toString());
292
- if (options$1 === null || options$1 === void 0 || (_options$authParams9 = options$1.authParams) === null || _options$authParams9 === void 0 ? void 0 : _options$authParams9.loginHint) signInRoute.searchParams.set("login_hint", options$1.authParams.loginHint);
293
- return redirect(signInRoute.toString());
294
- }
295
- if ((options$1 === null || options$1 === void 0 ? void 0 : options$1.groups) && !isUserInGroup(session.user, options$1.groups, options$1.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options$1.matchAll)) {
296
- if (options$1.onAccessDenied) return options$1.onAccessDenied({
297
- ...params,
298
- user: session.user
299
- });
300
- return "Access Denied";
301
- }
302
- return component({
303
- ...params,
304
- user: session.user
305
- });
306
- };
307
- };
308
- this.protectPagePage = (options$1) => {
309
- return async (context) => {
310
- const session = await this.getSession(context.req, context.res);
311
- if (!session) {
312
- var _options$authParams10, _options$authParams11, _options$authParams12, _options$authParams13, _options$authParams14, _options$authParams15, _options$authParams16, _options$authParams17, _options$authParams18;
313
- if (options$1 === null || options$1 === void 0 ? void 0 : options$1.onAccessDenied) {
314
- const customProps$1 = await options$1.onAccessDenied({ ...context });
315
- return {
316
- ...customProps$1 ?? {},
317
- props: { ...(customProps$1 === null || customProps$1 === void 0 ? void 0 : customProps$1.props) ?? {} }
318
- };
319
- }
320
- const { routes, appUrl } = this.getOptions();
321
- const signInRoute = new URL(`${appUrl}${ensureLeadingSlash(routes.signIn)}`);
322
- signInRoute.searchParams.set("return_url", (options$1 === null || options$1 === void 0 ? void 0 : options$1.returnUrl) ?? context.resolvedUrl);
323
- if (options$1 === null || options$1 === void 0 || (_options$authParams10 = options$1.authParams) === null || _options$authParams10 === void 0 ? void 0 : _options$authParams10.scopes) signInRoute.searchParams.set("scope", options$1.authParams.scopes);
324
- if (options$1 === null || options$1 === void 0 || (_options$authParams11 = options$1.authParams) === null || _options$authParams11 === void 0 ? void 0 : _options$authParams11.resource) signInRoute.searchParams.set("resource", options$1.authParams.resource);
325
- if (options$1 === null || options$1 === void 0 || (_options$authParams12 = options$1.authParams) === null || _options$authParams12 === void 0 ? void 0 : _options$authParams12.acrValues) signInRoute.searchParams.set("acr_values", options$1.authParams.acrValues.join(" "));
326
- if (options$1 === null || options$1 === void 0 || (_options$authParams13 = options$1.authParams) === null || _options$authParams13 === void 0 ? void 0 : _options$authParams13.display) signInRoute.searchParams.set("display", options$1.authParams.display);
327
- if (options$1 === null || options$1 === void 0 || (_options$authParams14 = options$1.authParams) === null || _options$authParams14 === void 0 ? void 0 : _options$authParams14.prompt) signInRoute.searchParams.set("prompt", options$1.authParams.prompt);
328
- if (options$1 === null || options$1 === void 0 || (_options$authParams15 = options$1.authParams) === null || _options$authParams15 === void 0 ? void 0 : _options$authParams15.authenticatorHint) signInRoute.searchParams.set("authenticator_hint", options$1.authParams.authenticatorHint);
329
- if (options$1 === null || options$1 === void 0 || (_options$authParams16 = options$1.authParams) === null || _options$authParams16 === void 0 ? void 0 : _options$authParams16.uiLocales) signInRoute.searchParams.set("ui_locales", options$1.authParams.uiLocales);
330
- if (options$1 === null || options$1 === void 0 || (_options$authParams17 = options$1.authParams) === null || _options$authParams17 === void 0 ? void 0 : _options$authParams17.maxAge) signInRoute.searchParams.set("max_age", options$1.authParams.maxAge.toString());
331
- if (options$1 === null || options$1 === void 0 || (_options$authParams18 = options$1.authParams) === null || _options$authParams18 === void 0 ? void 0 : _options$authParams18.loginHint) signInRoute.searchParams.set("login_hint", options$1.authParams.loginHint);
332
- return { redirect: {
333
- destination: signInRoute.toString(),
334
- permanent: false
335
- } };
336
- }
337
- if ((options$1 === null || options$1 === void 0 ? void 0 : options$1.groups) && !isUserInGroup(session.user, options$1.groups, options$1.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options$1.matchAll)) {
338
- var _options$onAccessDeni;
339
- const customProps$1 = await ((_options$onAccessDeni = options$1.onAccessDenied) === null || _options$onAccessDeni === void 0 ? void 0 : _options$onAccessDeni.call(options$1, {
340
- ...context,
341
- user: session.user
342
- })) ?? { props: { accessDenied: true } };
343
- return {
344
- ...customProps$1,
345
- props: { ...customProps$1.props ?? {} }
346
- };
347
- }
348
- const customProps = (options$1 === null || options$1 === void 0 ? void 0 : options$1.getServerSideProps) ? await options$1.getServerSideProps(context) : {};
349
- const promiseProp = customProps.props;
350
- if (promiseProp instanceof Promise) return {
351
- ...customProps,
352
- props: promiseProp.then((props) => ({
353
- user: session.user,
354
- ...props
355
- }))
356
- };
357
- return {
358
- ...customProps,
359
- props: {
360
- user: session.user,
361
- ...customProps.props
362
- }
363
- };
364
- };
365
- };
366
- this.protectApi = (handler, options$1) => {
367
- return (req, resOrCtx) => {
368
- if (isAppRouter(req)) return this.protectAppApi(req, resOrCtx, handler, options$1);
369
- return this.protectPageApi(req, resOrCtx, handler, options$1);
370
- };
371
- };
372
- this.protectAppApi = async (req, ctx, handler, options$1) => {
373
- const res = new NextResponse();
374
- const session = await this.getSession(req, res);
375
- if (!session) {
376
- if (options$1 === null || options$1 === void 0 ? void 0 : options$1.onAccessDenied) {
377
- const result = await options$1.onAccessDenied(req, ctx);
378
- if (result instanceof NextResponse) return mergeResponse([res, result]);
379
- return mergeResponse([res, new NextResponse(result.body, result)]);
380
- }
381
- return mergeResponse([res, NextResponse.json({ message: "unauthorized" }, { status: 401 })]);
382
- }
383
- if ((options$1 === null || options$1 === void 0 ? void 0 : options$1.groups) && !isUserInGroup(session.user, options$1.groups, options$1.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options$1.matchAll)) {
384
- if (options$1.onAccessDenied) {
385
- const result = await options$1.onAccessDenied(req, ctx);
386
- if (result instanceof NextResponse) return mergeResponse([res, result]);
387
- return mergeResponse([res, new NextResponse(result.body, result)]);
388
- }
389
- return mergeResponse([res, NextResponse.json({ message: "forbidden" }, { status: 403 })]);
390
- }
391
- const resp = await handler(req, ctx);
392
- if (resp instanceof NextResponse) return mergeResponse([res, resp]);
393
- return mergeResponse([res, new NextResponse(resp.body, resp)]);
394
- };
395
- this.protectPageApi = async (req, res, handler, options$1) => {
396
- const session = await this.getSession(req, res);
397
- if (!session) {
398
- if (options$1 === null || options$1 === void 0 ? void 0 : options$1.onAccessDenied) return options$1.onAccessDenied(req, res);
399
- return res.status(401).json({ message: "unauthorized" });
400
- }
401
- if ((options$1 === null || options$1 === void 0 ? void 0 : options$1.groups) && !isUserInGroup(session.user, options$1.groups, options$1.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options$1.matchAll)) {
402
- if (options$1.onAccessDenied) return options$1.onAccessDenied(req, res, session.user);
403
- return res.status(403).json({ message: "forbidden" });
404
- }
405
- return handler(req, res);
406
- };
407
- this.authMiddleware = (...args) => {
408
- let req;
409
- let evt;
410
- let options$1;
411
- /* v8 ignore else -- @preserve */
412
- if (Array.isArray(args)) {
413
- if (args.length === 2) {
414
- /* v8 ignore else -- @preserve */
415
- if (isAppRouter(args[0])) {
416
- req = args[0];
417
- evt = args[1];
418
- }
419
- }
420
- if (args.length === 1) options$1 = args[0];
421
- }
422
- if (req && evt) return this.authMiddlewareHandler(req, evt, options$1);
423
- return (request, nxtEvt) => {
424
- return this.authMiddlewareHandler(request, nxtEvt, options$1);
425
- };
426
- };
427
- this.getSession = this.resolveFunction(this.resolvedGetSession.bind(this));
428
- this.getTokens = this.resolveFunction(this.resolvedGetTokens.bind(this));
429
- this.isAuthenticated = this.resolveFunction(this.resolvedIsAuthenticated.bind(this));
430
442
  const opt = {
431
443
  ...options ?? {},
432
- userAgent: (options === null || options === void 0 ? void 0 : options.userAgent) ?? `@monocloud/auth-nextjs@0.1.1`,
444
+ userAgent: (options === null || options === void 0 ? void 0 : options.userAgent) ?? `@monocloud/auth-nextjs@0.1.2`,
433
445
  debugger: (options === null || options === void 0 ? void 0 : options.debugger) ?? "@monocloud:auth-nextjs"
434
446
  };
435
447
  this.registerPublicEnvVariables();
@@ -440,12 +452,65 @@ var MonoCloudNextClient = class {
440
452
  * that processes all MonoCloud authentication endpoints
441
453
  * (`/signin`, `/callback`, `/userinfo`, `/signout`).
442
454
  *
443
- * @param {MonoCloudAuthOptions} [options] Optional configuration authentication routes.
455
+ * @param options Authentication configuration routes.
444
456
  *
445
457
  * **Note:** If you are already using `authMiddleware()`, you typically do **not**
446
458
  * need this API route handler. This function is intended for applications where
447
459
  * middleware cannot be used—such as statically generated (SSG) deployments that still
448
460
  * require server-side authentication flows.
461
+ *
462
+ * @example App Router
463
+ *
464
+ * ```typescript
465
+ * // app/api/auth/[...monocloud]/route.ts
466
+ *
467
+ * import { monoCloud } from "@/lib/monocloud";
468
+ *
469
+ * export const GET = monoCloud.monoCloudAuth();
470
+ *```
471
+ *
472
+ * @example App Router with Response
473
+ *
474
+ * ```typescript
475
+ * import { monoCloud } from "@/lib/monocloud";
476
+ * import { NextRequest, NextResponse } from "next/server";
477
+ *
478
+ * export const GET = (req: NextRequest) => {
479
+ * const authHandler = monoCloud.monoCloudAuth();
480
+ *
481
+ * const res = new NextResponse();
482
+ *
483
+ * res.cookies.set("last_auth_requested", `${Date.now()}`);
484
+ *
485
+ * return authHandler(req, res);
486
+ * };
487
+ * ```
488
+ *
489
+ * @example Pages Router
490
+ *
491
+ * ```typescript
492
+ * // pages/api/auth/[...monocloud].ts
493
+ *
494
+ * import { monoCloud } from "@/lib/monocloud";
495
+ *
496
+ * export default monoCloud.monoCloudAuth();
497
+ *```
498
+ *
499
+ * @example Page Router with Response
500
+ *
501
+ * ```typescript
502
+ * import { monoCloud } from "@/lib/monocloud";
503
+ * import { NextApiRequest, NextApiResponse } from "next";
504
+ *
505
+ * export default function handler(req: NextApiRequest, res: NextApiResponse) {
506
+ * const authHandler = monoCloud.monoCloudAuth();
507
+ *
508
+ * res.setHeader("last_auth_requested", `${Date.now()}`);
509
+ *
510
+ * return authHandler(req, res);
511
+ * }
512
+ * ```
513
+ *
449
514
  */
450
515
  monoCloudAuth(options) {
451
516
  return (req, resOrCtx) => {
@@ -455,17 +520,185 @@ var MonoCloudNextClient = class {
455
520
  const route = new URL(url);
456
521
  let onError;
457
522
  if (typeof (options === null || options === void 0 ? void 0 : options.onError) === "function") onError = (error) => options.onError(req, resOrCtx, error);
458
- const { request, response } = getMonoCloudReqRes(req, resOrCtx);
523
+ let request;
524
+ let response;
525
+ if (isAppRouter(req)) {
526
+ request = new MonoCloudAppRouterRequest(getNextRequest(req));
527
+ response = new MonoCloudAppRouterResponse(getNextResponse(resOrCtx));
528
+ } else {
529
+ request = new MonoCloudPageRouterRequest(req);
530
+ response = new MonoCloudPageRouterResponse(resOrCtx);
531
+ }
459
532
  return this.handleAuthRoutes(request, response, route.pathname, routes, onError);
460
533
  };
461
534
  }
535
+ protectPage(...args) {
536
+ if (typeof args[0] === "function") return this.protectAppPage(args[0], args[1]);
537
+ return this.protectPagePage(args[0]);
538
+ }
539
+ protectAppPage(component, options) {
540
+ return async (params) => {
541
+ const session = await this.getSession();
542
+ if (!session) {
543
+ var _options$authParams, _options$authParams2, _options$authParams3, _options$authParams4, _options$authParams5, _options$authParams6, _options$authParams7, _options$authParams8, _options$authParams9;
544
+ if (options === null || options === void 0 ? void 0 : options.onAccessDenied) return options.onAccessDenied({ ...params });
545
+ const { routes, appUrl } = this.getOptions();
546
+ const { headers } = await import("next/headers");
547
+ const path = (await headers()).get("x-monocloud-path");
548
+ const signInRoute = new URL(`${appUrl}${ensureLeadingSlash(routes.signIn)}`);
549
+ signInRoute.searchParams.set("return_url", (options === null || options === void 0 ? void 0 : options.returnUrl) ?? path ?? "/");
550
+ if (options === null || options === void 0 || (_options$authParams = options.authParams) === null || _options$authParams === void 0 ? void 0 : _options$authParams.scopes) signInRoute.searchParams.set("scope", options.authParams.scopes);
551
+ if (options === null || options === void 0 || (_options$authParams2 = options.authParams) === null || _options$authParams2 === void 0 ? void 0 : _options$authParams2.resource) signInRoute.searchParams.set("resource", options.authParams.resource);
552
+ if (options === null || options === void 0 || (_options$authParams3 = options.authParams) === null || _options$authParams3 === void 0 ? void 0 : _options$authParams3.acrValues) signInRoute.searchParams.set("acr_values", options.authParams.acrValues.join(" "));
553
+ if (options === null || options === void 0 || (_options$authParams4 = options.authParams) === null || _options$authParams4 === void 0 ? void 0 : _options$authParams4.display) signInRoute.searchParams.set("display", options.authParams.display);
554
+ if (options === null || options === void 0 || (_options$authParams5 = options.authParams) === null || _options$authParams5 === void 0 ? void 0 : _options$authParams5.prompt) signInRoute.searchParams.set("prompt", options.authParams.prompt);
555
+ if (options === null || options === void 0 || (_options$authParams6 = options.authParams) === null || _options$authParams6 === void 0 ? void 0 : _options$authParams6.authenticatorHint) signInRoute.searchParams.set("authenticator_hint", options.authParams.authenticatorHint);
556
+ if (options === null || options === void 0 || (_options$authParams7 = options.authParams) === null || _options$authParams7 === void 0 ? void 0 : _options$authParams7.uiLocales) signInRoute.searchParams.set("ui_locales", options.authParams.uiLocales);
557
+ if (options === null || options === void 0 || (_options$authParams8 = options.authParams) === null || _options$authParams8 === void 0 ? void 0 : _options$authParams8.maxAge) signInRoute.searchParams.set("max_age", options.authParams.maxAge.toString());
558
+ if (options === null || options === void 0 || (_options$authParams9 = options.authParams) === null || _options$authParams9 === void 0 ? void 0 : _options$authParams9.loginHint) signInRoute.searchParams.set("login_hint", options.authParams.loginHint);
559
+ const { redirect } = await import("next/navigation");
560
+ return redirect(signInRoute.toString());
561
+ }
562
+ if ((options === null || options === void 0 ? void 0 : options.groups) && !isUserInGroup(session.user, options.groups, options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options.matchAll)) {
563
+ if (options.onAccessDenied) return options.onAccessDenied({
564
+ ...params,
565
+ user: session.user
566
+ });
567
+ return "Access Denied";
568
+ }
569
+ return component({
570
+ ...params,
571
+ user: session.user
572
+ });
573
+ };
574
+ }
575
+ protectPagePage(options) {
576
+ return async (context) => {
577
+ const session = await this.getSession(context.req, context.res);
578
+ if (!session) {
579
+ var _options$authParams10, _options$authParams11, _options$authParams12, _options$authParams13, _options$authParams14, _options$authParams15, _options$authParams16, _options$authParams17, _options$authParams18;
580
+ if (options === null || options === void 0 ? void 0 : options.onAccessDenied) {
581
+ const customProps$1 = await options.onAccessDenied({ ...context });
582
+ return {
583
+ ...customProps$1 ?? {},
584
+ props: { ...(customProps$1 === null || customProps$1 === void 0 ? void 0 : customProps$1.props) ?? {} }
585
+ };
586
+ }
587
+ const { routes, appUrl } = this.getOptions();
588
+ const signInRoute = new URL(`${appUrl}${ensureLeadingSlash(routes.signIn)}`);
589
+ signInRoute.searchParams.set("return_url", (options === null || options === void 0 ? void 0 : options.returnUrl) ?? context.resolvedUrl);
590
+ if (options === null || options === void 0 || (_options$authParams10 = options.authParams) === null || _options$authParams10 === void 0 ? void 0 : _options$authParams10.scopes) signInRoute.searchParams.set("scope", options.authParams.scopes);
591
+ if (options === null || options === void 0 || (_options$authParams11 = options.authParams) === null || _options$authParams11 === void 0 ? void 0 : _options$authParams11.resource) signInRoute.searchParams.set("resource", options.authParams.resource);
592
+ if (options === null || options === void 0 || (_options$authParams12 = options.authParams) === null || _options$authParams12 === void 0 ? void 0 : _options$authParams12.acrValues) signInRoute.searchParams.set("acr_values", options.authParams.acrValues.join(" "));
593
+ if (options === null || options === void 0 || (_options$authParams13 = options.authParams) === null || _options$authParams13 === void 0 ? void 0 : _options$authParams13.display) signInRoute.searchParams.set("display", options.authParams.display);
594
+ if (options === null || options === void 0 || (_options$authParams14 = options.authParams) === null || _options$authParams14 === void 0 ? void 0 : _options$authParams14.prompt) signInRoute.searchParams.set("prompt", options.authParams.prompt);
595
+ if (options === null || options === void 0 || (_options$authParams15 = options.authParams) === null || _options$authParams15 === void 0 ? void 0 : _options$authParams15.authenticatorHint) signInRoute.searchParams.set("authenticator_hint", options.authParams.authenticatorHint);
596
+ if (options === null || options === void 0 || (_options$authParams16 = options.authParams) === null || _options$authParams16 === void 0 ? void 0 : _options$authParams16.uiLocales) signInRoute.searchParams.set("ui_locales", options.authParams.uiLocales);
597
+ if (options === null || options === void 0 || (_options$authParams17 = options.authParams) === null || _options$authParams17 === void 0 ? void 0 : _options$authParams17.maxAge) signInRoute.searchParams.set("max_age", options.authParams.maxAge.toString());
598
+ if (options === null || options === void 0 || (_options$authParams18 = options.authParams) === null || _options$authParams18 === void 0 ? void 0 : _options$authParams18.loginHint) signInRoute.searchParams.set("login_hint", options.authParams.loginHint);
599
+ return { redirect: {
600
+ destination: signInRoute.toString(),
601
+ permanent: false
602
+ } };
603
+ }
604
+ if ((options === null || options === void 0 ? void 0 : options.groups) && !isUserInGroup(session.user, options.groups, options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options.matchAll)) {
605
+ var _options$onAccessDeni;
606
+ const customProps$1 = await ((_options$onAccessDeni = options.onAccessDenied) === null || _options$onAccessDeni === void 0 ? void 0 : _options$onAccessDeni.call(options, {
607
+ ...context,
608
+ user: session.user
609
+ })) ?? { props: { accessDenied: true } };
610
+ return {
611
+ ...customProps$1,
612
+ props: { ...customProps$1.props ?? {} }
613
+ };
614
+ }
615
+ const customProps = (options === null || options === void 0 ? void 0 : options.getServerSideProps) ? await options.getServerSideProps(context) : {};
616
+ const promiseProp = customProps.props;
617
+ if (promiseProp instanceof Promise) return {
618
+ ...customProps,
619
+ props: promiseProp.then((props) => ({
620
+ user: session.user,
621
+ ...props
622
+ }))
623
+ };
624
+ return {
625
+ ...customProps,
626
+ props: {
627
+ user: session.user,
628
+ ...customProps.props
629
+ }
630
+ };
631
+ };
632
+ }
633
+ protectApi(handler, options) {
634
+ return (req, resOrCtx) => {
635
+ if (isAppRouter(req)) return this.protectAppApi(req, resOrCtx, handler, options);
636
+ return this.protectPageApi(req, resOrCtx, handler, options);
637
+ };
638
+ }
639
+ async protectAppApi(req, ctx, handler, options) {
640
+ const res = new NextResponse();
641
+ const session = await this.getSession(req, res);
642
+ if (!session) {
643
+ if (options === null || options === void 0 ? void 0 : options.onAccessDenied) {
644
+ const result = await options.onAccessDenied(req, ctx);
645
+ if (result instanceof NextResponse) return mergeResponse([res, result]);
646
+ return mergeResponse([res, new NextResponse(result.body, result)]);
647
+ }
648
+ return mergeResponse([res, NextResponse.json({ message: "unauthorized" }, { status: 401 })]);
649
+ }
650
+ if ((options === null || options === void 0 ? void 0 : options.groups) && !isUserInGroup(session.user, options.groups, options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options.matchAll)) {
651
+ if (options.onAccessDenied) {
652
+ const result = await options.onAccessDenied(req, ctx);
653
+ if (result instanceof NextResponse) return mergeResponse([res, result]);
654
+ return mergeResponse([res, new NextResponse(result.body, result)]);
655
+ }
656
+ return mergeResponse([res, NextResponse.json({ message: "forbidden" }, { status: 403 })]);
657
+ }
658
+ const resp = await handler(req, ctx);
659
+ if (resp instanceof NextResponse) return mergeResponse([res, resp]);
660
+ return mergeResponse([res, new NextResponse(resp.body, resp)]);
661
+ }
662
+ async protectPageApi(req, res, handler, options) {
663
+ const session = await this.getSession(req, res);
664
+ if (!session) {
665
+ if (options === null || options === void 0 ? void 0 : options.onAccessDenied) return options.onAccessDenied(req, res);
666
+ return res.status(401).json({ message: "unauthorized" });
667
+ }
668
+ if ((options === null || options === void 0 ? void 0 : options.groups) && !isUserInGroup(session.user, options.groups, options.groupsClaim ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options.matchAll)) {
669
+ if (options.onAccessDenied) return options.onAccessDenied(req, res, session.user);
670
+ return res.status(403).json({ message: "forbidden" });
671
+ }
672
+ return handler(req, res);
673
+ }
674
+ authMiddleware(...args) {
675
+ let req;
676
+ let evt;
677
+ let options;
678
+ /* v8 ignore else -- @preserve */
679
+ if (Array.isArray(args)) {
680
+ if (args.length === 2) {
681
+ /* v8 ignore else -- @preserve */
682
+ if (isAppRouter(args[0])) {
683
+ req = args[0];
684
+ evt = args[1];
685
+ }
686
+ }
687
+ if (args.length === 1) options = args[0];
688
+ }
689
+ if (req && evt) return this.authMiddlewareHandler(req, evt, options);
690
+ return (request, nxtEvt) => {
691
+ return this.authMiddlewareHandler(request, nxtEvt, options);
692
+ };
693
+ }
462
694
  async authMiddlewareHandler(req, evt, options) {
695
+ req = getNextRequest(req);
463
696
  if (req.headers.has("x-middleware-subrequest")) return NextResponse.json({ message: "forbidden" }, { status: 403 });
464
697
  const { routes, appUrl } = this.getOptions();
465
698
  if (Object.values(routes).map((x) => ensureLeadingSlash(x)).includes(req.nextUrl.pathname)) {
466
699
  let onError;
467
700
  if (typeof (options === null || options === void 0 ? void 0 : options.onError) === "function") onError = (error) => options.onError(req, evt, error);
468
- const request = new MonoCloudAppRouterRequest(req, { params: {} });
701
+ const request = new MonoCloudAppRouterRequest(req);
469
702
  const response = new MonoCloudAppRouterResponse(new NextResponse());
470
703
  return this.handleAuthRoutes(request, response, req.nextUrl.pathname, routes, onError);
471
704
  }
@@ -521,10 +754,101 @@ var MonoCloudNextClient = class {
521
754
  return response.done();
522
755
  }
523
756
  }
757
+ async getSession(...args) {
758
+ let request;
759
+ let response;
760
+ if (args.length === 0) {
761
+ request = new MonoCloudCookieRequest();
762
+ response = new MonoCloudCookieResponse();
763
+ } else ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
764
+ /* v8 ignore next -- @preserve */
765
+ if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) throw new MonoCloudValidationError$1("Invalid parameters passed to getSession()");
766
+ return await this.coreClient.getSession(request, response);
767
+ }
768
+ async getTokens(...args) {
769
+ let request;
770
+ let response;
771
+ let options;
772
+ if (args.length === 0) {
773
+ request = new MonoCloudCookieRequest();
774
+ response = new MonoCloudCookieResponse();
775
+ } else if (args.length === 1) if (args[0] instanceof Request) ({request, response} = getMonoCloudCookieReqRes(args[0], void 0));
776
+ else {
777
+ request = new MonoCloudCookieRequest();
778
+ response = new MonoCloudCookieResponse();
779
+ options = args[0];
780
+ }
781
+ else if (args.length === 2 && args[0] instanceof Request) if (args[1] instanceof Response) ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
782
+ else {
783
+ ({request, response} = getMonoCloudCookieReqRes(args[0], void 0));
784
+ options = args[1];
785
+ }
786
+ else if (args.length === 2 && args[0] instanceof IncomingMessage && args[1] instanceof ServerResponse) ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
787
+ else {
788
+ ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
789
+ options = args[2];
790
+ }
791
+ if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response) || options && typeof options !== "object") throw new MonoCloudValidationError$1("Invalid parameters passed to getTokens()");
792
+ return await this.coreClient.getTokens(request, response, options);
793
+ }
794
+ async isAuthenticated(...args) {
795
+ let request;
796
+ let response;
797
+ if (args.length === 0) {
798
+ request = new MonoCloudCookieRequest();
799
+ response = new MonoCloudCookieResponse();
800
+ } else ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
801
+ /* v8 ignore next -- @preserve */
802
+ if (!isMonoCloudRequest(request) || !isMonoCloudResponse(response)) throw new MonoCloudValidationError$1("Invalid parameters passed to isAuthenticated()");
803
+ return await this.coreClient.isAuthenticated(request, response);
804
+ }
524
805
  /**
525
- * Redirects the user to sign-in if not authenticated.
806
+ * Redirects the user to the sign-in flow if they are not authenticated.
807
+ *
808
+ * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**
809
+ *
810
+ * @param options Options to customize the sign-in.
811
+ *
812
+ * @returns
813
+ *
814
+ * @example React Server Component
815
+ *
816
+ * ```tsx
817
+ * import { monoCloud } from "@/lib/monocloud";
818
+ *
819
+ * export default async function Home() {
820
+ * await monoCloud.protect();
821
+ *
822
+ * return <>You are signed in.</>;
823
+ * }
824
+ * ```
825
+ *
826
+ * @example API Handler
827
+ *
828
+ * ```typescript
829
+ * import { NextResponse } from "next/server";
830
+ * import { monoCloud } from "@/lib/monocloud";
526
831
  *
527
- * **Note: This function only works on App Router.**
832
+ * export const GET = async () => {
833
+ * await monoCloud.protect();
834
+ *
835
+ * return NextResponse.json({ secret: "ssshhhh!!!" });
836
+ * };
837
+ * ```
838
+ *
839
+ * @example Server Action
840
+ *
841
+ * ```typescript
842
+ * "use server";
843
+ *
844
+ * import { monoCloud } from "@/lib/monocloud";
845
+ *
846
+ * export async function getMessage() {
847
+ * await monoCloud.protect();
848
+ *
849
+ * return { secret: "sssshhhhh!!!" };
850
+ * }
851
+ * ```
528
852
  */
529
853
  async protect(options) {
530
854
  var _options$authParams19, _options$authParams20, _options$authParams21, _options$authParams22, _options$authParams23, _options$authParams24, _options$authParams25, _options$authParams26, _options$authParams27;
@@ -537,7 +861,7 @@ var MonoCloudNextClient = class {
537
861
  const { headers } = await import("next/headers");
538
862
  path = (await headers()).get("x-monocloud-path") ?? "/";
539
863
  } catch {
540
- throw new Error("protect() can only be used in App Router project");
864
+ throw new Error("protect() can only be used in App Router server environments (RSC, route handlers, or server actions)");
541
865
  }
542
866
  const signInRoute = new URL(`${appUrl}${routes.signIn}`);
543
867
  signInRoute.searchParams.set("return_url", (options === null || options === void 0 ? void 0 : options.returnUrl) ?? path);
@@ -550,6 +874,7 @@ var MonoCloudNextClient = class {
550
874
  if (Array.isArray(options === null || options === void 0 || (_options$authParams25 = options.authParams) === null || _options$authParams25 === void 0 ? void 0 : _options$authParams25.acrValues)) signInRoute.searchParams.set("acr_values", options.authParams.acrValues.join(" "));
551
875
  if (options === null || options === void 0 || (_options$authParams26 = options.authParams) === null || _options$authParams26 === void 0 ? void 0 : _options$authParams26.loginHint) signInRoute.searchParams.set("login_hint", options.authParams.loginHint);
552
876
  if (options === null || options === void 0 || (_options$authParams27 = options.authParams) === null || _options$authParams27 === void 0 ? void 0 : _options$authParams27.prompt) signInRoute.searchParams.set("prompt", options.authParams.prompt);
877
+ const { redirect } = await import("next/navigation");
553
878
  redirect(signInRoute.toString());
554
879
  }
555
880
  async isUserInGroup(...args) {
@@ -558,44 +883,105 @@ var MonoCloudNextClient = class {
558
883
  let groups;
559
884
  let options;
560
885
  if (args.length === 4) {
561
- const req = args[0];
562
- const res = args[1];
563
886
  groups = args[2];
564
887
  options = args[3];
565
- const reqRes = getMonoCloudReqRes(req, res);
566
- ({request} = reqRes);
567
- ({response} = reqRes);
888
+ ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
568
889
  }
569
890
  if (args.length === 3) {
570
- const req = args[0];
571
- const res = args[1];
572
- groups = args[2];
573
- const reqRes = getMonoCloudReqRes(req, res);
574
- ({request} = reqRes);
575
- ({response} = reqRes);
891
+ if (args[0] instanceof Request) if (args[1] instanceof Response) {
892
+ ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
893
+ groups = args[2];
894
+ } else {
895
+ ({request, response} = getMonoCloudCookieReqRes(args[0], void 0));
896
+ groups = args[1];
897
+ options = args[2];
898
+ }
899
+ if (args[0] instanceof IncomingMessage && args[1] instanceof ServerResponse) {
900
+ ({request, response} = getMonoCloudCookieReqRes(args[0], args[1]));
901
+ groups = args[2];
902
+ }
576
903
  }
577
904
  if (args.length === 2) {
578
- request = new MonoCloudCookieRequest();
579
- response = new MonoCloudCookieResponse();
580
- groups = args[0];
581
- options = args[1];
905
+ if (args[0] instanceof Request) {
906
+ ({request, response} = getMonoCloudCookieReqRes(args[0], void 0));
907
+ groups = args[1];
908
+ }
909
+ if (Array.isArray(args[0])) {
910
+ request = new MonoCloudCookieRequest();
911
+ response = new MonoCloudCookieResponse();
912
+ groups = args[0];
913
+ options = args[1];
914
+ }
582
915
  }
583
916
  if (args.length === 1) {
584
917
  request = new MonoCloudCookieRequest();
585
918
  response = new MonoCloudCookieResponse();
586
919
  groups = args[0];
587
920
  }
588
- if (!Array.isArray(groups) || !request || !response) throw new MonoCloudValidationError$1("Invalid parameters passed to isUserInGroup()");
921
+ if (!Array.isArray(groups) || !isMonoCloudRequest(request) || !isMonoCloudResponse(response) || options && typeof options !== "object") throw new MonoCloudValidationError$1("Invalid parameters passed to isUserInGroup()");
589
922
  return await this.coreClient.isUserInGroup(request, response, groups, (options === null || options === void 0 ? void 0 : options.groupsClaim) ?? process.env.MONOCLOUD_AUTH_GROUPS_CLAIM, options === null || options === void 0 ? void 0 : options.matchAll);
590
923
  }
591
924
  /**
592
- * Redirects the user to the sign-in route.
925
+ * Redirects the user to the sign-in flow.
926
+ *
927
+ * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**
928
+ *
929
+ * @param options Options to customize the sign-in.
930
+ *
931
+ * @returns
593
932
  *
594
- * This helper is intended for **App Router** only (server components,
595
- * route handlers, server actions). It constructs the MonoCloud sign-in URL
596
- * with optional parameters and issues a framework redirect.
933
+ * @example React Server Component
597
934
  *
598
- * @throws Error if used outside of an App Router context.
935
+ * ```tsx
936
+ * import { monoCloud } from "@/lib/monocloud";
937
+ *
938
+ * export default async function Home() {
939
+ * const allowed = await monoCloud.isUserInGroup(["admin"]);
940
+ *
941
+ * if (!allowed) {
942
+ * await monoCloud.redirectToSignIn({ returnUrl: "/home" });
943
+ * }
944
+ *
945
+ * return <>You are signed in.</>;
946
+ * }
947
+ * ```
948
+ *
949
+ * @example Server Action
950
+ *
951
+ * ```typescript
952
+ * "use server";
953
+ *
954
+ * import { monoCloud } from "@/lib/monocloud";
955
+ *
956
+ * export async function protectedAction() {
957
+ * const session = await monoCloud.getSession();
958
+ *
959
+ * if (!session) {
960
+ * await monoCloud.redirectToSignIn();
961
+ * }
962
+ *
963
+ * return { data: "Sensitive Data" };
964
+ * }
965
+ * ```
966
+ *
967
+ * @example API Handler
968
+ *
969
+ * ```typescript
970
+ * import { NextResponse } from "next/server";
971
+ * import { monoCloud } from "@/lib/monocloud";
972
+ *
973
+ * export const GET = async () => {
974
+ * const session = await monoCloud.getSession();
975
+ *
976
+ * if (!session) {
977
+ * await monoCloud.redirectToSignIn({
978
+ * returnUrl: "/dashboard",
979
+ * });
980
+ * }
981
+ *
982
+ * return NextResponse.json({ data: "Protected content" });
983
+ * };
984
+ * ```
599
985
  */
600
986
  async redirectToSignIn(options) {
601
987
  const { routes, appUrl } = this.coreClient.getOptions();
@@ -603,7 +989,7 @@ var MonoCloudNextClient = class {
603
989
  const { headers } = await import("next/headers");
604
990
  await headers();
605
991
  } catch {
606
- throw new Error("redirectToSignIn() can only be used in App Router project");
992
+ throw new Error("redirectToSignIn() can only be used in App Router server environments (RSC, route handlers, or server actions)");
607
993
  }
608
994
  const signInRoute = new URL(`${appUrl}${routes.signIn}`);
609
995
  if (options === null || options === void 0 ? void 0 : options.returnUrl) signInRoute.searchParams.set("return_url", options.returnUrl);
@@ -616,15 +1002,69 @@ var MonoCloudNextClient = class {
616
1002
  if (Array.isArray(options === null || options === void 0 ? void 0 : options.acrValues)) signInRoute.searchParams.set("acr_values", options.acrValues.join(" "));
617
1003
  if (options === null || options === void 0 ? void 0 : options.loginHint) signInRoute.searchParams.set("login_hint", options.loginHint);
618
1004
  if (options === null || options === void 0 ? void 0 : options.prompt) signInRoute.searchParams.set("prompt", options.prompt);
1005
+ const { redirect } = await import("next/navigation");
619
1006
  redirect(signInRoute.toString());
620
1007
  }
621
1008
  /**
622
- * Redirects the user to the sign-out route.
1009
+ * Redirects the user to the sign-out flow.
1010
+ *
1011
+ * **This helper is App Router only and is designed for server environments (server components, route handlers, and server actions).**
1012
+ *
1013
+ * @param options Options to customize the sign out.
1014
+ *
1015
+ * @returns
1016
+ *
1017
+ * @example React Server Component
623
1018
  *
624
- * This helper is intended for **App Router** only. It builds the sign-out
625
- * URL and optionally attaches a `post_logout_redirect_uri` override.
1019
+ * ```tsx
1020
+ * import { monoCloud } from "@/lib/monocloud";
626
1021
  *
627
- * @throws Error if used outside of an App Router context.
1022
+ * export default async function Page() {
1023
+ * const session = await monoCloud.getSession();
1024
+ *
1025
+ * // Example: Force sign-out if a specific condition is met (e.g., account suspended)
1026
+ * if (session?.user.isSuspended) {
1027
+ * await monoCloud.redirectToSignOut();
1028
+ * }
1029
+ *
1030
+ * return <>Welcome User</>;
1031
+ * }
1032
+ * ```
1033
+ *
1034
+ * @example Server Action
1035
+ *
1036
+ * ```typescript
1037
+ * "use server";
1038
+ *
1039
+ * import { monoCloud } from "@/lib/monocloud";
1040
+ *
1041
+ * export async function signOutAction() {
1042
+ * const session = await monoCloud.getSession();
1043
+ *
1044
+ * if (session) {
1045
+ * await monoCloud.redirectToSignOut();
1046
+ * }
1047
+ * }
1048
+ * ```
1049
+ *
1050
+ * @example API Handler
1051
+ *
1052
+ * ```typescript
1053
+ * import { monoCloud } from "@/lib/monocloud";
1054
+ * import { NextResponse } from "next/server";
1055
+ *
1056
+ * export const GET = async () => {
1057
+ * const session = await monoCloud.getSession();
1058
+ *
1059
+ * if (session) {
1060
+ * await monoCloud.redirectToSignOut({
1061
+ * postLogoutRedirectUri: "/goodbye",
1062
+ * });
1063
+ * }
1064
+ *
1065
+ * return NextResponse.json({ status: "already_signed_out" });
1066
+ * };
1067
+ * ```
628
1068
  */
629
1069
  async redirectToSignOut(options) {
630
1070
  var _options$postLogoutRe;
@@ -633,71 +1073,14 @@ var MonoCloudNextClient = class {
633
1073
  const { headers } = await import("next/headers");
634
1074
  await headers();
635
1075
  } catch {
636
- throw new Error("redirectToSignOut() can only be used in App Router project");
1076
+ throw new Error("redirectToSignOut() can only be used in App Router server environments (RSC, route handlers, or server actions)");
637
1077
  }
638
1078
  const signOutRoute = new URL(`${appUrl}${routes.signOut}`);
639
1079
  if (options === null || options === void 0 || (_options$postLogoutRe = options.postLogoutRedirectUri) === null || _options$postLogoutRe === void 0 ? void 0 : _options$postLogoutRe.trim().length) signOutRoute.searchParams.set("post_logout_url", options.postLogoutRedirectUri);
1080
+ if (typeof (options === null || options === void 0 ? void 0 : options.federated) === "boolean") signOutRoute.searchParams.set("federated", options.federated.toString());
1081
+ const { redirect } = await import("next/navigation");
640
1082
  redirect(signOutRoute.toString());
641
1083
  }
642
- resolveFunction(baseHandler) {
643
- return ((...args) => {
644
- if (args.length === 3) {
645
- const req = args[0];
646
- const res = args[1];
647
- const options = args[2];
648
- return baseHandler(req, res, options);
649
- }
650
- if (args.length === 2) {
651
- const req = args[0];
652
- const res = args[1];
653
- return baseHandler(req, res);
654
- }
655
- if (args.length === 1) {
656
- const options = args[0];
657
- return baseHandler(void 0, void 0, options);
658
- }
659
- return baseHandler();
660
- });
661
- }
662
- resolvedGetSession(req, resOrCtx) {
663
- let request;
664
- let response;
665
- if (req && resOrCtx) {
666
- const result = getMonoCloudReqRes(req, resOrCtx);
667
- ({request} = result);
668
- ({response} = result);
669
- } else {
670
- request = new MonoCloudCookieRequest();
671
- response = new MonoCloudCookieResponse();
672
- }
673
- return this.coreClient.getSession(request, response);
674
- }
675
- resolvedGetTokens(req, resOrCtx, options) {
676
- let request;
677
- let response;
678
- if (req && resOrCtx) {
679
- const result = getMonoCloudReqRes(req, resOrCtx);
680
- ({request} = result);
681
- ({response} = result);
682
- } else {
683
- request = new MonoCloudCookieRequest();
684
- response = new MonoCloudCookieResponse();
685
- }
686
- return this.coreClient.getTokens(request, response, options);
687
- }
688
- resolvedIsAuthenticated(req, resOrCtx) {
689
- let request;
690
- let response;
691
- if (req && resOrCtx) {
692
- const result = getMonoCloudReqRes(req, resOrCtx);
693
- ({request} = result);
694
- ({response} = result);
695
- } else {
696
- request = new MonoCloudCookieRequest();
697
- response = new MonoCloudCookieResponse();
698
- }
699
- return this.coreClient.isAuthenticated(request, response);
700
- }
701
1084
  getOptions() {
702
1085
  return this.coreClient.getOptions();
703
1086
  }