@strapi/plugin-users-permissions 5.0.0-rc.0 → 5.0.0-rc.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.
Files changed (31) hide show
  1. package/dist/_chunks/{index-iaebB1BT.js → index-B1qzCQd5.js} +8 -8
  2. package/dist/_chunks/{index-iaebB1BT.js.map → index-B1qzCQd5.js.map} +1 -1
  3. package/dist/_chunks/{index-DVEZVDjs.js → index-BrHOhLiu.js} +2 -2
  4. package/dist/_chunks/{index-DVEZVDjs.js.map → index-BrHOhLiu.js.map} +1 -1
  5. package/dist/_chunks/{index-DCFIfSfa.mjs → index-CGwt3Ia4.mjs} +3 -3
  6. package/dist/_chunks/{index-DCFIfSfa.mjs.map → index-CGwt3Ia4.mjs.map} +1 -1
  7. package/dist/_chunks/{index-iSLj9xJT.js → index-Cp4WQ7CY.js} +2 -2
  8. package/dist/_chunks/{index-iSLj9xJT.js.map → index-Cp4WQ7CY.js.map} +1 -1
  9. package/dist/_chunks/{index-DRoVF6Y7.js → index-CxY6jE0v.js} +7 -7
  10. package/dist/_chunks/{index-DRoVF6Y7.js.map → index-CxY6jE0v.js.map} +1 -1
  11. package/dist/_chunks/{index-iMO1GC3n.js → index-D-gXJApn.js} +4 -4
  12. package/dist/_chunks/{index-iMO1GC3n.js.map → index-D-gXJApn.js.map} +1 -1
  13. package/dist/_chunks/{index-Cf2sMpyd.mjs → index-DUjTQKud.mjs} +8 -8
  14. package/dist/_chunks/{index-Cf2sMpyd.mjs.map → index-DUjTQKud.mjs.map} +1 -1
  15. package/dist/_chunks/{index-qhy_K2pJ.mjs → index-DkSluM9h.mjs} +2 -2
  16. package/dist/_chunks/{index-qhy_K2pJ.mjs.map → index-DkSluM9h.mjs.map} +1 -1
  17. package/dist/_chunks/{index-zmcUQlrv.mjs → index-Dt46aAk-.mjs} +3 -3
  18. package/dist/_chunks/{index-zmcUQlrv.mjs.map → index-Dt46aAk-.mjs.map} +1 -1
  19. package/dist/_chunks/{index-B9OX-a4A.mjs → index-_XxxzBHB.mjs} +2 -2
  20. package/dist/_chunks/{index-B9OX-a4A.mjs.map → index-_XxxzBHB.mjs.map} +1 -1
  21. package/dist/_chunks/{index-8-k5RCnK-BHUgmsKx.mjs → index-m_rp3iqs-BHUgmsKx.mjs} +1 -1
  22. package/dist/_chunks/{index-8-k5RCnK-BHUgmsKx.mjs.map → index-m_rp3iqs-BHUgmsKx.mjs.map} +1 -1
  23. package/dist/_chunks/{index-8-k5RCnK-qR3QHvSP.js → index-m_rp3iqs-qR3QHvSP.js} +1 -1
  24. package/dist/_chunks/{index-8-k5RCnK-qR3QHvSP.js.map → index-m_rp3iqs-qR3QHvSP.js.map} +1 -1
  25. package/dist/admin/index.js +1 -1
  26. package/dist/admin/index.mjs +1 -1
  27. package/package.json +4 -4
  28. package/server/bootstrap/index.js +13 -9
  29. package/server/services/providers-registry.js +465 -275
  30. package/server/utils/index.d.ts +2 -1
  31. package/server/bootstrap/grant-config.js +0 -140
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { strict: assert } = require('assert');
4
4
  const jwt = require('jsonwebtoken');
5
+ const urljoin = require('url-join');
5
6
  const jwkToPem = require('jwk-to-pem');
6
7
 
7
8
  const getCognitoPayload = async ({ idToken, jwksUrl, purest }) => {
@@ -45,330 +46,519 @@ const getCognitoPayload = async ({ idToken, jwksUrl, purest }) => {
45
46
  }
46
47
  };
47
48
 
