strapi-plugin-oidc 1.5.3 → 1.6.0
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 +143 -26
- package/dist/admin/{index-DWm8oOJF.js → index-DTOcUHZi.js} +342 -177
- package/dist/admin/{index-Dz3WlTpL.mjs → index-DmJadA2p.mjs} +344 -179
- package/dist/admin/{index-Dzf0bJC1.mjs → index-P9HriRms.mjs} +31 -6
- package/dist/admin/{index-CqgjBmJ5.js → index-f3cmU_tE.js} +31 -6
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +620 -174
- package/dist/server/index.mjs +621 -175
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,8 +5,11 @@
|
|
|
5
5
|
<a href="https://www.npmjs.com/package/strapi-plugin-oidc">
|
|
6
6
|
<img src="https://img.shields.io/npm/v/strapi-plugin-oidc.svg" alt="npm version">
|
|
7
7
|
</a>
|
|
8
|
-
<a href="https://github.com/edmogeor/strapi-plugin-oidc/actions/workflows/
|
|
9
|
-
<img src="https://github.com/edmogeor/strapi-plugin-oidc/actions/workflows/
|
|
8
|
+
<a href="https://github.com/edmogeor/strapi-plugin-oidc/actions/workflows/ci.yml">
|
|
9
|
+
<img src="https://github.com/edmogeor/strapi-plugin-oidc/actions/workflows/ci.yml/badge.svg" alt="CI"/>
|
|
10
|
+
</a>
|
|
11
|
+
<a href="./LICENSE">
|
|
12
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"/>
|
|
10
13
|
</a>
|
|
11
14
|
</p>
|
|
12
15
|
</div>
|
|
@@ -28,7 +31,7 @@ module.exports = ({ env }) => ({
|
|
|
28
31
|
'strapi-plugin-oidc': {
|
|
29
32
|
enabled: true,
|
|
30
33
|
config: {
|
|
31
|
-
// Required
|
|
34
|
+
// Required — find these in your provider's OIDC discovery document
|
|
32
35
|
OIDC_CLIENT_ID: env('OIDC_CLIENT_ID'),
|
|
33
36
|
OIDC_CLIENT_SECRET: env('OIDC_CLIENT_SECRET'),
|
|
34
37
|
OIDC_REDIRECT_URI: env('OIDC_REDIRECT_URI'), // https://your-strapi.com/strapi-plugin-oidc/oidc/callback
|
|
@@ -41,18 +44,27 @@ module.exports = ({ env }) => ({
|
|
|
41
44
|
OIDC_GRANT_TYPE: 'authorization_code',
|
|
42
45
|
OIDC_FAMILY_NAME_FIELD: 'family_name',
|
|
43
46
|
OIDC_GIVEN_NAME_FIELD: 'given_name',
|
|
44
|
-
OIDC_END_SESSION_ENDPOINT: '', // Provider end-session URL
|
|
47
|
+
OIDC_END_SESSION_ENDPOINT: '', // Provider end-session URL for RP-initiated logout
|
|
45
48
|
OIDC_SSO_BUTTON_TEXT: 'Login via SSO',
|
|
46
49
|
OIDC_ENFORCE: null, // null = use Admin UI toggle; true/false = override in config
|
|
47
50
|
REMEMBER_ME: false, // Persist session across browser restarts
|
|
51
|
+
AUDIT_LOG_RETENTION_DAYS: 90, // Set to 0 to disable audit logging; otherwise entries older than this many days are purged daily at midnight
|
|
52
|
+
OIDC_GROUP_FIELD: 'groups', // OIDC claim field containing group membership
|
|
53
|
+
OIDC_GROUP_ROLE_MAP: '{}', // JSON map of group names to Strapi role names
|
|
48
54
|
},
|
|
49
55
|
},
|
|
50
56
|
});
|
|
51
57
|
```
|
|
52
58
|
|
|
59
|
+
All required values come from your provider's OIDC discovery document, typically available at `https://your-provider/.well-known/openid-configuration`.
|
|
60
|
+
|
|
53
61
|
## Login
|
|
54
62
|
|
|
55
|
-
Navigate to `/strapi-plugin-oidc/oidc` to start the OIDC flow, or click the **Login via SSO** button
|
|
63
|
+
Navigate to `/strapi-plugin-oidc/oidc` to start the OIDC flow, or click the **Login via SSO** button injected into the Strapi login page.
|
|
64
|
+
|
|
65
|
+
## Logout
|
|
66
|
+
|
|
67
|
+
When `OIDC_END_SESSION_ENDPOINT` is set, clicking logout in Strapi redirects the browser to the provider's end-session URL (RP-initiated logout). If the provider session has already expired, Strapi skips the redirect and goes straight to the login page.
|
|
56
68
|
|
|
57
69
|
## Admin Settings
|
|
58
70
|
|
|
@@ -60,18 +72,57 @@ Manage the plugin under **Settings → OIDC Plugin**.
|
|
|
60
72
|
|
|
61
73
|
**Default Roles** — Select which Strapi admin role(s) are assigned to new users on first login.
|
|
62
74
|
|
|
63
|
-
**Whitelist** — Restrict access to specific email addresses. When
|
|
75
|
+
**Whitelist** — Restrict access to specific email addresses. When enabled, only listed emails can log in. When empty, any successfully authenticated OIDC user gets an account. The whitelist supports:
|
|
64
76
|
|
|
65
77
|
- Adding individual emails with optional role overrides
|
|
66
78
|
- JSON import / export (see [format](#import-format) below)
|
|
67
79
|
- Bulk delete with confirmation
|
|
68
80
|
- Unsaved changes are held in the UI until **Save Changes** is clicked
|
|
69
81
|
|
|
82
|
+
**Audit Logs** — Every authentication event is recorded in the plugin's audit log table and visible in the **Audit Logs** section at the bottom of the settings page. A **Download** button exports all records as JSON, compatible with SIEM tools and log processors. Setting `AUDIT_LOG_RETENTION_DAYS` to `0` disables audit logging entirely. Otherwise records older than the configured value (default: 90 days) are automatically purged by a daily cron job. The audit log is also accessible [via API](#audit-log-api).
|
|
83
|
+
|
|
70
84
|
**Enforce OIDC Login** — Removes the standard email/password fields from the login page and blocks direct login API calls server-side. Automatically disabled when the whitelist is empty to prevent lockout.
|
|
71
85
|
|
|
72
86
|
- The toggle is grayed out and locked when `OIDC_ENFORCE` is set in config.
|
|
73
87
|
- **Lockout recovery**: set `OIDC_ENFORCE: false` in your plugin config and restart Strapi. This writes through to the database so removing the variable afterwards keeps the setting.
|
|
74
88
|
|
|
89
|
+
## Group-to-Role Mapping
|
|
90
|
+
|
|
91
|
+
When your OIDC provider includes group membership in the userinfo response (e.g. a `groups` claim containing `["strapi-admins", "strapi-editors"]`), you can automatically assign Strapi roles based on group membership.
|
|
92
|
+
|
|
93
|
+
| Setting | Default | Description |
|
|
94
|
+
| --------------------- | ---------- | --------------------------------------------------------- |
|
|
95
|
+
| `OIDC_GROUP_FIELD` | `'groups'` | OIDC claim field that contains the group membership array |
|
|
96
|
+
| `OIDC_GROUP_ROLE_MAP` | `'{}'` | JSON map of group names → Strapi role names |
|
|
97
|
+
|
|
98
|
+
### Example configuration
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
module.exports = ({ env }) => ({
|
|
102
|
+
'strapi-plugin-oidc': {
|
|
103
|
+
enabled: true,
|
|
104
|
+
config: {
|
|
105
|
+
// ... other OIDC config ...
|
|
106
|
+
OIDC_GROUP_FIELD: 'groups',
|
|
107
|
+
OIDC_GROUP_ROLE_MAP: JSON.stringify({
|
|
108
|
+
'strapi-admins': ['Super Admin'],
|
|
109
|
+
'strapi-editors': ['Editor'],
|
|
110
|
+
'strapi-authors': ['Editor', 'Author'],
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Role names are the **display names** shown in **Settings → Roles** (e.g. `"Editor"`, `"Super Admin"`, `"Author"`). IDs are not supported — use names for clarity.
|
|
118
|
+
|
|
119
|
+
### Role assignment precedence
|
|
120
|
+
|
|
121
|
+
1. **User's OIDC groups match `OIDC_GROUP_ROLE_MAP`** → use the mapped Strapi roles
|
|
122
|
+
2. **No group match or no mapping configured** → use the default OIDC roles
|
|
123
|
+
|
|
124
|
+
> **Note:** Existing users' roles are updated on every login to reflect current group membership.
|
|
125
|
+
|
|
75
126
|
## Whitelist API
|
|
76
127
|
|
|
77
128
|
The whitelist can be managed programmatically using a Strapi **API token** (Settings → API Tokens → Full Access). All endpoints are under `/api/strapi-plugin-oidc` and require `Authorization: Bearer <token>`.
|
|
@@ -79,9 +130,10 @@ The whitelist can be managed programmatically using a Strapi **API token** (Sett
|
|
|
79
130
|
| Method | Path | Description |
|
|
80
131
|
| -------- | ------------------------------------------ | ---------------------- |
|
|
81
132
|
| `GET` | `/api/strapi-plugin-oidc/whitelist` | List all entries |
|
|
133
|
+
| `GET` | `/api/strapi-plugin-oidc/whitelist/export` | Export as JSON |
|
|
82
134
|
| `POST` | `/api/strapi-plugin-oidc/whitelist` | Add one or more emails |
|
|
83
135
|
| `POST` | `/api/strapi-plugin-oidc/whitelist/import` | Bulk import |
|
|
84
|
-
| `DELETE` | `/api/strapi-plugin-oidc/whitelist/:
|
|
136
|
+
| `DELETE` | `/api/strapi-plugin-oidc/whitelist/:email` | Remove by email |
|
|
85
137
|
| `DELETE` | `/api/strapi-plugin-oidc/whitelist` | Remove all entries |
|
|
86
138
|
|
|
87
139
|
API calls write directly to the database — there is no unsaved state.
|
|
@@ -107,6 +159,11 @@ Duplicate emails within the payload and emails already in the whitelist are sile
|
|
|
107
159
|
curl -H "Authorization: Bearer <token>" \
|
|
108
160
|
http://localhost:1337/api/strapi-plugin-oidc/whitelist
|
|
109
161
|
|
|
162
|
+
# Export
|
|
163
|
+
curl -H "Authorization: Bearer <token>" \
|
|
164
|
+
http://localhost:1337/api/strapi-plugin-oidc/whitelist/export \
|
|
165
|
+
-o whitelist.json
|
|
166
|
+
|
|
110
167
|
# Add
|
|
111
168
|
curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/json" \
|
|
112
169
|
-d '{"email": "user@example.com", "roles": ["Editor"]}' \
|
|
@@ -117,33 +174,93 @@ curl -X POST -H "Authorization: Bearer <token>" -H "Content-Type: application/js
|
|
|
117
174
|
-d '{"users": [{"email": "a@example.com", "roles": ["Editor"]}, {"email": "b@example.com"}]}' \
|
|
118
175
|
http://localhost:1337/api/strapi-plugin-oidc/whitelist/import
|
|
119
176
|
|
|
120
|
-
# Delete one
|
|
177
|
+
# Delete one (by email)
|
|
121
178
|
curl -X DELETE -H "Authorization: Bearer <token>" \
|
|
122
|
-
http://localhost:1337/api/strapi-plugin-oidc/whitelist/
|
|
179
|
+
"http://localhost:1337/api/strapi-plugin-oidc/whitelist/user%40example.com"
|
|
123
180
|
|
|
124
181
|
# Delete all
|
|
125
182
|
curl -X DELETE -H "Authorization: Bearer <token>" \
|
|
126
183
|
http://localhost:1337/api/strapi-plugin-oidc/whitelist
|
|
127
184
|
```
|
|
128
185
|
|
|
186
|
+
## Audit Log API
|
|
187
|
+
|
|
188
|
+
Audit log entries can be fetched programmatically using a Strapi **API token** (Settings → API Tokens → Full Access). Endpoints are under `/api/strapi-plugin-oidc` and require `Authorization: Bearer <token>`.
|
|
189
|
+
|
|
190
|
+
| Method | Path | Description |
|
|
191
|
+
| ------ | ------------------------------------------- | ----------------------------- |
|
|
192
|
+
| `GET` | `/api/strapi-plugin-oidc/audit-logs` | Paginated list of log entries |
|
|
193
|
+
| `GET` | `/api/strapi-plugin-oidc/audit-logs/export` | All records as JSON download |
|
|
194
|
+
|
|
195
|
+
### Query parameters (`GET /audit-logs`)
|
|
196
|
+
|
|
197
|
+
| Parameter | Default | Description |
|
|
198
|
+
| ---------- | ------- | ---------------- |
|
|
199
|
+
| `page` | `1` | Page number |
|
|
200
|
+
| `pageSize` | `25` | Results per page |
|
|
201
|
+
|
|
202
|
+
Results are sorted newest-first. The response shape is:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"results": [
|
|
207
|
+
{
|
|
208
|
+
"datetime": "2026-04-08T12:00:00.000Z",
|
|
209
|
+
"action": "login_success",
|
|
210
|
+
"email": "alice@example.com",
|
|
211
|
+
"ip": "203.0.113.42"
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
"pagination": { "page": 1, "pageSize": 25, "total": 1, "pageCount": 1 }
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Recorded actions
|
|
219
|
+
|
|
220
|
+
| Action | Trigger |
|
|
221
|
+
| ----------------------- | --------------------------------------------------- |
|
|
222
|
+
| `login_success` | Successful OIDC authentication |
|
|
223
|
+
| `user_created` | New Strapi admin user created during login |
|
|
224
|
+
| `login_failure` | Generic authentication error (missing code, etc.) |
|
|
225
|
+
| `state_mismatch` | CSRF state cookie does not match callback parameter |
|
|
226
|
+
| `nonce_mismatch` | ID token nonce does not match the session nonce |
|
|
227
|
+
| `token_exchange_failed` | Provider returned an error during token exchange |
|
|
228
|
+
| `whitelist_rejected` | Email not present in the active whitelist |
|
|
229
|
+
| `logout` | User logged out via `/logout` |
|
|
230
|
+
| `session_expired` | Logout attempted but provider session already stale |
|
|
231
|
+
|
|
232
|
+
Each event is also emitted on Strapi's internal eventHub as `strapi-plugin-oidc::auth.<action>`, which Enterprise audit log listeners pick up automatically.
|
|
233
|
+
|
|
234
|
+
### Examples
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Paginated list
|
|
238
|
+
curl -H "Authorization: Bearer <token>" \
|
|
239
|
+
"http://localhost:1337/api/strapi-plugin-oidc/audit-logs?page=1&pageSize=50"
|
|
240
|
+
|
|
241
|
+
# JSON export
|
|
242
|
+
curl -H "Authorization: Bearer <token>" \
|
|
243
|
+
http://localhost:1337/api/strapi-plugin-oidc/audit-logs/export \
|
|
244
|
+
-o oidc-audit-log.json
|
|
245
|
+
```
|
|
246
|
+
|
|
129
247
|
## Credits & Changes
|
|
130
248
|
|
|
131
249
|
This plugin is a hard fork of [`strapi-plugin-sso`](https://github.com/yasudacloud/strapi-plugin-sso) by **yasudacloud**. Huge thanks to them for creating the foundation of this plugin!
|
|
132
250
|
|
|
133
|
-
### Changes
|
|
134
|
-
|
|
135
|
-
- Removed alternative SSO methods to
|
|
136
|
-
- Redesigned the Whitelist and Role management UI
|
|
137
|
-
- Added an
|
|
138
|
-
- Added
|
|
139
|
-
- Migrated
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
- Added misc. quality of life improvements and bug fixes.
|
|
251
|
+
### Changes from the original:
|
|
252
|
+
|
|
253
|
+
- Removed alternative SSO methods to focus solely on OIDC.
|
|
254
|
+
- Redesigned the Whitelist and Role management UI using native Strapi components.
|
|
255
|
+
- Added OIDC enforcement with an admin toggle and config override (`OIDC_ENFORCE`).
|
|
256
|
+
- Added RP-initiated logout with smart session detection — skips the provider redirect if the session is already expired.
|
|
257
|
+
- Migrated to Vitest with comprehensive e2e test coverage.
|
|
258
|
+
- Config variable names aligned with OIDC discovery document field names (`OIDC_SCOPE`, `OIDC_USERINFO_ENDPOINT`, `OIDC_END_SESSION_ENDPOINT`).
|
|
259
|
+
- Always injects a **Login via SSO** button on the Strapi login page. Button text is configurable via `OIDC_SSO_BUTTON_TEXT`.
|
|
260
|
+
- Whitelist: programmatic REST API with JSON import/export, bulk delete, delete by email, and unsaved changes guard.
|
|
261
|
+
- Hardened OIDC flow: server-generated state and nonce, PKCE, Bearer token auth for userinfo, and generic error messages on failure.
|
|
262
|
+
- Audit log: records all auth events to a queryable table with Admin UI, JSON export, and REST API. API responses use a single `datetime` field and omit framework metadata (id, documentId, locale, publishedAt, etc.). A separate `user_created` event is emitted when a Strapi admin is provisioned during login.
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
[MIT](./LICENSE)
|