strapi-plugin-oidc 1.2.4 → 1.3.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.
@@ -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);
@@ -105,6 +89,21 @@ async function bootstrap({ strapi: strapi2 }) {
105
89
  }
106
90
  ];
107
91
  await strapi2.admin.services.permission.actionProvider.registerMany(actions);
92
+ const enforceOIDCConfig = getEnforceOIDCConfig(strapi2);
93
+ if (enforceOIDCConfig !== null) {
94
+ try {
95
+ const whitelistService2 = strapi2.plugin("strapi-plugin-oidc").service("whitelist");
96
+ const settings = await whitelistService2.getSettings();
97
+ if (settings.enforceOIDC !== enforceOIDCConfig) {
98
+ await whitelistService2.setSettings({ ...settings, enforceOIDC: enforceOIDCConfig });
99
+ strapi2.log.info(
100
+ `[strapi-plugin-oidc] OIDC_ENFORCE=${enforceOIDCConfig} written to database settings`
101
+ );
102
+ }
103
+ } catch (err) {
104
+ strapi2.log.error("[strapi-plugin-oidc] Failed to sync OIDC_ENFORCE to database:", err);
105
+ }
106
+ }
108
107
  try {
109
108
  const oidcRoleCount = await strapi2.query("plugin::strapi-plugin-oidc.roles").count({
110
109
  where: { oauth_type: "4" }
@@ -152,8 +151,6 @@ function destroy() {
152
151
  const config = {
153
152
  default: {
154
153
  REMEMBER_ME: false,
155
- REMEMBER_ME_DAYS: 30,
156
- // 30 days
157
154
  OIDC_REDIRECT_URI: "http://localhost:1337/strapi-plugin-oidc/oidc/callback",
158
155
  OIDC_CLIENT_ID: "",
159
156
  OIDC_CLIENT_SECRET: "",
@@ -165,7 +162,10 @@ const config = {
165
162
  OIDC_GRANT_TYPE: "authorization_code",
166
163
  OIDC_FAMILY_NAME_FIELD: "family_name",
167
164
  OIDC_GIVEN_NAME_FIELD: "given_name",
168
- OIDC_LOGOUT_URL: ""
165
+ OIDC_LOGOUT_URL: "",
166
+ OIDC_SSO_BUTTON_TEXT: "Login via SSO",
167
+ OIDC_ENFORCE: null
168
+ // null = use DB setting; true/false = override DB (useful for lockout recovery)
169
169
  },
170
170
  validator() {
171
171
  }
@@ -200,6 +200,23 @@ const contentTypes = {
200
200
  roles,
201
201
  whitelists
202
202
  };
203
+ function getExpiredCookieOptions(strapi2, ctx) {
204
+ const isProduction = strapi2.config.get("environment") === "production";
205
+ return {
206
+ httpOnly: true,
207
+ secure: isProduction && ctx.request.secure,
208
+ path: strapi2.config.get("admin.auth.cookie.path", "/admin"),
209
+ domain: strapi2.config.get("admin.auth.cookie.domain") || strapi2.config.get("admin.auth.domain"),
210
+ sameSite: strapi2.config.get("admin.auth.cookie.sameSite", "lax"),
211
+ maxAge: 0,
212
+ expires: /* @__PURE__ */ new Date(0)
213
+ };
214
+ }
215
+ function clearAuthCookies(strapi2, ctx) {
216
+ const options2 = getExpiredCookieOptions(strapi2, ctx);
217
+ ctx.cookies.set("strapi_admin_refresh", "", options2);
218
+ ctx.cookies.set("oidc_authenticated", "", { ...options2, path: "/" });
219
+ }
203
220
  function configValidation() {
204
221
  const config2 = strapi.config.get("plugin::strapi-plugin-oidc");
205
222
  const requiredKeys = [
@@ -339,6 +356,8 @@ async function oidcSignInCallback(ctx) {
339
356
  }
340
357
  const oidcState = ctx.cookies.get("oidc_state");
341
358
  const codeVerifier = ctx.cookies.get("oidc_code_verifier");
359
+ ctx.cookies.set("oidc_state", null);
360
+ ctx.cookies.set("oidc_code_verifier", null);
342
361
  if (!ctx.query.state || ctx.query.state !== oidcState) {
343
362
  return ctx.send(oauthService2.renderSignUpError("Invalid state"));
344
363
  }
@@ -419,14 +438,13 @@ async function info(ctx) {
419
438
  const whitelistUsers = await whitelistService2.getUsers();
420
439
  ctx.body = {
421
440
  useWhitelist: settings.useWhitelist,
422
- enforceOIDC: settings.enforceOIDC || false,
423
- showSSOButton: settings.showSSOButton !== false,
424
- ssoButtonText: settings.ssoButtonText || "Login via SSO",
441
+ enforceOIDC: resolveEnforceOIDC(strapi, settings.enforceOIDC),
442
+ enforceOIDCConfig: getEnforceOIDCConfig(strapi),
425
443
  whitelistUsers
426
444
  };
427
445
  }
428
446
  async function updateSettings(ctx) {
429
- let { useWhitelist, enforceOIDC, showSSOButton, ssoButtonText } = ctx.request.body;
447
+ let { useWhitelist, enforceOIDC } = ctx.request.body;
430
448
  const whitelistService2 = strapi.plugin("strapi-plugin-oidc").service("whitelist");
431
449
  if (useWhitelist && enforceOIDC) {
432
450
  const users = await whitelistService2.getUsers();
@@ -434,16 +452,16 @@ async function updateSettings(ctx) {
434
452
  enforceOIDC = false;
435
453
  }
436
454
  }
437
- await whitelistService2.setSettings({ useWhitelist, enforceOIDC, showSSOButton, ssoButtonText });
438
- ctx.body = { useWhitelist, enforceOIDC, showSSOButton, ssoButtonText };
455
+ await whitelistService2.setSettings({ useWhitelist, enforceOIDC });
456
+ ctx.body = { useWhitelist, enforceOIDC };
439
457
  }
440
458
  async function publicSettings(ctx) {
441
459
  const whitelistService2 = strapi.plugin("strapi-plugin-oidc").service("whitelist");
442
460
  const settings = await whitelistService2.getSettings();
461
+ const config2 = strapi.config.get("plugin::strapi-plugin-oidc");
443
462
  ctx.body = {
444
- enforceOIDC: settings.enforceOIDC || false,
445
- showSSOButton: settings.showSSOButton !== false,
446
- ssoButtonText: settings.ssoButtonText || "Login via SSO"
463
+ enforceOIDC: resolveEnforceOIDC(strapi, settings.enforceOIDC),
464
+ ssoButtonText: config2.OIDC_SSO_BUTTON_TEXT
447
465
  };
448
466
  }
449
467
  async function register(ctx) {
@@ -928,13 +946,11 @@ function oauthService({ strapi: strapi2 }) {
928
946
  const config2 = strapi2.config.get("plugin::strapi-plugin-oidc");
929
947
  const REMEMBER_ME = config2["REMEMBER_ME"];
930
948
  const rememberMe = !!REMEMBER_ME;
931
- const { token: refreshToken } = await sessionManager("admin").generateRefreshToken(
932
- userId,
933
- deviceId,
934
- {
935
- type: rememberMe ? "refresh" : "session"
936
- }
937
- );
949
+ const { token: refreshToken, absoluteExpiresAt } = await sessionManager(
950
+ "admin"
951
+ ).generateRefreshToken(userId, deviceId, {
952
+ type: rememberMe ? "refresh" : "session"
953
+ });
938
954
  const isProduction = strapi2.config.get("environment") === "production";
939
955
  const domain = strapi2.config.get("admin.auth.cookie.domain") || strapi2.config.get("admin.auth.domain");
940
956
  const path = strapi2.config.get("admin.auth.cookie.path", "/admin");
@@ -948,10 +964,16 @@ function oauthService({ strapi: strapi2 }) {
948
964
  sameSite
949
965
  };
950
966
  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);
967
+ const idleLifespanSec = strapi2.config.get(
968
+ "admin.auth.sessions.idleRefreshTokenLifespan",
969
+ 1209600
970
+ // 14 days Strapi default
971
+ );
972
+ const idleMs = idleLifespanSec * 1e3;
973
+ const absoluteMs = new Date(absoluteExpiresAt).getTime() - Date.now();
974
+ const ms = Math.min(idleMs, absoluteMs);
975
+ cookieOptions.maxAge = ms;
976
+ cookieOptions.expires = new Date(Date.now() + ms);
955
977
  }
956
978
  ctx.cookies.set("strapi_admin_refresh", refreshToken, cookieOptions);
957
979
  ctx.cookies.set("oidc_authenticated", "1", { ...cookieOptions, path: "/" });
@@ -1027,9 +1049,7 @@ function whitelistService({ strapi: strapi2 }) {
1027
1049
  if (!settings) {
1028
1050
  settings = {
1029
1051
  useWhitelist: true,
1030
- enforceOIDC: false,
1031
- showSSOButton: true,
1032
- ssoButtonText: "Login via SSO"
1052
+ enforceOIDC: false
1033
1053
  };
1034
1054
  await getPluginStore().set({ key: "settings", value: settings });
1035
1055
  }
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.2",
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",