@nihplod/sso-sdk 1.1.0 → 1.2.1

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.
@@ -61,6 +61,18 @@ interface SsoMiddlewareConfig {
61
61
  returnUrlCookieName?: string;
62
62
  /** PKCE Verifier Cookie 名称,默认 __Secure-nihplod_sso_verifier */
63
63
  verifierCookieName?: string;
64
+ /**
65
+ * 本地 HTTP 开发模式(默认 false)。
66
+ *
67
+ * ⚠️ 仅限 http://localhost 开发:关闭 Cookie 的 Secure 属性并去除
68
+ * __Host-/__Secure- 前缀(浏览器拒绝在 HTTP 下写入带这两个前缀的 Cookie,
69
+ * 否则会出现「登录后 cookie 写不进去 → middleware 永远判定未登录 →
70
+ * 反复跳 SSO」的无限重定向)。开启时启动告警;生产环境严禁启用——
71
+ * 生产环境(NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被
72
+ * 强制忽略并告警,仍走 secure cookie。
73
+ * middleware / callback / logout 三处配置需保持一致。
74
+ */
75
+ insecureLocalDev?: boolean;
64
76
  }
65
77
  declare function createSsoMiddleware(config: SsoMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
66
78
 
@@ -115,6 +127,14 @@ interface CallbackRouteConfig {
115
127
  returnUrlCookieName?: string;
116
128
  /** PKCE Verifier Cookie 名称,默认 __Secure-nihplod_sso_verifier */
117
129
  verifierCookieName?: string;
130
+ /**
131
+ * 本地 HTTP 开发模式(默认 false)。关闭 Cookie 的 Secure 属性并去除
132
+ * __Host-/__Secure- 前缀;必须与 createSsoMiddleware 的配置保持一致,
133
+ * 否则读不到 middleware 写入的 state/verifier Cookie。生产严禁启用——
134
+ * 生产环境(NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被
135
+ * 强制忽略并告警。
136
+ */
137
+ insecureLocalDev?: boolean;
118
138
  }
119
139
  declare function createCallbackRouteHandler(config: CallbackRouteConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
120
140
 
@@ -176,6 +196,13 @@ interface LogoutRouteConfig {
176
196
  callbackPath?: string;
177
197
  /** Logout State Cookie 名称(RP-Initiated Logout CSRF 防护),默认 __Host-nihplod_sso_logout_state */
178
198
  logoutStateCookieName?: string;
199
+ /**
200
+ * 本地 HTTP 开发模式(默认 false)。关闭 Cookie 的 Secure 属性并去除
201
+ * __Host-/__Secure- 前缀;必须与 middleware / callback 的配置保持一致,
202
+ * 否则无法清除它们写入的 Cookie。生产严禁启用——生产环境
203
+ * (NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被强制忽略并告警。
204
+ */
205
+ insecureLocalDev?: boolean;
179
206
  }
180
207
  declare function createLogoutRouteHandler(config: LogoutRouteConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
181
208
 
@@ -196,21 +223,27 @@ declare const DEFAULT_STATE_COOKIE_NAME = "__Host-nihplod_sso_state";
196
223
  declare const DEFAULT_RETURN_COOKIE_NAME = "__Host-nihplod_sso_return";
197
224
  declare const DEFAULT_VERIFIER_COOKIE_NAME = "__Secure-nihplod_sso_verifier";
198
225
  declare const DEFAULT_LOGOUT_STATE_COOKIE_NAME = "__Host-nihplod_sso_logout_state";
226
+ /**
227
+ * insecureLocalDev 场景:去除 __Host-/__Secure- 前缀。
228
+ * 浏览器强制要求带这两个前缀的 Cookie 必须设置 Secure,
229
+ * HTTP 本地开发时若保留前缀,即使 secure=false 也会被拒绝写入。
230
+ */
231
+ declare function toInsecureCookieName(name: string): string;
199
232
  /** __Host- 前缀 Cookie 的安全选项(Path 必须为 /) */
200
- declare function getHostCookieOptions(maxAge?: number): {
233
+ declare function getHostCookieOptions(maxAge?: number, secure?: boolean): {
201
234
  httpOnly: true;
202
- secure: true;
235
+ secure: boolean;
203
236
  sameSite: "lax";
204
237
  path: "/";
205
238
  maxAge?: number;
206
239
  };
207
240
  /** __Secure- 前缀 Cookie 的安全选项(允许自定义 Path) */
208
- declare function getSecureCookieOptions(maxAge?: number, path?: string): {
241
+ declare function getSecureCookieOptions(maxAge?: number, path?: string, secure?: boolean): {
209
242
  httpOnly: true;
210
- secure: true;
243
+ secure: boolean;
211
244
  sameSite: "lax";
212
245
  path: string;
213
246
  maxAge?: number;
214
247
  };
215
248
 
216
- export { type CallbackRouteConfig, DEFAULT_ACCESS_TOKEN_COOKIE_NAME, DEFAULT_ID_TOKEN_COOKIE_NAME, DEFAULT_LOGOUT_STATE_COOKIE_NAME, DEFAULT_REFRESH_TOKEN_COOKIE_NAME, DEFAULT_RETURN_COOKIE_NAME, DEFAULT_STATE_COOKIE_NAME, DEFAULT_VERIFIER_COOKIE_NAME, type LogoutRouteConfig, type SsoMiddlewareConfig, createCallbackRouteHandler, createLogoutRouteHandler, createSsoMiddleware, getHostCookieOptions, getSecureCookieOptions };
249
+ export { type CallbackRouteConfig, DEFAULT_ACCESS_TOKEN_COOKIE_NAME, DEFAULT_ID_TOKEN_COOKIE_NAME, DEFAULT_LOGOUT_STATE_COOKIE_NAME, DEFAULT_REFRESH_TOKEN_COOKIE_NAME, DEFAULT_RETURN_COOKIE_NAME, DEFAULT_STATE_COOKIE_NAME, DEFAULT_VERIFIER_COOKIE_NAME, type LogoutRouteConfig, type SsoMiddlewareConfig, createCallbackRouteHandler, createLogoutRouteHandler, createSsoMiddleware, getHostCookieOptions, getSecureCookieOptions, toInsecureCookieName };
@@ -61,6 +61,18 @@ interface SsoMiddlewareConfig {
61
61
  returnUrlCookieName?: string;
62
62
  /** PKCE Verifier Cookie 名称,默认 __Secure-nihplod_sso_verifier */
63
63
  verifierCookieName?: string;
64
+ /**
65
+ * 本地 HTTP 开发模式(默认 false)。
66
+ *
67
+ * ⚠️ 仅限 http://localhost 开发:关闭 Cookie 的 Secure 属性并去除
68
+ * __Host-/__Secure- 前缀(浏览器拒绝在 HTTP 下写入带这两个前缀的 Cookie,
69
+ * 否则会出现「登录后 cookie 写不进去 → middleware 永远判定未登录 →
70
+ * 反复跳 SSO」的无限重定向)。开启时启动告警;生产环境严禁启用——
71
+ * 生产环境(NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被
72
+ * 强制忽略并告警,仍走 secure cookie。
73
+ * middleware / callback / logout 三处配置需保持一致。
74
+ */
75
+ insecureLocalDev?: boolean;
64
76
  }
65
77
  declare function createSsoMiddleware(config: SsoMiddlewareConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
66
78
 
@@ -115,6 +127,14 @@ interface CallbackRouteConfig {
115
127
  returnUrlCookieName?: string;
116
128
  /** PKCE Verifier Cookie 名称,默认 __Secure-nihplod_sso_verifier */
117
129
  verifierCookieName?: string;
130
+ /**
131
+ * 本地 HTTP 开发模式(默认 false)。关闭 Cookie 的 Secure 属性并去除
132
+ * __Host-/__Secure- 前缀;必须与 createSsoMiddleware 的配置保持一致,
133
+ * 否则读不到 middleware 写入的 state/verifier Cookie。生产严禁启用——
134
+ * 生产环境(NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被
135
+ * 强制忽略并告警。
136
+ */
137
+ insecureLocalDev?: boolean;
118
138
  }
119
139
  declare function createCallbackRouteHandler(config: CallbackRouteConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
120
140
 
@@ -176,6 +196,13 @@ interface LogoutRouteConfig {
176
196
  callbackPath?: string;
177
197
  /** Logout State Cookie 名称(RP-Initiated Logout CSRF 防护),默认 __Host-nihplod_sso_logout_state */
178
198
  logoutStateCookieName?: string;
199
+ /**
200
+ * 本地 HTTP 开发模式(默认 false)。关闭 Cookie 的 Secure 属性并去除
201
+ * __Host-/__Secure- 前缀;必须与 middleware / callback 的配置保持一致,
202
+ * 否则无法清除它们写入的 Cookie。生产严禁启用——生产环境
203
+ * (NODE_ENV=production 且 ssoBaseUrl 为 https)下该开关会被强制忽略并告警。
204
+ */
205
+ insecureLocalDev?: boolean;
179
206
  }
180
207
  declare function createLogoutRouteHandler(config: LogoutRouteConfig): (request: NextRequest) => Promise<NextResponse<unknown>>;
181
208
 
@@ -196,21 +223,27 @@ declare const DEFAULT_STATE_COOKIE_NAME = "__Host-nihplod_sso_state";
196
223
  declare const DEFAULT_RETURN_COOKIE_NAME = "__Host-nihplod_sso_return";
197
224
  declare const DEFAULT_VERIFIER_COOKIE_NAME = "__Secure-nihplod_sso_verifier";
198
225
  declare const DEFAULT_LOGOUT_STATE_COOKIE_NAME = "__Host-nihplod_sso_logout_state";
226
+ /**
227
+ * insecureLocalDev 场景:去除 __Host-/__Secure- 前缀。
228
+ * 浏览器强制要求带这两个前缀的 Cookie 必须设置 Secure,
229
+ * HTTP 本地开发时若保留前缀,即使 secure=false 也会被拒绝写入。
230
+ */
231
+ declare function toInsecureCookieName(name: string): string;
199
232
  /** __Host- 前缀 Cookie 的安全选项(Path 必须为 /) */
200
- declare function getHostCookieOptions(maxAge?: number): {
233
+ declare function getHostCookieOptions(maxAge?: number, secure?: boolean): {
201
234
  httpOnly: true;
202
- secure: true;
235
+ secure: boolean;
203
236
  sameSite: "lax";
204
237
  path: "/";
205
238
  maxAge?: number;
206
239
  };
207
240
  /** __Secure- 前缀 Cookie 的安全选项(允许自定义 Path) */
208
- declare function getSecureCookieOptions(maxAge?: number, path?: string): {
241
+ declare function getSecureCookieOptions(maxAge?: number, path?: string, secure?: boolean): {
209
242
  httpOnly: true;
210
- secure: true;
243
+ secure: boolean;
211
244
  sameSite: "lax";
212
245
  path: string;
213
246
  maxAge?: number;
214
247
  };
215
248
 
216
- export { type CallbackRouteConfig, DEFAULT_ACCESS_TOKEN_COOKIE_NAME, DEFAULT_ID_TOKEN_COOKIE_NAME, DEFAULT_LOGOUT_STATE_COOKIE_NAME, DEFAULT_REFRESH_TOKEN_COOKIE_NAME, DEFAULT_RETURN_COOKIE_NAME, DEFAULT_STATE_COOKIE_NAME, DEFAULT_VERIFIER_COOKIE_NAME, type LogoutRouteConfig, type SsoMiddlewareConfig, createCallbackRouteHandler, createLogoutRouteHandler, createSsoMiddleware, getHostCookieOptions, getSecureCookieOptions };
249
+ export { type CallbackRouteConfig, DEFAULT_ACCESS_TOKEN_COOKIE_NAME, DEFAULT_ID_TOKEN_COOKIE_NAME, DEFAULT_LOGOUT_STATE_COOKIE_NAME, DEFAULT_REFRESH_TOKEN_COOKIE_NAME, DEFAULT_RETURN_COOKIE_NAME, DEFAULT_STATE_COOKIE_NAME, DEFAULT_VERIFIER_COOKIE_NAME, type LogoutRouteConfig, type SsoMiddlewareConfig, createCallbackRouteHandler, createLogoutRouteHandler, createSsoMiddleware, getHostCookieOptions, getSecureCookieOptions, toInsecureCookieName };
@@ -31,7 +31,8 @@ __export(next_exports, {
31
31
  createLogoutRouteHandler: () => createLogoutRouteHandler,
32
32
  createSsoMiddleware: () => createSsoMiddleware,
33
33
  getHostCookieOptions: () => getHostCookieOptions,
34
- getSecureCookieOptions: () => getSecureCookieOptions
34
+ getSecureCookieOptions: () => getSecureCookieOptions,
35
+ toInsecureCookieName: () => toInsecureCookieName
35
36
  });
36
37
  module.exports = __toCommonJS(next_exports);
37
38
 
@@ -46,19 +47,35 @@ var DEFAULT_STATE_COOKIE_NAME = "__Host-nihplod_sso_state";
46
47
  var DEFAULT_RETURN_COOKIE_NAME = "__Host-nihplod_sso_return";
47
48
  var DEFAULT_VERIFIER_COOKIE_NAME = "__Secure-nihplod_sso_verifier";
48
49
  var DEFAULT_LOGOUT_STATE_COOKIE_NAME = "__Host-nihplod_sso_logout_state";
49
- function getHostCookieOptions(maxAge) {
50
+ function toInsecureCookieName(name) {
51
+ return name.replace(/^__(Host|Secure)-/, "");
52
+ }
53
+ function resolveInsecureLocalDev(enabled, ssoBaseUrl) {
54
+ if (!enabled) return false;
55
+ if (process.env.NODE_ENV === "production" && /^https:\/\//i.test(ssoBaseUrl)) {
56
+ console.warn(
57
+ "[SSO SDK] insecureLocalDev=true \u5DF2\u88AB\u5FFD\u7565\uFF1A\u5F53\u524D\u4E3A\u751F\u4EA7\u73AF\u5883\uFF08NODE_ENV=production\uFF09\u4E14 ssoBaseUrl \u4F7F\u7528 HTTPS\uFF0CCookie \u4ECD\u4FDD\u6301 Secure \u5C5E\u6027\u4E0E __Host-/__Secure- \u524D\u7F00\u3002\u8BF7\u4ECE\u751F\u4EA7\u914D\u7F6E\u4E2D\u79FB\u9664\u8BE5\u5F00\u5173\u3002"
58
+ );
59
+ return false;
60
+ }
61
+ console.warn(
62
+ "[SSO SDK] insecureLocalDev=true\uFF1ACookie \u7684 Secure \u5C5E\u6027\u5DF2\u5173\u95ED\u4E14\u53BB\u9664 __Host-/__Secure- \u524D\u7F00\u3002\u4EC5\u9650 http://localhost \u672C\u5730\u5F00\u53D1\u4F7F\u7528\uFF0C\u751F\u4EA7\u73AF\u5883\u5FC5\u987B\u79FB\u9664\u8BE5\u914D\u7F6E\uFF08\u751F\u4EA7\u5FC5\u987B\u7528 HTTPS\uFF09\u3002"
63
+ );
64
+ return true;
65
+ }
66
+ function getHostCookieOptions(maxAge, secure = true) {
50
67
  return {
51
68
  httpOnly: true,
52
- secure: true,
69
+ secure,
53
70
  sameSite: "lax",
54
71
  path: "/",
55
72
  ...maxAge !== void 0 ? { maxAge } : {}
56
73
  };
57
74
  }
58
- function getSecureCookieOptions(maxAge, path = "/") {
75
+ function getSecureCookieOptions(maxAge, path = "/", secure = true) {
59
76
  return {
60
77
  httpOnly: true,
61
- secure: true,
78
+ secure,
62
79
  sameSite: "lax",
63
80
  path,
64
81
  ...maxAge !== void 0 ? { maxAge } : {}
@@ -176,11 +193,14 @@ function createSsoMiddleware(config) {
176
193
  callbackPath = "/api/auth/callback",
177
194
  ssoCookieName = "__Host-user_token",
178
195
  validateSsoCookie = true,
179
- accessTokenCookieName = DEFAULT_ACCESS_TOKEN_COOKIE_NAME,
180
- stateCookieName = DEFAULT_STATE_COOKIE_NAME,
181
- returnUrlCookieName = DEFAULT_RETURN_COOKIE_NAME,
182
- verifierCookieName = DEFAULT_VERIFIER_COOKIE_NAME
196
+ insecureLocalDev: insecureLocalDevOpt = false
183
197
  } = config;
198
+ const insecureLocalDev = resolveInsecureLocalDev(insecureLocalDevOpt, ssoBaseUrl);
199
+ const secureCookies = !insecureLocalDev;
200
+ const accessTokenCookieName = insecureLocalDev ? toInsecureCookieName(config.accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE_NAME) : config.accessTokenCookieName ?? DEFAULT_ACCESS_TOKEN_COOKIE_NAME;
201
+ const stateCookieName = insecureLocalDev ? toInsecureCookieName(config.stateCookieName ?? DEFAULT_STATE_COOKIE_NAME) : config.stateCookieName ?? DEFAULT_STATE_COOKIE_NAME;
202
+ const returnUrlCookieName = insecureLocalDev ? toInsecureCookieName(config.returnUrlCookieName ?? DEFAULT_RETURN_COOKIE_NAME) : config.returnUrlCookieName ?? DEFAULT_RETURN_COOKIE_NAME;
203
+ const verifierCookieName = insecureLocalDev ? toInsecureCookieName(config.verifierCookieName ?? DEFAULT_VERIFIER_COOKIE_NAME) : config.verifierCookieName ?? DEFAULT_VERIFIER_COOKIE_NAME;
184
204
  const normalizedBase = ssoBaseUrl.replace(/\/+$/, "");
185
205
  if (process.env.NODE_ENV !== "production") {
186
206
  if (!validateSsoCookie) {
@@ -248,12 +268,12 @@ function createSsoMiddleware(config) {
248
268
  const loginUrl = new URL("/api/oauth/authorize", normalizedBase);
249
269
  loginUrl.search = authorizeParams.toString();
250
270
  const response = import_server.NextResponse.redirect(loginUrl);
251
- response.cookies.set(stateCookieName, state, getHostCookieOptions(600));
252
- response.cookies.set(verifierCookieName, verifier, getSecureCookieOptions(600, callbackPath));
271
+ response.cookies.set(stateCookieName, state, getHostCookieOptions(600, secureCookies));
272
+ response.cookies.set(verifierCookieName, verifier, getSecureCookieOptions(600, callbackPath, secureCookies));
253
273
  const safeReturnUrl = (request.nextUrl.pathname + request.nextUrl.search).slice(0, 2048);
254
- response.cookies.set(returnUrlCookieName, safeReturnUrl, getHostCookieOptions(600));
274
+ response.cookies.set(returnUrlCookieName, safeReturnUrl, getHostCookieOptions(600, secureCookies));
255
275
  if (accessTokenCookie?.value) {
256
- response.cookies.set(accessTokenCookieName, "", getHostCookieOptions(0));
276
+ response.cookies.set(accessTokenCookieName, "", getHostCookieOptions(0, secureCookies));
257
277
  }
258
278
  return response;
259
279
  };
@@ -276,6 +296,7 @@ var SsoError = class extends Error {
276
296
  // src/core/security.ts
277
297
  function isTrustedReturnUrl(url, currentOrigin) {
278
298
  if (!url) return false;
299
+ if (url.includes("\\")) return false;
279
300
  if (url.startsWith("/") && !url.startsWith("//")) return true;
280
301
  try {
281
302
  return new URL(url).origin === currentOrigin;
@@ -481,7 +502,7 @@ async function validateIdToken(idToken, accessToken, expectedIssuer, expectedCli
481
502
  if (typeof payload.exp !== "number") {
482
503
  throw new SsoError("id_token_invalid", "ID Token \u7F3A\u5C11 exp \u58F0\u660E");
483
504
  }
484
- if (Date.now() >= payload.exp * 1e3) {
505
+ if (Date.now() >= payload.exp * 1e3 + 6e4) {
485
506
  throw new SsoError("id_token_expired", "ID Token \u5DF2\u8FC7\u671F");
486
507
  }
487
508
  if (typeof payload.iat === "number" && payload.iat * 1e3 > Date.now() + 6e4) {
@@ -507,13 +528,17 @@ function createCallbackRouteHandler(config) {
507
528
  redirectUri,
508
529
  clientSecret,
509
530
  defaultReturnPath = "/",
510
- accessTokenCookieName = DEFAULT_ACCESS_TOKEN_COOKIE_NAME,
511
- refreshTokenCookieName = DEFAULT_REFRESH_TOKEN_COOKIE_NAME,
512
- idTokenCookieName = DEFAULT_ID_TOKEN_COOKIE_NAME,
513
- stateCookieName = DEFAULT_STATE_COOKIE_NAME,
514
- returnUrlCookieName = DEFAULT_RETURN_COOKIE_NAME,
515
- verifierCookieName = DEFAULT_VERIFIER_COOKIE_NAME
531
+ insecureLocalDev: insecureLocalDevOpt = false
516
532
  } = config;
533
+ const insecureLocalDev = resolveInsecureLocalDev(insecureLocalDevOpt, ssoBaseUrl);
534
+ const secureCookies = !insecureLocalDev;
535
+ const pickName = (explicit, fallback) => insecureLocalDev ? toInsecureCookieName(explicit ?? fallback) : explicit ?? fallback;
536
+ const accessTokenCookieName = pickName(config.accessTokenCookieName, DEFAULT_ACCESS_TOKEN_COOKIE_NAME);
537
+ const refreshTokenCookieName = pickName(config.refreshTokenCookieName, DEFAULT_REFRESH_TOKEN_COOKIE_NAME);
538
+ const idTokenCookieName = pickName(config.idTokenCookieName, DEFAULT_ID_TOKEN_COOKIE_NAME);
539
+ const stateCookieName = pickName(config.stateCookieName, DEFAULT_STATE_COOKIE_NAME);
540
+ const returnUrlCookieName = pickName(config.returnUrlCookieName, DEFAULT_RETURN_COOKIE_NAME);
541
+ const verifierCookieName = pickName(config.verifierCookieName, DEFAULT_VERIFIER_COOKIE_NAME);
517
542
  const normalizedBase = ssoBaseUrl.replace(/\/+$/, "");
518
543
  return async function GET(request) {
519
544
  const { searchParams } = request.nextUrl;
@@ -621,6 +646,15 @@ function createCallbackRouteHandler(config) {
621
646
  );
622
647
  }
623
648
  const tokenData = await res.json();
649
+ if (!tokenData.access_token || !tokenData.refresh_token) {
650
+ return import_server2.NextResponse.json(
651
+ {
652
+ error: "server_error",
653
+ error_description: "Token \u54CD\u5E94\u7F3A\u5C11 access_token \u6216 refresh_token"
654
+ },
655
+ { status: 502 }
656
+ );
657
+ }
624
658
  if (tokenData.id_token) {
625
659
  try {
626
660
  await validateIdToken(
@@ -639,15 +673,16 @@ function createCallbackRouteHandler(config) {
639
673
  );
640
674
  }
641
675
  }
676
+ const callbackOrigin = new URL(redirectUri).origin;
642
677
  const rawReturnUrl = request.cookies.get(returnUrlCookieName)?.value || defaultReturnPath;
643
- const returnUrl = isTrustedReturnUrl(rawReturnUrl, request.nextUrl.origin) ? rawReturnUrl : "/";
644
- const response = import_server2.NextResponse.redirect(new URL(returnUrl, request.url));
678
+ const returnUrl = isTrustedReturnUrl(rawReturnUrl, callbackOrigin) ? rawReturnUrl : "/";
679
+ const response = import_server2.NextResponse.redirect(new URL(returnUrl, callbackOrigin));
645
680
  response.cookies.set(accessTokenCookieName, tokenData.access_token, {
646
- ...getHostCookieOptions(tokenData.expires_in)
681
+ ...getHostCookieOptions(tokenData.expires_in, secureCookies)
647
682
  });
648
683
  const refreshMaxAge = tokenData.refresh_expires_in != null ? tokenData.refresh_expires_in : 30 * 24 * 60 * 60;
649
684
  response.cookies.set(refreshTokenCookieName, tokenData.refresh_token, {
650
- ...getHostCookieOptions(refreshMaxAge)
685
+ ...getHostCookieOptions(refreshMaxAge, secureCookies)
651
686
  });
652
687
  if (tokenData.id_token) {
653
688
  let idTokenMaxAge = 3600;
@@ -665,14 +700,14 @@ function createCallbackRouteHandler(config) {
665
700
  }
666
701
  if (idTokenMaxAge > 0) {
667
702
  response.cookies.set(idTokenCookieName, tokenData.id_token, {
668
- ...getHostCookieOptions(idTokenMaxAge)
703
+ ...getHostCookieOptions(idTokenMaxAge, secureCookies)
669
704
  });
670
705
  }
671
706
  }
672
- response.cookies.set(stateCookieName, "", getHostCookieOptions(0));
673
- response.cookies.set(returnUrlCookieName, "", getHostCookieOptions(0));
674
- response.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, "/"));
675
- response.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, request.nextUrl.pathname));
707
+ response.cookies.set(stateCookieName, "", getHostCookieOptions(0, secureCookies));
708
+ response.cookies.set(returnUrlCookieName, "", getHostCookieOptions(0, secureCookies));
709
+ response.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, "/", secureCookies));
710
+ response.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, request.nextUrl.pathname, secureCookies));
676
711
  return response;
677
712
  };
678
713
  }
@@ -717,16 +752,21 @@ function createLogoutRouteHandler(config) {
717
752
  clientSecret,
718
753
  postLogoutRedirectUri = new URL(redirectUri).origin + "/",
719
754
  redirectToSso = true,
720
- accessTokenCookieName = DEFAULT_ACCESS_TOKEN_COOKIE_NAME,
721
- refreshTokenCookieName = DEFAULT_REFRESH_TOKEN_COOKIE_NAME,
722
- idTokenCookieName = DEFAULT_ID_TOKEN_COOKIE_NAME,
723
- stateCookieName = DEFAULT_STATE_COOKIE_NAME,
724
- returnUrlCookieName = DEFAULT_RETURN_COOKIE_NAME,
725
- verifierCookieName = DEFAULT_VERIFIER_COOKIE_NAME,
726
755
  callbackPath = "/api/auth/callback",
727
- logoutStateCookieName = DEFAULT_LOGOUT_STATE_COOKIE_NAME
756
+ insecureLocalDev: insecureLocalDevOpt = false
728
757
  } = config;
758
+ const insecureLocalDev = resolveInsecureLocalDev(insecureLocalDevOpt, ssoBaseUrl);
759
+ const secureCookies = !insecureLocalDev;
760
+ const pickName = (explicit, fallback) => insecureLocalDev ? toInsecureCookieName(explicit ?? fallback) : explicit ?? fallback;
761
+ const accessTokenCookieName = pickName(config.accessTokenCookieName, DEFAULT_ACCESS_TOKEN_COOKIE_NAME);
762
+ const refreshTokenCookieName = pickName(config.refreshTokenCookieName, DEFAULT_REFRESH_TOKEN_COOKIE_NAME);
763
+ const idTokenCookieName = pickName(config.idTokenCookieName, DEFAULT_ID_TOKEN_COOKIE_NAME);
764
+ const stateCookieName = pickName(config.stateCookieName, DEFAULT_STATE_COOKIE_NAME);
765
+ const returnUrlCookieName = pickName(config.returnUrlCookieName, DEFAULT_RETURN_COOKIE_NAME);
766
+ const verifierCookieName = pickName(config.verifierCookieName, DEFAULT_VERIFIER_COOKIE_NAME);
767
+ const logoutStateCookieName = pickName(config.logoutStateCookieName, DEFAULT_LOGOUT_STATE_COOKIE_NAME);
729
768
  const normalizedBase = ssoBaseUrl.replace(/\/+$/, "");
769
+ const callbackOrigin = new URL(redirectUri).origin;
730
770
  return async function handler(request) {
731
771
  const returnedState = request.nextUrl.searchParams.get("state");
732
772
  if (returnedState) {
@@ -737,8 +777,8 @@ function createLogoutRouteHandler(config) {
737
777
  { status: 400 }
738
778
  );
739
779
  }
740
- const res = import_server3.NextResponse.redirect(request.nextUrl.origin + "/");
741
- res.cookies.set(logoutStateCookieName, "", getHostCookieOptions(0));
780
+ const res = import_server3.NextResponse.redirect(callbackOrigin + "/");
781
+ res.cookies.set(logoutStateCookieName, "", getHostCookieOptions(0, secureCookies));
742
782
  return res;
743
783
  }
744
784
  const refreshToken = request.cookies.get(refreshTokenCookieName)?.value;
@@ -764,18 +804,18 @@ function createLogoutRouteHandler(config) {
764
804
  }
765
805
  }
766
806
  const clearCookies = (res) => {
767
- res.cookies.set(accessTokenCookieName, "", getHostCookieOptions(0));
768
- res.cookies.set(refreshTokenCookieName, "", getHostCookieOptions(0));
769
- res.cookies.set(idTokenCookieName, "", getHostCookieOptions(0));
770
- res.cookies.set(stateCookieName, "", getHostCookieOptions(0));
771
- res.cookies.set(returnUrlCookieName, "", getHostCookieOptions(0));
772
- res.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, "/"));
773
- res.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, callbackPath));
807
+ res.cookies.set(accessTokenCookieName, "", getHostCookieOptions(0, secureCookies));
808
+ res.cookies.set(refreshTokenCookieName, "", getHostCookieOptions(0, secureCookies));
809
+ res.cookies.set(idTokenCookieName, "", getHostCookieOptions(0, secureCookies));
810
+ res.cookies.set(stateCookieName, "", getHostCookieOptions(0, secureCookies));
811
+ res.cookies.set(returnUrlCookieName, "", getHostCookieOptions(0, secureCookies));
812
+ res.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, "/", secureCookies));
813
+ res.cookies.set(verifierCookieName, "", getSecureCookieOptions(0, callbackPath, secureCookies));
774
814
  return res;
775
815
  };
776
816
  if (redirectToSso) {
777
817
  const discovery = await fetchDiscovery(normalizedBase);
778
- const endSessionEndpoint = discovery?.end_session_endpoint || `${normalizedBase}/logout`;
818
+ const endSessionEndpoint = discovery?.end_session_endpoint || `${normalizedBase}/api/oauth/end-session`;
779
819
  const logoutUrl = new URL(endSessionEndpoint);
780
820
  logoutUrl.searchParams.set("client_id", clientId);
781
821
  logoutUrl.searchParams.set(
@@ -788,11 +828,11 @@ function createLogoutRouteHandler(config) {
788
828
  const logoutState = generateRandomString2(32);
789
829
  logoutUrl.searchParams.set("state", logoutState);
790
830
  const res = clearCookies(import_server3.NextResponse.redirect(logoutUrl.toString()));
791
- res.cookies.set(logoutStateCookieName, logoutState, getHostCookieOptions(600));
831
+ res.cookies.set(logoutStateCookieName, logoutState, getHostCookieOptions(600, secureCookies));
792
832
  return res;
793
833
  }
794
834
  return clearCookies(
795
- import_server3.NextResponse.redirect(request.nextUrl.origin + "/")
835
+ import_server3.NextResponse.redirect(callbackOrigin + "/")
796
836
  );
797
837
  };
798
838
  }
@@ -809,6 +849,7 @@ function createLogoutRouteHandler(config) {
809
849
  createLogoutRouteHandler,
810
850
  createSsoMiddleware,
811
851
  getHostCookieOptions,
812
- getSecureCookieOptions
852
+ getSecureCookieOptions,
853
+ toInsecureCookieName
813
854
  });
814
855
  //# sourceMappingURL=index.js.map