strapi-plugin-oidc 1.2.4 → 1.3.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.
@@ -4,22 +4,19 @@ import strapiUtils from "@strapi/utils";
4
4
  import generator from "generate-password";
5
5
  function register$1() {
6
6
  }
7
- function getExpiredCookieOptions(strapi2, ctx) {
8
- const isProduction = strapi2.config.get("environment") === "production";
9
- return {
10
- httpOnly: true,
11
- secure: isProduction && ctx.request.secure,
12
- path: strapi2.config.get("admin.auth.cookie.path", "/admin"),
13
- domain: strapi2.config.get("admin.auth.cookie.domain") || strapi2.config.get("admin.auth.domain"),
14
- sameSite: strapi2.config.get("admin.auth.cookie.sameSite", "lax"),
15
- maxAge: 0,
16
- expires: /* @__PURE__ */ new Date(0)
17
- };
7
+ function getEnforceOIDCConfig(strapi2) {
8
+ const config2 = strapi2.config.get("plugin::strapi-plugin-oidc");
9
+ const val = config2.OIDC_ENFORCE;
10
+ if (val === null || val === void 0) return null;
11
+ if (typeof val === "boolean") return val;
12
+ if (val === "true") return true;
13
+ if (val === "false") return false;
14
+ return null;
18
15
  }
19
- function clearAuthCookies(strapi2, ctx) {
20
- const options2 = getExpiredCookieOptions(strapi2, ctx);
21
- ctx.cookies.set("strapi_admin_refresh", "", options2);
22
- ctx.cookies.set("oidc_authenticated", "", { ...options2, path: "/" });
16
+ function resolveEnforceOIDC(strapi2, dbValue) {
17
+ const configValue = getEnforceOIDCConfig(strapi2);
18
+ if (configValue !== null) return configValue;
19
+ return dbValue ?? false;
23
20
  }
24
21
  async function bootstrap({ strapi: strapi2 }) {
25
22
  const enforceOidcMiddleware = async (ctx, next) => {
@@ -32,13 +29,12 @@ async function bootstrap({ strapi: strapi2 }) {
32
29
  ];
33
30
  const isPostAuth = authRoutes.includes(ctx.request.path) && ctx.request.method === "POST";
34
31
  const isTokenRefresh = ctx.request.path === `${adminUrl}/token/refresh` && ctx.request.method === "POST";
35
- const isHtmlRequest = ctx.request.accepts("html", "json") === "html" && !ctx.request.path.match(/\.[a-zA-Z0-9]+$/);
36
- const isGetAdminHtml = ctx.request.method === "GET" && ctx.request.path.startsWith(adminUrl) && isHtmlRequest;
37
- if (isPostAuth || isTokenRefresh || isGetAdminHtml) {
32
+ if (isPostAuth || isTokenRefresh) {
38
33
  try {
39
34
  const whitelistService2 = strapi2.plugin("strapi-plugin-oidc").service("whitelist");
40
35
  const settings = await whitelistService2.getSettings();
41
- if (settings?.enforceOIDC) {
36
+ const enforceOIDC = resolveEnforceOIDC(strapi2, settings?.enforceOIDC);
37
+ if (enforceOIDC) {
42
38
  if (isPostAuth) {
43
39
  ctx.status = 403;
44
40
  ctx.body = {
@@ -66,18 +62,6 @@ async function bootstrap({ strapi: strapi2 }) {
66
62
  };
67
63
  return;
68
64
  }
69
- if (isGetAdminHtml) {
70
- const hasRefreshCookie = !!ctx.cookies.get("strapi_admin_refresh");
71
- if (hasRefreshCookie && !hasOidcSession) {
72
- clearAuthCookies(strapi2, ctx);
73
- ctx.redirect("/strapi-plugin-oidc/oidc");
74
- return;
75
- }
76
- if (!hasRefreshCookie) {
77
- ctx.redirect("/strapi-plugin-oidc/oidc");
78
- return;
79
- }
80
- }
81
65
  }
82
66
  } catch (err) {
83
67
  strapi2.log.error("Error checking OIDC enforcement in middleware:", err);
@@ -152,8 +136,6 @@ function destroy() {
152
136
  const config = {
153
137
  default: {
154
138
  REMEMBER_ME: false,
155
- REMEMBER_ME_DAYS: 30,
156
- // 30 days
157
139
  OIDC_REDIRECT_URI: "http://localhost:1337/strapi-plugin-oidc/oidc/callback",
158
140
  OIDC_CLIENT_ID: "",
159
141
  OIDC_CLIENT_SECRET: "",
@@ -165,7 +147,10 @@ const config = {
165
147
  OIDC_GRANT_TYPE: "authorization_code",
166
148
  OIDC_FAMILY_NAME_FIELD: "family_name",
167
149
  OIDC_GIVEN_NAME_FIELD: "given_name",
168
- OIDC_LOGOUT_URL: ""
150
+ OIDC_LOGOUT_URL: "",
151
+ OIDC_SSO_BUTTON_TEXT: "Login via SSO",
152
+ OIDC_ENFORCE: null
153
+ // null = use DB setting; true/false = override DB (useful for lockout recovery)
169
154
  },
170
155
  validator() {
171
156
  }
@@ -200,6 +185,23 @@ const contentTypes = {
200
185
  roles,
201
186
  whitelists
202
187
  };
188
+ function getExpiredCookieOptions(strapi2, ctx) {
189
+ const isProduction = strapi2.config.get("environment") === "production";
190
+ return {
191
+ httpOnly: true,
192
+ secure: isProduction && ctx.request.secure,
193
+ path: strapi2.config.get("admin.auth.cookie.path", "/admin"),
194
+ domain: strapi2.config.get("admin.auth.cookie.domain") || strapi2.config.get("admin.auth.domain"),
195
+ sameSite: strapi2.config.get("admin.auth.cookie.sameSite", "lax"),
196
+ maxAge: 0,
197
+ expires: /* @__PURE__ */ new Date(0)
198
+ };
199
+ }
200
+ function clearAuthCookies(strapi2, ctx) {
201
+ const options2 = getExpiredCookieOptions(strapi2, ctx);
202
+ ctx.cookies.set("strapi_admin_refresh", "", options2);
203
+ ctx.cookies.set("oidc_authenticated", "", { ...options2, path: "/" });
204
+ }
203
205
  function configValidation() {
204
206
  const config2 = strapi.config.get("plugin::strapi-plugin-oidc");
205
207
  const requiredKeys = [
@@ -339,6 +341,8 @@ async function oidcSignInCallback(ctx) {
339
341
  }
340
342
  const oidcState = ctx.cookies.get("oidc_state");
341
343
  const codeVerifier = ctx.cookies.get("oidc_code_verifier");
344
+ ctx.cookies.set("oidc_state", null);
345
+ ctx.cookies.set("oidc_code_verifier", null);
342
346
  if (!ctx.query.state || ctx.query.state !== oidcState) {
343
347
  return ctx.send(oauthService2.renderSignUpError("Invalid state"));
344
348
  }
@@ -419,14 +423,13 @@ async function info(ctx) {
419
423
  const whitelistUsers = await whitelistService2.getUsers();
420
424
  ctx.body = {
421
425
  useWhitelist: settings.useWhitelist,
422
- enforceOIDC: settings.enforceOIDC || false,
423
- showSSOButton: settings.showSSOButton !== false,
424
- ssoButtonText: settings.ssoButtonText || "Login via SSO",
426
+ enforceOIDC: resolveEnforceOIDC(strapi, settings.enforceOIDC),
427
+ enforceOIDCConfig: getEnforceOIDCConfig(strapi),
425
428
  whitelistUsers
426
429
  };
427
430
  }
428
431
  async function updateSettings(ctx) {
429
- let { useWhitelist, enforceOIDC, showSSOButton, ssoButtonText } = ctx.request.body;
432
+ let { useWhitelist, enforceOIDC } = ctx.request.body;
430
433
  const whitelistService2 = strapi.plugin("strapi-plugin-oidc").service("whitelist");
431
434
  if (useWhitelist && enforceOIDC) {
432
435
  const users = await whitelistService2.getUsers();
@@ -434,16 +437,16 @@ async function updateSettings(ctx) {
434
437
  enforceOIDC = false;
435
438
  }
436
439
  }
437
- await whitelistService2.setSettings({ useWhitelist, enforceOIDC, showSSOButton, ssoButtonText });
438
- ctx.body = { useWhitelist, enforceOIDC, showSSOButton, ssoButtonText };
440
+ await whitelistService2.setSettings({ useWhitelist, enforceOIDC });
441
+ ctx.body = { useWhitelist, enforceOIDC };
439
442
  }
440
443
  async function publicSettings(ctx) {
441
444
  const whitelistService2 = strapi.plugin("strapi-plugin-oidc").service("whitelist");
442
445
  const settings = await whitelistService2.getSettings();
446
+ const config2 = strapi.config.get("plugin::strapi-plugin-oidc");
443
447
  ctx.body = {
444
- enforceOIDC: settings.enforceOIDC || false,
445
- showSSOButton: settings.showSSOButton !== false,
446
- ssoButtonText: settings.ssoButtonText || "Login via SSO"
448
+ enforceOIDC: resolveEnforceOIDC(strapi, settings.enforceOIDC),
449
+ ssoButtonText: config2.OIDC_SSO_BUTTON_TEXT
447
450
  };
448
451
  }
449
452
  async function register(ctx) {
@@ -928,13 +931,11 @@ function oauthService({ strapi: strapi2 }) {
928
931
  const config2 = strapi2.config.get("plugin::strapi-plugin-oidc");
929
932
  const REMEMBER_ME = config2["REMEMBER_ME"];
930
933
  const rememberMe = !!REMEMBER_ME;
931
- const { token: refreshToken } = await sessionManager("admin").generateRefreshToken(
932
- userId,
933
- deviceId,
934
- {
935
- type: rememberMe ? "refresh" : "session"
936
- }
937
- );
934
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager(
935
+ "admin"
936
+ ).generateRefreshToken(userId, deviceId, {
937
+ type: rememberMe ? "refresh" : "session"
938
+ });
938
939
  const isProduction = strapi2.config.get("environment") === "production";
939
940
  const domain = strapi2.config.get("admin.auth.cookie.domain") || strapi2.config.get("admin.auth.domain");
940
941
  const path = strapi2.config.get("admin.auth.cookie.path", "/admin");
@@ -948,10 +949,16 @@ function oauthService({ strapi: strapi2 }) {
948
949
  sameSite
949
950
  };
950
951
  if (rememberMe) {
951
- const REMEMBER_ME_DAYS = config2["REMEMBER_ME_DAYS"] || 30;
952
- const durationInMs = REMEMBER_ME_DAYS * 24 * 60 * 60 * 1e3;
953
- cookieOptions.maxAge = durationInMs;
954
- cookieOptions.expires = new Date(Date.now() + durationInMs);
952
+ const idleLifespanSec = strapi2.config.get(
953
+ "admin.auth.sessions.idleRefreshTokenLifespan",
954
+ 1209600
955
+ // 14 days Strapi default
956
+ );
957
+ const idleMs = idleLifespanSec * 1e3;
958
+ const absoluteMs = new Date(absoluteExpiresAt).getTime() - Date.now();
959
+ const ms = Math.min(idleMs, absoluteMs);
960
+ cookieOptions.maxAge = ms;
961
+ cookieOptions.expires = new Date(Date.now() + ms);
955
962
  }
956
963
  ctx.cookies.set("strapi_admin_refresh", refreshToken, cookieOptions);
957
964
  ctx.cookies.set("oidc_authenticated", "1", { ...cookieOptions, path: "/" });
@@ -1027,9 +1034,7 @@ function whitelistService({ strapi: strapi2 }) {
1027
1034
  if (!settings) {
1028
1035
  settings = {
1029
1036
  useWhitelist: true,
1030
- enforceOIDC: false,
1031
- showSSOButton: true,
1032
- ssoButtonText: "Login via SSO"
1037
+ enforceOIDC: false
1033
1038
  };
1034
1039
  await getPluginStore().set({ key: "settings", value: settings });
1035
1040
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-oidc",
3
- "version": "1.2.4",
3
+ "version": "1.3.1",
4
4
  "description": "A Strapi plugin that provides OpenID Connect (OIDC) authentication functionality for the Strapi Admin Panel.",
5
5
  "strapi": {
6
6
  "displayName": "OIDC Plugin",
@@ -86,7 +86,6 @@
86
86
  "msw": "^2.13.0",
87
87
  "prettier": "^3.8.1",
88
88
  "react": "^18.3.1",
89
- "react-dom": "^18.3.1",
90
89
  "react-router-dom": "^6.30.3",
91
90
  "styled-components": "^6.3.12",
92
91
  "supertest": "^7.2.2",