@strapi/plugin-users-permissions 5.50.1 → 5.51.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.
Files changed (65) hide show
  1. package/admin/src/pages/Roles/pages/EditPage.jsx +1 -1
  2. package/admin/src/translations/en.json +2 -0
  3. package/admin/src/translations/ko.json +2 -1
  4. package/dist/admin/pages/Roles/pages/EditPage.js +1 -1
  5. package/dist/admin/pages/Roles/pages/EditPage.js.map +1 -1
  6. package/dist/admin/pages/Roles/pages/EditPage.mjs +1 -1
  7. package/dist/admin/pages/Roles/pages/EditPage.mjs.map +1 -1
  8. package/dist/admin/translations/en.json.js +1 -0
  9. package/dist/admin/translations/en.json.js.map +1 -1
  10. package/dist/admin/translations/en.json.mjs +1 -0
  11. package/dist/admin/translations/en.json.mjs.map +1 -1
  12. package/dist/admin/translations/ko.json.js +2 -1
  13. package/dist/admin/translations/ko.json.js.map +1 -1
  14. package/dist/admin/translations/ko.json.mjs +2 -1
  15. package/dist/admin/translations/ko.json.mjs.map +1 -1
  16. package/dist/server/_virtual/_node_crypto.js +10 -0
  17. package/dist/server/_virtual/_node_crypto.js.map +1 -0
  18. package/dist/server/_virtual/_node_crypto.mjs +7 -0
  19. package/dist/server/_virtual/_node_crypto.mjs.map +1 -0
  20. package/dist/server/_virtual/_node_url.js +10 -0
  21. package/dist/server/_virtual/_node_url.js.map +1 -0
  22. package/dist/server/_virtual/_node_url.mjs +7 -0
  23. package/dist/server/_virtual/_node_url.mjs.map +1 -0
  24. package/dist/server/controllers/auth.js +19 -19
  25. package/dist/server/controllers/auth.js.map +1 -1
  26. package/dist/server/controllers/auth.mjs +19 -18
  27. package/dist/server/controllers/auth.mjs.map +1 -1
  28. package/dist/server/services/providers-registry.js +121 -242
  29. package/dist/server/services/providers-registry.js.map +1 -1
  30. package/dist/server/services/providers-registry.mjs +121 -239
  31. package/dist/server/services/providers-registry.mjs.map +1 -1
  32. package/dist/server/utils/oauth-connect/index.js +236 -0
  33. package/dist/server/utils/oauth-connect/index.js.map +1 -0
  34. package/dist/server/utils/oauth-connect/index.mjs +230 -0
  35. package/dist/server/utils/oauth-connect/index.mjs.map +1 -0
  36. package/dist/server/utils/oauth-connect/oauth1.js +138 -0
  37. package/dist/server/utils/oauth-connect/oauth1.js.map +1 -0
  38. package/dist/server/utils/oauth-connect/oauth1.mjs +136 -0
  39. package/dist/server/utils/oauth-connect/oauth1.mjs.map +1 -0
  40. package/dist/server/utils/oauth-connect/oauth2.js +117 -0
  41. package/dist/server/utils/oauth-connect/oauth2.js.map +1 -0
  42. package/dist/server/utils/oauth-connect/oauth2.mjs +115 -0
  43. package/dist/server/utils/oauth-connect/oauth2.mjs.map +1 -0
  44. package/dist/server/utils/oauth-connect/providers.js +109 -0
  45. package/dist/server/utils/oauth-connect/providers.js.map +1 -0
  46. package/dist/server/utils/oauth-connect/providers.mjs +107 -0
  47. package/dist/server/utils/oauth-connect/providers.mjs.map +1 -0
  48. package/dist/server/utils/provider-http.js +52 -0
  49. package/dist/server/utils/provider-http.js.map +1 -0
  50. package/dist/server/utils/provider-http.mjs +50 -0
  51. package/dist/server/utils/provider-http.mjs.map +1 -0
  52. package/dist/server/utils/verify-jwt-with-jwks.js +60 -0
  53. package/dist/server/utils/verify-jwt-with-jwks.js.map +1 -0
  54. package/dist/server/utils/verify-jwt-with-jwks.mjs +54 -0
  55. package/dist/server/utils/verify-jwt-with-jwks.mjs.map +1 -0
  56. package/jsconfig.json +7 -0
  57. package/package.json +12 -12
  58. package/server/controllers/auth.js +13 -20
  59. package/server/services/providers-registry.js +137 -293
  60. package/server/utils/oauth-connect/index.js +256 -0
  61. package/server/utils/oauth-connect/oauth1.js +169 -0
  62. package/server/utils/oauth-connect/oauth2.js +123 -0
  63. package/server/utils/oauth-connect/providers.js +100 -0
  64. package/server/utils/provider-http.js +49 -0
  65. package/server/utils/verify-jwt-with-jwks.js +43 -0
