strapi-plugin-oidc 1.9.3 → 1.9.5

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/README.md CHANGED
@@ -32,7 +32,7 @@ module.exports = ({ env }) => ({
32
32
  enabled: true,
33
33
  config: {
34
34
  // Required
35
- OIDC_DISCOVERY_URL: env('OIDC_DISCOVERY_URL'), // https://your-provider/.well-known/openid-configuration
35
+ OIDC_ISSUER: env('OIDC_ISSUER'), // https://your-provider or https://your-provider/realms/your-realm
36
36
  OIDC_CLIENT_ID: env('OIDC_CLIENT_ID'),
37
37
  OIDC_CLIENT_SECRET: env('OIDC_CLIENT_SECRET'),
38
38
  OIDC_REDIRECT_URI: env('OIDC_REDIRECT_URI'), // https://your-strapi.com/strapi-plugin-oidc/oidc/callback
@@ -55,7 +55,7 @@ module.exports = ({ env }) => ({
55
55
  });
56
56
  ```
57
57
 
58
- `OIDC_DISCOVERY_URL` is the URL of your provider's OpenID Connect discovery document (`/.well-known/openid-configuration`). The plugin fetches it at startup and automatically configures all endpoints, JWKS URI, and issuer.
58
+ `OIDC_ISSUER` is your provider's issuer URL (e.g. `https://auth.example.com` or `https://auth.example.com/realms/myrealm`). The plugin appends `/.well-known/openid-configuration` automatically if not present, and fetches the discovery document at startup to configure all endpoints, JWKS URI, and canonical issuer.
59
59
 
60
60
  ### Security features
61
61
 
@@ -59,7 +59,8 @@ const errorMessages = {
59
59
  WHITELIST_NOT_PRESENT: "Not present in whitelist",
60
60
  PROVIDER_RESPONSE_INVALID: "Unexpected response from OIDC provider",
61
61
  SESSION_MANAGER_UNSUPPORTED: "sessionManager is not supported. Please upgrade to Strapi v5.24.1 or later.",
62
- JWKS_URI_NOT_CONFIGURED: "[OIDC] OIDC_JWKS_URI is not configured — ID token signature verification is disabled. Set OIDC_JWKS_URI and OIDC_ISSUER from your provider's discovery document.",
62
+ OIDC_ISSUER_NOT_CONFIGURED: "[strapi-plugin-oidc] OIDC_ISSUER is not configured — discovery skipped. OIDC sign-in will fail until OIDC_ISSUER is set in your plugin config.",
63
+ JWKS_URI_NOT_CONFIGURED: "[strapi-plugin-oidc] OIDC_JWKS_URI is not configured — ID token signature verification is disabled. Set OIDC_JWKS_URI and OIDC_ISSUER from your provider's discovery document.",
63
64
  ENFORCE_MIDDLEWARE_ERROR: "Error checking OIDC enforcement in middleware:",
64
65
  ENFORCE_SYNC_ERROR: "[strapi-plugin-oidc] Failed to sync OIDC_ENFORCE to database:",
65
66
  DEFAULT_ROLE_INIT_ERROR: "Could not initialize default OIDC role:",
@@ -102,7 +103,6 @@ const coerceBoolNullable = zod.z.preprocess(
102
103
  );
103
104
  const pluginConfigSchema = zod.z.object({
104
105
  REMEMBER_ME: coerceBool(false),
105
- OIDC_DISCOVERY_URL: zod.z.string().default(""),
106
106
  OIDC_REDIRECT_URI: zod.z.string().default(""),
107
107
  OIDC_CLIENT_ID: zod.z.string().default(""),
108
108
  OIDC_CLIENT_SECRET: zod.z.string().default(""),
@@ -172,6 +172,7 @@ const CACHE_TTL = {
172
172
  const DEFAULT_RETENTION_DAYS = 90;
173
173
  const DAY_MS = 864e5;
174
174
  const DISCOVERY_TIMEOUT_MS = 5e3;
175
+ const OIDC_DISCOVERY_PATH = "/.well-known/openid-configuration";
175
176
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
176
177
  function getPluginConfig() {
177
178
  return pluginConfigSchema.parse(strapi.config.get("plugin::strapi-plugin-oidc") ?? {});
@@ -198,7 +199,6 @@ const discoveryDocumentSchema = zod.z.object({
198
199
  jwks_uri: zod.z.string().optional()
199
200
  }).passthrough();
200
201
  const FIELD_MAP = [
201
- ["issuer", "OIDC_ISSUER"],
202
202
  ["authorization_endpoint", "OIDC_AUTHORIZATION_ENDPOINT"],
203
203
  ["token_endpoint", "OIDC_TOKEN_ENDPOINT"],
204
204
  ["userinfo_endpoint", "OIDC_USERINFO_ENDPOINT"],
@@ -207,8 +207,20 @@ const FIELD_MAP = [
207
207
  ];
208
208
  async function applyDiscovery(strapi2) {
209
209
  const config2 = strapi2.config.get("plugin::strapi-plugin-oidc");
210
- const discoveryUrl = config2.OIDC_DISCOVERY_URL;
211
- if (!discoveryUrl) return;
210
+ const issuer = config2.OIDC_ISSUER;
211
+ if (!issuer) {
212
+ strapi2.log.warn(errorMessages.OIDC_ISSUER_NOT_CONFIGURED);
213
+ return;
214
+ }
215
+ let discoveryUrl;
216
+ let canonicalIssuer;
217
+ if (issuer.includes(OIDC_DISCOVERY_PATH)) {
218
+ discoveryUrl = issuer;
219
+ canonicalIssuer = issuer.replace(OIDC_DISCOVERY_PATH, "");
220
+ } else {
221
+ discoveryUrl = issuer.replace(/\/$/, "") + OIDC_DISCOVERY_PATH;
222
+ canonicalIssuer = issuer.replace(/\/$/, "");
223
+ }
212
224
  let doc;
213
225
  try {
214
226
  const res = await fetch(discoveryUrl, { signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS) });
@@ -222,13 +234,13 @@ async function applyDiscovery(strapi2) {
222
234
  );
223
235
  return;
224
236
  }
225
- const updates = {};
237
+ const updates = { OIDC_ISSUER: canonicalIssuer };
226
238
  for (const [docField, configKey] of FIELD_MAP) {
227
239
  if (doc[docField]) {
228
240
  updates[configKey] = doc[docField];
229
241
  }
230
242
  }
231
- if (Object.keys(updates).length > 0) {
243
+ if (Object.keys(updates).length > 1) {
232
244
  strapi2.config.set("plugin::strapi-plugin-oidc", { ...config2, ...updates });
233
245
  strapi2.log.info(`[strapi-plugin-oidc] Discovery applied: ${Object.keys(updates).join(", ")}`);
234
246
  }
@@ -385,7 +397,6 @@ function destroy() {
385
397
  const config = {
386
398
  default: {
387
399
  REMEMBER_ME: false,
388
- OIDC_DISCOVERY_URL: "",
389
400
  OIDC_REDIRECT_URI: "http://localhost:1337/strapi-plugin-oidc/oidc/callback",
390
401
  OIDC_CLIENT_ID: "",
391
402
  OIDC_CLIENT_SECRET: "",
@@ -401,7 +412,7 @@ const config = {
401
412
  OIDC_REQUIRE_EMAIL_VERIFIED: true,
402
413
  OIDC_TRUSTED_IP_HEADER: "",
403
414
  OIDC_FORCE_SECURE_COOKIES: false,
404
- // Populated at bootstrap from OIDC_DISCOVERY_URL — not user-configurable directly
415
+ // Populated at bootstrap from OIDC_ISSUER — not user-configurable directly
405
416
  OIDC_AUTHORIZATION_ENDPOINT: "",
406
417
  OIDC_TOKEN_ENDPOINT: "",
407
418
  OIDC_USERINFO_ENDPOINT: "",
@@ -522,14 +533,14 @@ function toMessage(e) {
522
533
  return e instanceof Error ? e.message : String(e);
523
534
  }
524
535
  const REQUIRED_CONFIG_KEYS = [
525
- "OIDC_DISCOVERY_URL",
536
+ "OIDC_ISSUER",
526
537
  "OIDC_CLIENT_ID",
527
538
  "OIDC_CLIENT_SECRET",
528
539
  "OIDC_REDIRECT_URI",
529
540
  "OIDC_SCOPE",
530
541
  "OIDC_FAMILY_NAME_FIELD",
531
542
  "OIDC_GIVEN_NAME_FIELD",
532
- // Populated at bootstrap from OIDC_DISCOVERY_URL — checked here as a runtime safety net
543
+ // Populated at bootstrap from OIDC_ISSUER — checked here as a runtime safety net
533
544
  "OIDC_TOKEN_ENDPOINT",
534
545
  "OIDC_USERINFO_ENDPOINT",
535
546
  "OIDC_AUTHORIZATION_ENDPOINT"
@@ -53,7 +53,8 @@ const errorMessages = {
53
53
  WHITELIST_NOT_PRESENT: "Not present in whitelist",
54
54
  PROVIDER_RESPONSE_INVALID: "Unexpected response from OIDC provider",
55
55
  SESSION_MANAGER_UNSUPPORTED: "sessionManager is not supported. Please upgrade to Strapi v5.24.1 or later.",
56
- JWKS_URI_NOT_CONFIGURED: "[OIDC] OIDC_JWKS_URI is not configured — ID token signature verification is disabled. Set OIDC_JWKS_URI and OIDC_ISSUER from your provider's discovery document.",
56
+ OIDC_ISSUER_NOT_CONFIGURED: "[strapi-plugin-oidc] OIDC_ISSUER is not configured — discovery skipped. OIDC sign-in will fail until OIDC_ISSUER is set in your plugin config.",
57
+ JWKS_URI_NOT_CONFIGURED: "[strapi-plugin-oidc] OIDC_JWKS_URI is not configured — ID token signature verification is disabled. Set OIDC_JWKS_URI and OIDC_ISSUER from your provider's discovery document.",
57
58
  ENFORCE_MIDDLEWARE_ERROR: "Error checking OIDC enforcement in middleware:",
58
59
  ENFORCE_SYNC_ERROR: "[strapi-plugin-oidc] Failed to sync OIDC_ENFORCE to database:",
59
60
  DEFAULT_ROLE_INIT_ERROR: "Could not initialize default OIDC role:",
@@ -96,7 +97,6 @@ const coerceBoolNullable = z.preprocess(
96
97
  );
97
98
  const pluginConfigSchema = z.object({
98
99
  REMEMBER_ME: coerceBool(false),
99
- OIDC_DISCOVERY_URL: z.string().default(""),
100
100
  OIDC_REDIRECT_URI: z.string().default(""),
101
101
  OIDC_CLIENT_ID: z.string().default(""),
102
102
  OIDC_CLIENT_SECRET: z.string().default(""),
@@ -166,6 +166,7 @@ const CACHE_TTL = {
166
166
  const DEFAULT_RETENTION_DAYS = 90;
167
167
  const DAY_MS = 864e5;
168
168
  const DISCOVERY_TIMEOUT_MS = 5e3;
169
+ const OIDC_DISCOVERY_PATH = "/.well-known/openid-configuration";
169
170
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
170
171
  function getPluginConfig() {
171
172
  return pluginConfigSchema.parse(strapi.config.get("plugin::strapi-plugin-oidc") ?? {});
@@ -192,7 +193,6 @@ const discoveryDocumentSchema = z.object({
192
193
  jwks_uri: z.string().optional()
193
194
  }).passthrough();
194
195
  const FIELD_MAP = [
195
- ["issuer", "OIDC_ISSUER"],
196
196
  ["authorization_endpoint", "OIDC_AUTHORIZATION_ENDPOINT"],
197
197
  ["token_endpoint", "OIDC_TOKEN_ENDPOINT"],
198
198
  ["userinfo_endpoint", "OIDC_USERINFO_ENDPOINT"],
@@ -201,8 +201,20 @@ const FIELD_MAP = [
201
201
  ];
202
202
  async function applyDiscovery(strapi2) {
203
203
  const config2 = strapi2.config.get("plugin::strapi-plugin-oidc");
204
- const discoveryUrl = config2.OIDC_DISCOVERY_URL;
205
- if (!discoveryUrl) return;
204
+ const issuer = config2.OIDC_ISSUER;
205
+ if (!issuer) {
206
+ strapi2.log.warn(errorMessages.OIDC_ISSUER_NOT_CONFIGURED);
207
+ return;
208
+ }
209
+ let discoveryUrl;
210
+ let canonicalIssuer;
211
+ if (issuer.includes(OIDC_DISCOVERY_PATH)) {
212
+ discoveryUrl = issuer;
213
+ canonicalIssuer = issuer.replace(OIDC_DISCOVERY_PATH, "");
214
+ } else {
215
+ discoveryUrl = issuer.replace(/\/$/, "") + OIDC_DISCOVERY_PATH;
216
+ canonicalIssuer = issuer.replace(/\/$/, "");
217
+ }
206
218
  let doc;
207
219
  try {
208
220
  const res = await fetch(discoveryUrl, { signal: AbortSignal.timeout(DISCOVERY_TIMEOUT_MS) });
@@ -216,13 +228,13 @@ async function applyDiscovery(strapi2) {
216
228
  );
217
229
  return;
218
230
  }
219
- const updates = {};
231
+ const updates = { OIDC_ISSUER: canonicalIssuer };
220
232
  for (const [docField, configKey] of FIELD_MAP) {
221
233
  if (doc[docField]) {
222
234
  updates[configKey] = doc[docField];
223
235
  }
224
236
  }
225
- if (Object.keys(updates).length > 0) {
237
+ if (Object.keys(updates).length > 1) {
226
238
  strapi2.config.set("plugin::strapi-plugin-oidc", { ...config2, ...updates });
227
239
  strapi2.log.info(`[strapi-plugin-oidc] Discovery applied: ${Object.keys(updates).join(", ")}`);
228
240
  }
@@ -379,7 +391,6 @@ function destroy() {
379
391
  const config = {
380
392
  default: {
381
393
  REMEMBER_ME: false,
382
- OIDC_DISCOVERY_URL: "",
383
394
  OIDC_REDIRECT_URI: "http://localhost:1337/strapi-plugin-oidc/oidc/callback",
384
395
  OIDC_CLIENT_ID: "",
385
396
  OIDC_CLIENT_SECRET: "",
@@ -395,7 +406,7 @@ const config = {
395
406
  OIDC_REQUIRE_EMAIL_VERIFIED: true,
396
407
  OIDC_TRUSTED_IP_HEADER: "",
397
408
  OIDC_FORCE_SECURE_COOKIES: false,
398
- // Populated at bootstrap from OIDC_DISCOVERY_URL — not user-configurable directly
409
+ // Populated at bootstrap from OIDC_ISSUER — not user-configurable directly
399
410
  OIDC_AUTHORIZATION_ENDPOINT: "",
400
411
  OIDC_TOKEN_ENDPOINT: "",
401
412
  OIDC_USERINFO_ENDPOINT: "",
@@ -516,14 +527,14 @@ function toMessage(e) {
516
527
  return e instanceof Error ? e.message : String(e);
517
528
  }
518
529
  const REQUIRED_CONFIG_KEYS = [
519
- "OIDC_DISCOVERY_URL",
530
+ "OIDC_ISSUER",
520
531
  "OIDC_CLIENT_ID",
521
532
  "OIDC_CLIENT_SECRET",
522
533
  "OIDC_REDIRECT_URI",
523
534
  "OIDC_SCOPE",
524
535
  "OIDC_FAMILY_NAME_FIELD",
525
536
  "OIDC_GIVEN_NAME_FIELD",
526
- // Populated at bootstrap from OIDC_DISCOVERY_URL — checked here as a runtime safety net
537
+ // Populated at bootstrap from OIDC_ISSUER — checked here as a runtime safety net
527
538
  "OIDC_TOKEN_ENDPOINT",
528
539
  "OIDC_USERINFO_ENDPOINT",
529
540
  "OIDC_AUTHORIZATION_ENDPOINT"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-oidc",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
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",