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 +2 -2
- package/dist/server/index.js +22 -11
- package/dist/server/index.mjs +22 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ module.exports = ({ env }) => ({
|
|
|
32
32
|
enabled: true,
|
|
33
33
|
config: {
|
|
34
34
|
// Required
|
|
35
|
-
|
|
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
|
-
`
|
|
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
|
|
package/dist/server/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
211
|
-
if (!
|
|
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 >
|
|
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
|
|
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
|
-
"
|
|
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
|
|
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"
|
package/dist/server/index.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
|
205
|
-
if (!
|
|
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 >
|
|
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
|
|
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
|
-
"
|
|
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
|
|
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