@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.
- package/dist/_chunks/{index-iaebB1BT.js → index-B1qzCQd5.js} +8 -8
- package/dist/_chunks/{index-iaebB1BT.js.map → index-B1qzCQd5.js.map} +1 -1
- package/dist/_chunks/{index-DVEZVDjs.js → index-BrHOhLiu.js} +2 -2
- package/dist/_chunks/{index-DVEZVDjs.js.map → index-BrHOhLiu.js.map} +1 -1
- package/dist/_chunks/{index-DCFIfSfa.mjs → index-CGwt3Ia4.mjs} +3 -3
- package/dist/_chunks/{index-DCFIfSfa.mjs.map → index-CGwt3Ia4.mjs.map} +1 -1
- package/dist/_chunks/{index-iSLj9xJT.js → index-Cp4WQ7CY.js} +2 -2
- package/dist/_chunks/{index-iSLj9xJT.js.map → index-Cp4WQ7CY.js.map} +1 -1
- package/dist/_chunks/{index-DRoVF6Y7.js → index-CxY6jE0v.js} +7 -7
- package/dist/_chunks/{index-DRoVF6Y7.js.map → index-CxY6jE0v.js.map} +1 -1
- package/dist/_chunks/{index-iMO1GC3n.js → index-D-gXJApn.js} +4 -4
- package/dist/_chunks/{index-iMO1GC3n.js.map → index-D-gXJApn.js.map} +1 -1
- package/dist/_chunks/{index-Cf2sMpyd.mjs → index-DUjTQKud.mjs} +8 -8
- package/dist/_chunks/{index-Cf2sMpyd.mjs.map → index-DUjTQKud.mjs.map} +1 -1
- package/dist/_chunks/{index-qhy_K2pJ.mjs → index-DkSluM9h.mjs} +2 -2
- package/dist/_chunks/{index-qhy_K2pJ.mjs.map → index-DkSluM9h.mjs.map} +1 -1
- package/dist/_chunks/{index-zmcUQlrv.mjs → index-Dt46aAk-.mjs} +3 -3
- package/dist/_chunks/{index-zmcUQlrv.mjs.map → index-Dt46aAk-.mjs.map} +1 -1
- package/dist/_chunks/{index-B9OX-a4A.mjs → index-_XxxzBHB.mjs} +2 -2
- package/dist/_chunks/{index-B9OX-a4A.mjs.map → index-_XxxzBHB.mjs.map} +1 -1
- package/dist/_chunks/{index-8-k5RCnK-BHUgmsKx.mjs → index-m_rp3iqs-BHUgmsKx.mjs} +1 -1
- package/dist/_chunks/{index-8-k5RCnK-BHUgmsKx.mjs.map → index-m_rp3iqs-BHUgmsKx.mjs.map} +1 -1
- package/dist/_chunks/{index-8-k5RCnK-qR3QHvSP.js → index-m_rp3iqs-qR3QHvSP.js} +1 -1
- package/dist/_chunks/{index-8-k5RCnK-qR3QHvSP.js.map → index-m_rp3iqs-qR3QHvSP.js.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/package.json +4 -4
- package/server/bootstrap/index.js +13 -9
- package/server/services/providers-registry.js +465 -275
- package/server/utils/index.d.ts +2 -1
- 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
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
.
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
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
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
|
531
|
+
const apiPrefix = strapi.config.get('api.rest.prefix');
|
|
532
|
+
const baseURL = urljoin(strapi.config.server.url, apiPrefix, 'auth');
|
|
355
533
|
|
|
356
|
-
|
|
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
|
-
|
|
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
|
-
|
|
366
|
-
throw new Error('Unknown provider.');
|
|
367
|
-
}
|
|
557
|
+
const authProvider = authProviders[provider];
|
|
368
558
|
|
|
369
|
-
|
|
559
|
+
assert(authProvider, 'Unknown auth provider');
|
|
370
560
|
|
|
371
|
-
return
|
|
561
|
+
return authProvider.authCallback({ accessToken, query, providers, purest });
|
|
372
562
|
},
|
|
373
563
|
};
|
|
374
564
|
};
|