@@ -1,8 +1,8 @@
1
1
  import require$$0 from 'assert';
2
- import require$$1 from 'jsonwebtoken';
3
2
  import require$$2 from 'url-join';
4
- import require$$3 from 'jwk-to-pem';
5
- import require$$4 from 'purest';
3
+ import { __require as requireVerifyJwtWithJwks } from '../utils/verify-jwt-with-jwks.mjs';
4
+ import { __require as requireProviderHttp } from '../utils/provider-http.mjs';
5
+ import { __require as requireOauth1 } from '../utils/oauth-connect/oauth1.mjs';
6
6
 
7
7
  var providersRegistry;
8
8
  var hasRequiredProvidersRegistry;
@@ -10,53 +10,10 @@ function requireProvidersRegistry() {
10
10
  if (hasRequiredProvidersRegistry) return providersRegistry;
11
11
  hasRequiredProvidersRegistry = 1;
12
12
  const { strict: assert } = require$$0;
13
- const jwt = require$$1;
14
13
  const urljoin = require$$2;
15
- const jwkToPem = require$$3;
16
- const getCognitoPayload = async ({ idToken, jwksUrl, purest })=>{
17
- const { header: { kid }, payload } = jwt.decode(idToken, {
18
- complete: true
19
- });
20
- if (!payload || !kid) {
21
- throw new Error('The provided token is not valid');
22
- }
23
- const config = {
24
- cognito: {
25
- discovery: {
26
- origin: jwksUrl.origin,
27
- path: jwksUrl.pathname
28
- }
29
- }
30
- };
31
- try {
32
- const cognito = purest({
33
- provider: 'cognito',
34
- config
35
- });
36
- // get the JSON Web Key (JWK) for the user pool
37
- const { body: jwk } = await cognito('discovery').request();
38
- // Get the key with the same Key ID as the provided token
39
- const key = jwk.keys.find(({ kid: jwkKid })=>jwkKid === kid);
40
- const pem = jwkToPem(key);
41
- // https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-verifying-a-jwt.html
42
- const decodedToken = await new Promise((resolve, reject)=>{
43
- jwt.verify(idToken, pem, {
44
- algorithms: [
45
- 'RS256'
46
- ]
47
- }, (err, decodedToken)=>{
48
- if (err) {
49
- reject();
50
- }
51
- resolve(decodedToken);
52
- });
53
- });
54
- return decodedToken;
55
- } catch (err) {
56
- throw new Error('There was an error verifying the token');
57
- }
58
- };
59
- const initProviders = ({ baseURL, purest })=>({
14
+ const { verifyJwtWithJwks } = requireVerifyJwtWithJwks();
15
+ const { bearerGet, fetchJson } = requireProviderHttp();
16
+ const initProviders = ({ baseURL })=>({
60
17
  email: {
61
18
  enabled: true,
62
19
  icon: 'envelope',
@@ -75,17 +32,12 @@ function requireProvidersRegistry() {
75
32
  ]
76
33
  },
77
34
  async authCallback ({ accessToken }) {
78
- const discord = purest({
79
- provider: 'discord'
80
- });
81
- return discord.get('users/@me').auth(accessToken).request().then(({ body })=>{
82
- // Combine username and discriminator (if discriminator exists and not equal to 0)
83
- const username = body.discriminator && body.discriminator !== '0' ? `${body.username}#${body.discriminator}` : body.username;
84
- return {
85
- username,
86
- email: body.email
87
- };
88
- });
35
+ const { body } = await bearerGet('https://discord.com/api/users/@me', accessToken);
36
+ const username = body.discriminator && body.discriminator !== '0' ? `${body.username}#${body.discriminator}` : body.username;
37
+ return {
38
+ username,
39
+ email: body.email
40
+ };
89
41
  }
90
42
  },
91
43
  facebook: {
@@ -100,15 +52,15 @@ function requireProvidersRegistry() {
100
52
  ]
101
53
  },
102
54
  async authCallback ({ accessToken }) {
103
- const facebook = purest({
104
- provider: 'facebook'
55
+ const { body } = await bearerGet('https://graph.facebook.com/me', accessToken, {
56
+ qs: {
57
+ fields: 'name,email'
58
+ }
105
59
  });
106
- return facebook.get('me').auth(accessToken).qs({
107
- fields: 'name,email'
108
- }).request().then(({ body })=>({
109
- username: body.name,
110
- email: body.email
111
- }));
60
+ return {
61
+ username: body.name,
62
+ email: body.email
63
+ };
112
64
  }
113
65
  },
114
66
  google: {
@@ -123,15 +75,11 @@ function requireProvidersRegistry() {
123
75
  ]
124
76
  },
125
77
  async authCallback ({ accessToken }) {
126
- const google = purest({
127
- provider: 'google'
128
- });
129
- return google.query('oauth').get('tokeninfo').qs({
130
- accessToken
131
- }).request().then(({ body })=>({
132
- username: body.email.split('@')[0],
133
- email: body.email
134
- }));
78
+ const { body } = await fetchJson(`https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(accessToken)}`);
79
+ return {
80
+ username: body.email.split('@')[0],
81
+ email: body.email
82
+ };
135
83
  }
136
84
  },
137
85
  github: {
@@ -147,24 +95,22 @@ function requireProvidersRegistry() {
147
95
  ]
148
96
  },
149
97
  async authCallback ({ accessToken }) {
150
- const github = purest({
151
- provider: 'github',
152
- defaults: {
153
- headers: {
154
- 'user-agent': 'strapi'
155
- }
98
+ const { body: userBody } = await bearerGet('https://api.github.com/user', accessToken, {
99
+ headers: {
100
+ 'user-agent': 'strapi'
156
101
  }
157
102
  });
158
- const { body: userBody } = await github.get('user').auth(accessToken).request();
159
- // This is the public email on the github profile
160
103
  if (userBody.email) {
161
104
  return {
162
105
  username: userBody.login,
163
106
  email: userBody.email
164
107
  };
165
108
  }
166
- // Get the email with Github's user/emails API
167
- const { body: emailBody } = await github.get('user/emails').auth(accessToken).request();
109
+ const { body: emailBody } = await bearerGet('https://api.github.com/user/emails', accessToken, {
110
+ headers: {
111
+ 'user-agent': 'strapi'
112
+ }
113
+ });
168
114
  return {
169
115
  username: userBody.login,
170
116
  email: Array.isArray(emailBody) ? emailBody.find((email)=>email.primary === true).email : null
@@ -183,13 +129,11 @@ function requireProvidersRegistry() {
183
129
  ]
184
130
  },
185
131
  async authCallback ({ accessToken }) {
186
- const microsoft = purest({
187
- provider: 'microsoft'
188
- });
189
- return microsoft.get('me').auth(accessToken).request().then(({ body })=>({
190
- username: body.userPrincipalName,
191
- email: body.userPrincipalName
192
- }));
132
+ const { body } = await bearerGet('https://graph.microsoft.com/v1.0/me', accessToken);
133
+ return {
134
+ username: body.userPrincipalName,
135
+ email: body.userPrincipalName
136
+ };
193
137
  }
194
138
  },
195
139
  twitter: {
@@ -201,22 +145,22 @@ function requireProvidersRegistry() {
201
145
  callbackUrl: `${baseURL}/twitter/callback`
202
146
  },
203
147
  async authCallback ({ accessToken, query, providers }) {
204
- const twitter = purest({
205
- provider: 'twitter',
206
- defaults: {
207
- oauth: {
208
- consumer_key: providers.twitter.key,
209
- consumer_secret: providers.twitter.secret
210
- }
148
+ const { twitterGet } = requireOauth1();
149
+ const { body } = await twitterGet({
150
+ url: 'https://api.twitter.com/1.1/account/verify_credentials.json',
151
+ accessToken,
152
+ accessCredential: query.access_secret,
153
+ consumerKey: providers.twitter.key,
154
+ clientCredential: providers.twitter.secret,
155
+ qs: {
156
+ include_email: 'true',
157
+ screen_name: query['raw[screen_name]']
211
158
  }
212
159
  });
213
- return twitter.get('account/verify_credentials').auth(accessToken, query.access_secret).qs({
214
- screen_name: query['raw[screen_name]'],
215
- include_email: 'true'
216
- }).request().then(({ body })=>({
217
- username: body.screen_name,
218
- email: body.email
219
- }));
160
+ return {
161
+ username: body.screen_name,
162
+ email: body.email
163
+ };
220
164
  }
221
165
  },
222
166
  instagram: {
@@ -231,15 +175,15 @@ function requireProvidersRegistry() {
231
175
  ]
232
176
  },
233
177
  async authCallback ({ accessToken }) {
234
- const instagram = purest({
235
- provider: 'instagram'
178
+ const { body } = await bearerGet('https://graph.instagram.com/me', accessToken, {
179
+ qs: {
180
+ fields: 'id,username'
181
+ }
236
182
  });
237
- return instagram.get('me').auth(accessToken).qs({
238
- fields: 'id,username'
239
- }).request().then(({ body })=>({
240
- username: body.username,
241
- email: `${body.username}@strapi.io`
242
- }));
183
+ return {
184
+ username: body.username,
185
+ email: `${body.username}@strapi.io`
186
+ };
243
187
  }
244
188
  },
245
189
  vk: {
@@ -254,16 +198,16 @@ function requireProvidersRegistry() {
254
198
  ]
255
199
  },
256
200
  async authCallback ({ accessToken, query }) {
257
- const vk = purest({
258
- provider: 'vk'
201
+ const { body } = await bearerGet('https://api.vk.com/method/users.get', accessToken, {
202
+ qs: {
203
+ user_ids: query.raw.user_id,
204
+ v: '5.122'
205
+ }
259
206
  });
260
- return vk.get('users').auth(accessToken).qs({
261
- id: query.raw.user_id,
262
- v: '5.122'
263
- }).request().then(({ body })=>({
264
- username: `${body.response[0].last_name} ${body.response[0].first_name}`,
265
- email: query.raw.email
266
- }));
207
+ return {
208
+ username: `${body.response[0].last_name} ${body.response[0].first_name}`,
209
+ email: query.raw.email
210
+ };
267
211
  }
268
212
  },
269
213
  twitch: {
@@ -278,25 +222,15 @@ function requireProvidersRegistry() {
278
222
  ]
279
223
  },
280
224
  async authCallback ({ accessToken, providers }) {
281
- const twitch = purest({
282
- provider: 'twitch',
283
- config: {
284
- twitch: {
285
- default: {
286
- origin: 'https://api.twitch.tv',
287
- path: 'helix/{path}',
288
- headers: {
289
- Authorization: 'Bearer {auth}',
290
- 'Client-Id': '{auth}'
291
- }
292
- }
293
- }
225
+ const { body } = await bearerGet('https://api.twitch.tv/helix/users', accessToken, {
226
+ headers: {
227
+ 'Client-Id': providers.twitch.key
294
228
  }
295
229
  });
296
- return twitch.get('users').auth(accessToken, providers.twitch.key).request().then(({ body })=>({
297
- username: body.data[0].login,
298
- email: body.data[0].email
299
- }));
230
+ return {
231
+ username: body.data[0].login,
232
+ email: body.data[0].email
233
+ };
300
234
  }
301
235
  },
302
236
  linkedin: {
@@ -312,14 +246,11 @@ function requireProvidersRegistry() {
312
246
  ]
313
247
  },
314
248
  async authCallback ({ accessToken }) {
315
- const linkedIn = purest({
316
- provider: 'linkedin'
317
- });
318
- const { body: { localizedFirstName } } = await linkedIn.get('me').auth(accessToken).request();
319
- const { body: { elements } } = await linkedIn.get('emailAddress?q=members&projection=(elements*(handle~))').auth(accessToken).request();
320
- const email = elements[0]['handle~'];
249
+ const { body: profileBody } = await bearerGet('https://api.linkedin.com/v2/me', accessToken);
250
+ const { body: emailBody } = await bearerGet('https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))', accessToken);
251
+ const email = emailBody.elements[0]['handle~'];
321
252
  return {
322
- username: localizedFirstName,
253
+ username: profileBody.localizedFirstName,
323
254
  email: email.emailAddress
324
255
  };
325
256
  }
@@ -341,10 +272,9 @@ function requireProvidersRegistry() {
341
272
  async authCallback ({ query, providers }) {
342
273
  const jwksUrl = new URL(providers.cognito.jwksurl);
343
274
  const idToken = query.id_token;
344
- const tokenPayload = await getCognitoPayload({
275
+ const tokenPayload = await verifyJwtWithJwks({
345
276
  idToken,
346
- jwksUrl,
347
- purest
277
+ jwksUrl
348
278
  });
349
279
  return {
350
280
  username: tokenPayload['cognito:username'],
@@ -364,26 +294,15 @@ function requireProvidersRegistry() {
364
294
  ]
365
295
  },
366
296
  async authCallback ({ accessToken }) {
367
- const reddit = purest({
368
- provider: 'reddit',
369
- config: {
370
- reddit: {
371
- default: {
372
- origin: 'https://oauth.reddit.com',
373
- path: 'api/{version}/{path}',
374
- version: 'v1',
375
- headers: {
376
- Authorization: 'Bearer {auth}',
377
- 'user-agent': 'strapi'
378
- }
379
- }
380
- }
297
+ const { body } = await bearerGet('https://oauth.reddit.com/api/v1/me', accessToken, {
298
+ headers: {
299
+ 'user-agent': 'strapi'
381
300
  }
382
301
  });
383
- return reddit.get('me').auth(accessToken).request().then(({ body })=>({
384
- username: body.name,
385
- email: `${body.name}@strapi.io`
386
- }));
302
+ return {
303
+ username: body.name,
304
+ email: `${body.name}@strapi.io`
305
+ };
387
306
  }
388
307
  },
389
308
  auth0: {
@@ -401,17 +320,13 @@ function requireProvidersRegistry() {
401
320
  ]
402
321
  },
403
322
  async authCallback ({ accessToken, providers }) {
404
- const auth0 = purest({
405
- provider: 'auth0'
406
- });
407
- return auth0.get('userinfo').subdomain(providers.auth0.subdomain).auth(accessToken).request().then(({ body })=>{
408
- const username = body.username || body.nickname || body.name || body.email.split('@')[0];
409
- const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
410
- return {
411
- username,
412
- email
413
- };
414
- });
323
+ const { body } = await bearerGet(`https://${providers.auth0.subdomain}.auth0.com/userinfo`, accessToken);
324
+ const username = body.username || body.nickname || body.name || body.email.split('@')[0];
325
+ const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
326
+ return {
327
+ username,
328
+ email
329
+ };
415
330
  }
416
331
  },
417
332
  cas: {
@@ -427,21 +342,16 @@ function requireProvidersRegistry() {
427
342
  subdomain: 'my.subdomain.com/cas'
428
343
  },
429
344
  async authCallback ({ accessToken, providers }) {
430
- const cas = purest({
431
- provider: 'cas'
432
- });
433
- return cas.get('oidc/profile').subdomain(providers.cas.subdomain).auth(accessToken).request().then(({ body })=>{
434
- // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
435
- const username = body.attributes ? body.attributes.strapiusername || body.id || body.sub : body.strapiusername || body.id || body.sub;
436
- const email = body.attributes ? body.attributes.strapiemail || body.attributes.email : body.strapiemail || body.email;
437
- if (!username || !email) {
438
- strapi.log.warn(`CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`);
439
- }
440
- return {
441
- username,
442
- email
443
- };
444
- });
345
+ const { body } = await bearerGet(`https://${providers.cas.subdomain}/oidc/profile`, accessToken);
346
+ const username = body.attributes ? body.attributes.strapiusername || body.id || body.sub : body.strapiusername || body.id || body.sub;
347
+ const email = body.attributes ? body.attributes.strapiemail || body.attributes.email : body.strapiemail || body.email;
348
+ if (!username || !email) {
349
+ strapi.log.warn(`CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`);
350
+ }
351
+ return {
352
+ username,
353
+ email
354
+ };
445
355
  }
446
356
  },
447
357
  patreon: {
@@ -457,29 +367,12 @@ function requireProvidersRegistry() {
457
367
  ]
458
368
  },
459
369
  async authCallback ({ accessToken }) {
460
- const patreon = purest({
461
- provider: 'patreon',
462
- config: {
463
- patreon: {
464
- default: {
465
- origin: 'https://www.patreon.com',
466
- path: 'api/oauth2/{path}',
467
- headers: {
468
- authorization: 'Bearer {auth}'
469
- }
470
- }
471
- }
472
- }
473
- });
474
- return patreon.get('v2/identity').auth(accessToken).qs(new URLSearchParams({
475
- 'fields[user]': 'full_name,email'
476
- }).toString()).request().then(({ body })=>{
477
- const patreonData = body.data.attributes;
478
- return {
479
- username: patreonData.full_name,
480
- email: patreonData.email
481
- };
482
- });
370
+ const { body } = await bearerGet('https://www.patreon.com/api/oauth2/v2/identity?fields[user]=full_name,email', accessToken);
371
+ const patreonData = body.data.attributes;
372
+ return {
373
+ username: patreonData.full_name,
374
+ email: patreonData.email
375
+ };
483
376
  }
484
377
  },
485
378
  keycloak: {
@@ -497,29 +390,21 @@ function requireProvidersRegistry() {
497
390
  ]
498
391
  },
499
392
  async authCallback ({ accessToken, providers }) {
500
- const keycloak = purest({
501
- provider: 'keycloak'
502
- });
503
- return keycloak.subdomain(providers.keycloak.subdomain).get('protocol/openid-connect/userinfo').auth(accessToken).request().then(({ body })=>{
504
- return {
505
- username: body.preferred_username,
506
- email: body.email
507
- };
508
- });
393
+ const { body } = await bearerGet(`https://${providers.keycloak.subdomain}/protocol/openid-connect/userinfo`, accessToken);
394
+ return {
395
+ username: body.preferred_username,
396
+ email: body.email
397
+ };
509
398
  }
510
399
  }
511
400
  });
512
401
  providersRegistry = ()=>{
513
- const purest = require$$4;
514
402
  const apiPrefix = strapi.config.get('api.rest.prefix');
515
403
  const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
516
404
  const authProviders = initProviders({
517
- baseURL,
518
- purest
405
+ baseURL
519
406
  });
520
- /**
521
- * @public
522
- */ return {
407
+ return {
523
408
  getAll () {
524
409
  return authProviders;
525
410
  },
@@ -532,16 +417,13 @@ function requireProvidersRegistry() {
532
417
  remove (name) {
533
418
  delete authProviders[name];
534
419
  },
535
- /**
536
- * @internal
537
- */ async run ({ provider, accessToken, query, providers }) {
420
+ async run ({ provider, accessToken, query, providers }) {
538
421
  const authProvider = authProviders[provider];
539
422
  assert(authProvider, 'Unknown auth provider');
540
423
  return authProvider.authCallback({
541
424
  accessToken,
542
425
  query,
543
- providers,
544
- purest
426
+ providers
545
427
  });
546
428
  }
547
429
  };