48
- const getInitialProviders = ({ purest }) => ({
49
- async discord({ accessToken }) {
50
- const discord = purest({ provider: 'discord' });
51
-
52
- return discord
53
- .get('users/@me')
54
- .auth(accessToken)
55
- .request()
56
- .then(({ body }) => {
57
- // Combine username and discriminator because discord username is not unique
58
- const username = `${body.username}#${body.discriminator}`;
59
- return {
60
- username,
61
- email: body.email,
62
- };
63
- });
49
+ const initProviders = ({ baseURL, purest }) => ({
50
+ email: {
51
+ enabled: true,
52
+ icon: 'envelope',
53
+ grantConfig: {},
64
54
  },
65
- async cognito({ query, providers }) {
66
- const jwksUrl = new URL(providers.cognito.jwksurl);
67
- const idToken = query.id_token;
68
- const tokenPayload = await getCognitoPayload({ idToken, jwksUrl, purest });
69
- return {
70
- username: tokenPayload['cognito:username'],
71
- email: tokenPayload.email,
72
- };
55
+ discord: {
56
+ enabled: false,
57
+ icon: 'discord',
58
+ grantConfig: {
59
+ key: '',
60
+ secret: '',
61
+ callbackUrl: `${baseURL}/discord/callback`,
62
+ scope: ['identify', 'email'],
63
+ },
64
+ async authCallback({ accessToken }) {
65
+ const discord = purest({ provider: 'discord' });
66
+
67
+ return discord
68
+ .get('users/@me')
69
+ .auth(accessToken)
70
+ .request()
71
+ .then(({ body }) => {
72
+ // Combine username and discriminator because discord username is not unique
73
+ const username = `${body.username}#${body.discriminator}`;
74
+ return {
75
+ username,
76
+ email: body.email,
77
+ };
78
+ });
79
+ },
73
80
  },
74
- async facebook({ accessToken }) {
75
- const facebook = purest({ provider: 'facebook' });
76
-
77
- return facebook
78
- .get('me')
79
- .auth(accessToken)
80
- .qs({ fields: 'name,email' })
81
- .request()
82
- .then(({ body }) => ({
83
- username: body.name,
84
- email: body.email,
85
- }));
81
+ facebook: {
82
+ enabled: false,
83
+ icon: 'facebook-square',
84
+ grantConfig: {
85
+ key: '',
86
+ secret: '',
87
+ callbackUrl: `${baseURL}/facebook/callback`,
88
+ scope: ['email'],
89
+ },
90
+ async authCallback({ accessToken }) {
91
+ const facebook = purest({ provider: 'facebook' });
92
+
93
+ return facebook
94
+ .get('me')
95
+ .auth(accessToken)
96
+ .qs({ fields: 'name,email' })
97
+ .request()
98
+ .then(({ body }) => ({
99
+ username: body.name,
100
+ email: body.email,
101
+ }));
102
+ },
86
103
  },
87
- async google({ accessToken }) {
88
- const google = purest({ provider: 'google' });
89
-
90
- return google
91
- .query('oauth')
92
- .get('tokeninfo')
93
- .qs({ accessToken })
94
- .request()
95
- .then(({ body }) => ({
96
- username: body.email.split('@')[0],
97
- email: body.email,
98
- }));
104
+ google: {
105
+ enabled: false,
106
+ icon: 'google',
107
+ grantConfig: {
108
+ key: '',
109
+ secret: '',
110
+ callbackUrl: `${baseURL}/google/callback`,
111
+ scope: ['email'],
112
+ },
113
+ async authCallback({ accessToken }) {
114
+ const google = purest({ provider: 'google' });
115
+
116
+ return google
117
+ .query('oauth')
118
+ .get('tokeninfo')
119
+ .qs({ accessToken })
120
+ .request()
121
+ .then(({ body }) => ({
122
+ username: body.email.split('@')[0],
123
+ email: body.email,
124
+ }));
125
+ },
99
126
  },
100
- async github({ accessToken }) {
101
- const github = purest({
102
- provider: 'github',
103
- defaults: {
104
- headers: {
105
- 'user-agent': 'strapi',
127
+ github: {
128
+ enabled: false,
129
+ icon: 'github',
130
+ grantConfig: {
131
+ key: '',
132
+ secret: '',
133
+ callbackUrl: `${baseURL}/github/callback`,
134
+ scope: ['user', 'user:email'],
135
+ },
136
+ async authCallback({ accessToken }) {
137
+ const github = purest({
138
+ provider: 'github',
139
+ defaults: {
140
+ headers: {
141
+ 'user-agent': 'strapi',
142
+ },
106
143
  },
107
- },
108
- });
144
+ });
145
+
146
+ const { body: userBody } = await github.get('user').auth(accessToken).request();
109
147
 
110
- const { body: userBody } = await github.get('user').auth(accessToken).request();
148
+ // This is the public email on the github profile
149
+ if (userBody.email) {
150
+ return {
151
+ username: userBody.login,
152
+ email: userBody.email,
153
+ };
154
+ }
155
+ // Get the email with Github's user/emails API
156
+ const { body: emailBody } = await github.get('user/emails').auth(accessToken).request();
111
157
 
112
- // This is the public email on the github profile
113
- if (userBody.email) {
114
158
  return {
115
159
  username: userBody.login,
116
- email: userBody.email,
160
+ email: Array.isArray(emailBody)
161
+ ? emailBody.find((email) => email.primary === true).email
162
+ : null,
117
163
  };
118
- }
119
- // Get the email with Github's user/emails API
120
- const { body: emailBody } = await github.get('user/emails').auth(accessToken).request();
121
-
122
- return {
123
- username: userBody.login,
124
- email: Array.isArray(emailBody)
125
- ? emailBody.find((email) => email.primary === true).email
126
- : null,
127
- };
164
+ },
128
165
  },
129
- async microsoft({ accessToken }) {
130
- const microsoft = purest({ provider: 'microsoft' });
131
-
132
- return microsoft
133
- .get('me')
134
- .auth(accessToken)
135
- .request()
136
- .then(({ body }) => ({
137
- username: body.userPrincipalName,
138
- email: body.userPrincipalName,
139
- }));
166
+ microsoft: {
167
+ enabled: false,
168
+ icon: 'windows',
169
+ grantConfig: {
170
+ key: '',
171
+ secret: '',
172
+ callbackUrl: `${baseURL}/microsoft/callback`,
173
+ scope: ['user.read'],
174
+ },
175
+ async authCallback({ accessToken }) {
176
+ const microsoft = purest({ provider: 'microsoft' });
177
+
178
+ return microsoft
179
+ .get('me')
180
+ .auth(accessToken)
181
+ .request()
182
+ .then(({ body }) => ({
183
+ username: body.userPrincipalName,
184
+ email: body.userPrincipalName,
185
+ }));
186
+ },
140
187
  },
141
- async twitter({ accessToken, query, providers }) {
142
- const twitter = purest({
143
- provider: 'twitter',
144
- defaults: {
145
- oauth: {
146
- consumer_key: providers.twitter.key,
147
- consumer_secret: providers.twitter.secret,
188
+
189
+ twitter: {
190
+ enabled: false,
191
+ icon: 'twitter',
192
+ grantConfig: {
193
+ key: '',
194
+ secret: '',
195
+ callbackUrl: `${baseURL}/twitter/callback`,
196
+ },
197
+ async authCallback({ accessToken, query, providers }) {
198
+ const twitter = purest({
199
+ provider: 'twitter',
200
+ defaults: {
201
+ oauth: {
202
+ consumer_key: providers.twitter.key,
203
+ consumer_secret: providers.twitter.secret,
204
+ },
148
205
  },
149
- },
150
- });
206
+ });
151
207
 
152
- return twitter
153
- .get('account/verify_credentials')
154
- .auth(accessToken, query.access_secret)
155
- .qs({ screen_name: query['raw[screen_name]'], include_email: 'true' })
156
- .request()
157
- .then(({ body }) => ({
158
- username: body.screen_name,
159
- email: body.email,
160
- }));
208
+ return twitter
209
+ .get('account/verify_credentials')
210
+ .auth(accessToken, query.access_secret)
211
+ .qs({ screen_name: query['raw[screen_name]'], include_email: 'true' })
212
+ .request()
213
+ .then(({ body }) => ({
214
+ username: body.screen_name,
215
+ email: body.email,
216
+ }));
217
+ },
161
218
  },
162
- async instagram({ accessToken }) {
163
- const instagram = purest({ provider: 'instagram' });
164
-
165
- return instagram
166
- .get('me')
167
- .auth(accessToken)
168
- .qs({ fields: 'id,username' })
169
- .request()
170
- .then(({ body }) => ({
171
- username: body.username,
172
- email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
173
- }));
219
+ instagram: {
220
+ enabled: false,
221
+ icon: 'instagram',
222
+ grantConfig: {
223
+ key: '',
224
+ secret: '',
225
+ callbackUrl: `${baseURL}/instagram/callback`,
226
+ scope: ['user_profile'],
227
+ },
228
+ async authCallback({ accessToken }) {
229
+ const instagram = purest({ provider: 'instagram' });
230
+
231
+ return instagram
232
+ .get('me')
233
+ .auth(accessToken)
234
+ .qs({ fields: 'id,username' })
235
+ .request()
236
+ .then(({ body }) => ({
237
+ username: body.username,
238
+ email: `${body.username}@strapi.io`, // dummy email as Instagram does not provide user email
239
+ }));
240
+ },
174
241
  },
175
- async vk({ accessToken, query }) {
176
- const vk = purest({ provider: 'vk' });
177
-
178
- return vk
179
- .get('users')
180
- .auth(accessToken)
181
- .qs({ id: query.raw.user_id, v: '5.122' })
182
- .request()
183
- .then(({ body }) => ({
184
- username: `${body.response[0].last_name} ${body.response[0].first_name}`,
185
- email: query.raw.email,
186
- }));
242
+ vk: {
243
+ enabled: false,
244
+ icon: 'vk',
245
+ grantConfig: {
246
+ key: '',
247
+ secret: '',
248
+ callbackUrl: `${baseURL}/vk/callback`,
249
+ scope: ['email'],
250
+ },
251
+ async authCallback({ accessToken, query }) {
252
+ const vk = purest({ provider: 'vk' });
253
+
254
+ return vk
255
+ .get('users')
256
+ .auth(accessToken)
257
+ .qs({ id: query.raw.user_id, v: '5.122' })
258
+ .request()
259
+ .then(({ body }) => ({
260
+ username: `${body.response[0].last_name} ${body.response[0].first_name}`,
261
+ email: query.raw.email,
262
+ }));
263
+ },
187
264
  },
188
- async twitch({ accessToken, providers }) {
189
- const twitch = purest({
190
- provider: 'twitch',
191
- config: {
192
- twitch: {
193
- default: {
194
- origin: 'https://api.twitch.tv',
195
- path: 'helix/{path}',
196
- headers: {
197
- Authorization: 'Bearer {auth}',
198
- 'Client-Id': '{auth}',
265
+
266
+ twitch: {
267
+ enabled: false,
268
+ icon: 'twitch',
269
+ grantConfig: {
270
+ key: '',
271
+ secret: '',
272
+ callbackUrl: `${baseURL}/twitch/callback`,
273
+ scope: ['user:read:email'],
274
+ },
275
+ async authCallback({ accessToken, providers }) {
276
+ const twitch = purest({
277
+ provider: 'twitch',
278
+ config: {
279
+ twitch: {
280
+ default: {
281
+ origin: 'https://api.twitch.tv',
282
+ path: 'helix/{path}',
283
+ headers: {
284
+ Authorization: 'Bearer {auth}',
285
+ 'Client-Id': '{auth}',
286
+ },
199
287
  },
200
288
  },
201
289
  },
202
- },
203
- });
290
+ });
204
291
 
205
- return twitch
206
- .get('users')
207
- .auth(accessToken, providers.twitch.key)
208
- .request()
209
- .then(({ body }) => ({
210
- username: body.data[0].login,
211
- email: body.data[0].email,
212
- }));
292
+ return twitch
293
+ .get('users')
294
+ .auth(accessToken, providers.twitch.key)
295
+ .request()
296
+ .then(({ body }) => ({
297
+ username: body.data[0].login,
298
+ email: body.data[0].email,
299
+ }));
300
+ },
213
301
  },
214
- async linkedin({ accessToken }) {
215
- const linkedIn = purest({ provider: 'linkedin' });
216
- const {
217
- body: { localizedFirstName },
218
- } = await linkedIn.get('me').auth(accessToken).request();
219
- const {
220
- body: { elements },
221
- } = await linkedIn
222
- .get('emailAddress?q=members&projection=(elements*(handle~))')
223
- .auth(accessToken)
224
- .request();
225
-
226
- const email = elements[0]['handle~'];
227
-
228
- return {
229
- username: localizedFirstName,
230
- email: email.emailAddress,
231
- };
302
+
303
+ linkedin: {
304
+ enabled: false,
305
+ icon: 'linkedin',
306
+ grantConfig: {
307
+ key: '',
308
+ secret: '',
309
+ callbackUrl: `${baseURL}/linkedin/callback`,
310
+ scope: ['r_liteprofile', 'r_emailaddress'],
311
+ },
312
+ async authCallback({ accessToken }) {
313
+ const linkedIn = purest({ provider: 'linkedin' });
314
+ const {
315
+ body: { localizedFirstName },
316
+ } = await linkedIn.get('me').auth(accessToken).request();
317
+ const {
318
+ body: { elements },
319
+ } = await linkedIn
320
+ .get('emailAddress?q=members&projection=(elements*(handle~))')
321
+ .auth(accessToken)
322
+ .request();
323
+
324
+ const email = elements[0]['handle~'];
325
+
326
+ return {
327
+ username: localizedFirstName,
328
+ email: email.emailAddress,
329
+ };
330
+ },
331
+ },
332
+
333
+ cognito: {
334
+ enabled: false,
335
+ icon: 'aws',
336
+ grantConfig: {
337
+ key: '',
338
+ secret: '',
339
+ subdomain: 'my.subdomain.com',
340
+ callback: `${baseURL}/cognito/callback`,
341
+ scope: ['email', 'openid', 'profile'],
342
+ },
343
+ async authCallback({ query, providers }) {
344
+ const jwksUrl = new URL(providers.cognito.jwksurl);
345
+ const idToken = query.id_token;
346
+ const tokenPayload = await getCognitoPayload({ idToken, jwksUrl, purest });
347
+ return {
348
+ username: tokenPayload['cognito:username'],
349
+ email: tokenPayload.email,
350
+ };
351
+ },
232
352
  },
233
- async reddit({ accessToken }) {
234
- const reddit = purest({
235
- provider: 'reddit',
236
- config: {
237
- reddit: {
238
- default: {
239
- origin: 'https://oauth.reddit.com',
240
- path: 'api/{version}/{path}',
241
- version: 'v1',
242
- headers: {
243
- Authorization: 'Bearer {auth}',
244
- 'user-agent': 'strapi',
353
+
354
+ reddit: {
355
+ enabled: false,
356
+ icon: 'reddit',
357
+ grantConfig: {
358
+ key: '',
359
+ secret: '',
360
+ callback: `${baseURL}/reddit/callback`,
361
+ scope: ['identity'],
362
+ },
363
+ async authCallback({ accessToken }) {
364
+ const reddit = purest({
365
+ provider: 'reddit',
366
+ config: {
367
+ reddit: {
368
+ default: {
369
+ origin: 'https://oauth.reddit.com',
370
+ path: 'api/{version}/{path}',
371
+ version: 'v1',
372
+ headers: {
373
+ Authorization: 'Bearer {auth}',
374
+ 'user-agent': 'strapi',
375
+ },
245
376
  },
246
377
  },
247
378
  },
248
- },
249
- });
379
+ });
250
380
 
251
- return reddit
252
- .get('me')
253
- .auth(accessToken)
254
- .request()
255
- .then(({ body }) => ({
256
- username: body.name,
257
- email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
258
- }));
381
+ return reddit
382
+ .get('me')
383
+ .auth(accessToken)
384
+ .request()
385
+ .then(({ body }) => ({
386
+ username: body.name,
387
+ email: `${body.name}@strapi.io`, // dummy email as Reddit does not provide user email
388
+ }));
389
+ },
259
390
  },
260
- async auth0({ accessToken, providers }) {
261
- const auth0 = purest({ provider: 'auth0' });
262
-
263
- return auth0
264
- .get('userinfo')
265
- .subdomain(providers.auth0.subdomain)
266
- .auth(accessToken)
267
- .request()
268
- .then(({ body }) => {
269
- const username = body.username || body.nickname || body.name || body.email.split('@')[0];
270
- const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
271
391
 
272
- return {
273
- username,
274
- email,
275
- };
276
- });
392
+ auth0: {
393
+ enabled: false,
394
+ icon: '',
395
+ grantConfig: {
396
+ key: '',
397
+ secret: '',
398
+ subdomain: 'my-tenant.eu',
399
+ callback: `${baseURL}/auth0/callback`,
400
+ scope: ['openid', 'email', 'profile'],
401
+ },
402
+ async authCallback({ accessToken, providers }) {
403
+ const auth0 = purest({ provider: 'auth0' });
404
+
405
+ return auth0
406
+ .get('userinfo')
407
+ .subdomain(providers.auth0.subdomain)
408
+ .auth(accessToken)
409
+ .request()
410
+ .then(({ body }) => {
411
+ const username = body.username || body.nickname || body.name || body.email.split('@')[0];
412
+ const email = body.email || `${username.replace(/\s+/g, '.')}@strapi.io`;
413
+
414
+ return {
415
+ username,
416
+ email,
417
+ };
418
+ });
419
+ },
277
420
  },
278
- async cas({ accessToken, providers }) {
279
- const cas = purest({ provider: 'cas' });
280
-
281
- return cas
282
- .get('oidc/profile')
283
- .subdomain(providers.cas.subdomain)
284
- .auth(accessToken)
285
- .request()
286
- .then(({ body }) => {
287
- // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
288
- const username = body.attributes
289
- ? body.attributes.strapiusername || body.id || body.sub
290
- : body.strapiusername || body.id || body.sub;
291
- const email = body.attributes
292
- ? body.attributes.strapiemail || body.attributes.email
293
- : body.strapiemail || body.email;
294
- if (!username || !email) {
295
- strapi.log.warn(
296
- `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`
297
- );
298
- }
299
- return {
300
- username,
301
- email,
302
- };
303
- });
421
+
422
+ cas: {
423
+ enabled: false,
424
+ icon: 'book',
425
+ grantConfig: {
426
+ key: '',
427
+ secret: '',
428
+ callback: `${baseURL}/cas/callback`,
429
+ scope: ['openid email'], // scopes should be space delimited
430
+ subdomain: 'my.subdomain.com/cas',
431
+ },
432
+ async authCallback({ accessToken, providers }) {
433
+ const cas = purest({ provider: 'cas' });
434
+
435
+ return cas
436
+ .get('oidc/profile')
437
+ .subdomain(providers.cas.subdomain)
438
+ .auth(accessToken)
439
+ .request()
440
+ .then(({ body }) => {
441
+ // CAS attribute may be in body.attributes or "FLAT", depending on CAS config
442
+ const username = body.attributes
443
+ ? body.attributes.strapiusername || body.id || body.sub
444
+ : body.strapiusername || body.id || body.sub;
445
+ const email = body.attributes
446
+ ? body.attributes.strapiemail || body.attributes.email
447
+ : body.strapiemail || body.email;
448
+ if (!username || !email) {
449
+ strapi.log.warn(
450
+ `CAS Response Body did not contain required attributes: ${JSON.stringify(body)}`
451
+ );
452
+ }
453
+ return {
454
+ username,
455
+ email,
456
+ };
457
+ });
458
+ },
304
459
  },
305
- async patreon({ accessToken }) {
306
- const patreon = purest({
307
- provider: 'patreon',
308
- config: {
309
- patreon: {
310
- default: {
311
- origin: 'https://www.patreon.com',
312
- path: 'api/oauth2/{path}',
313
- headers: {
314
- authorization: 'Bearer {auth}',
460
+
461
+ patreon: {
462
+ enabled: false,
463
+ icon: '',
464
+ grantConfig: {
465
+ key: '',
466
+ secret: '',
467
+ callback: `${baseURL}/patreon/callback`,
468
+ scope: ['identity', 'identity[email]'],
469
+ },
470
+ async authCallback({ accessToken }) {
471
+ const patreon = purest({
472
+ provider: 'patreon',
473
+ config: {
474
+ patreon: {
475
+ default: {
476
+ origin: 'https://www.patreon.com',
477
+ path: 'api/oauth2/{path}',
478
+ headers: {
479
+ authorization: 'Bearer {auth}',
480
+ },
315
481
  },
316
482
  },
317
483
  },
318
- },
319
- });
320
-
321
- return patreon
322
- .get('v2/identity')
323
- .auth(accessToken)
324
- .qs(new URLSearchParams({ 'fields[user]': 'full_name,email' }).toString())
325
- .request()
326
- .then(({ body }) => {
327
- const patreonData = body.data.attributes;
328
- return {
329
- username: patreonData.full_name,
330
- email: patreonData.email,
331
- };
332
484
  });
485
+
486
+ return patreon
487
+ .get('v2/identity')
488
+ .auth(accessToken)
489
+ .qs(new URLSearchParams({ 'fields[user]': 'full_name,email' }).toString())
490
+ .request()
491
+ .then(({ body }) => {
492
+ const patreonData = body.data.attributes;
493
+ return {
494
+ username: patreonData.full_name,
495
+ email: patreonData.email,
496
+ };
497
+ });
498
+ },
333
499
  },
334
- async keycloak({ accessToken, providers }) {
335
- const keycloak = purest({ provider: 'keycloak' });
336
-
337
- return keycloak
338
- .subdomain(providers.keycloak.subdomain)
339
- .get('protocol/openid-connect/userinfo')
340
- .auth(accessToken)
341
- .request()
342
- .then(({ body }) => {
343
- return {
344
- username: body.preferred_username,
345
- email: body.email,
346
- };
347
- });
500
+ keycloack: {
501
+ enabled: false,
502
+ icon: '',
503
+ grantConfig: {
504
+ key: '',
505
+ secret: '',
506
+ subdomain: 'myKeycloakProvider.com/realms/myrealm',
507
+ callback: `${baseURL}/keycloak/callback`,
508
+ scope: ['openid', 'email', 'profile'],
509
+ },
510
+ async authCallback({ accessToken, providers }) {
511
+ const keycloak = purest({ provider: 'keycloak' });
512
+
513
+ return keycloak
514
+ .subdomain(providers.keycloak.subdomain)
515
+ .get('protocol/openid-connect/userinfo')
516
+ .auth(accessToken)
517
+ .request()
518
+ .then(({ body }) => {
519
+ return {
520
+ username: body.preferred_username,
521
+ email: body.email,
522
+ };
523
+ });
524
+ },
348
525
  },
349
526
  });
350
527
 
351
528
  module.exports = () => {
352
529
  const purest = require('purest');
353
530
 
354
- const providersCallbacks = getInitialProviders({ purest });
531
+ const apiPrefix = strapi.config.get('api.rest.prefix');
532
+ const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
355
533
 
356
- return {
357
- register(providerName, provider) {
358
- assert(typeof providerName === 'string', 'Provider name must be a string');
359
- assert(typeof provider === 'function', 'Provider callback must be a function');
534
+ const authProviders = initProviders({ baseURL, purest });
360
535
 
361
- providersCallbacks[providerName] = provider({ purest });
536
+ /**
537
+ * @public
538
+ */
539
+ return {
540
+ getAll() {
541
+ return authProviders;
542
+ },
543
+ get(name) {
544
+ return authProviders[name];
545
+ },
546
+ add(name, config) {
547
+ authProviders[name] = config;
548
+ },
549
+ remove(name) {
550
+ delete authProviders[name];
362
551
  },
363
552
 
553
+ /**
554
+ * @internal
555
+ */
364
556
  async run({ provider, accessToken, query, providers }) {
365
- if (!providersCallbacks[provider]) {
366
- throw new Error('Unknown provider.');
367
- }
557
+ const authProvider = authProviders[provider];
368
558
 
369
- const providerCb = providersCallbacks[provider];
559
+ assert(authProvider, 'Unknown auth provider');
370
560
 
371
- return providerCb({ accessToken, query, providers });
561
+ return authProvider.authCallback({ accessToken, query, providers, purest });
372
562
  },
373
563
  };
374
564
  };