@hapi/bell 13.1.0 → 13.2.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/lib/index.d.ts +14 -6
- package/lib/index.js +4 -3
- package/lib/oauth.js +39 -11
- package/package.json +11 -11
package/lib/index.d.ts
CHANGED
|
@@ -88,7 +88,7 @@ export interface OptionalOptions {
|
|
|
88
88
|
* * Twitter supports `force_login`, `screen_name`.
|
|
89
89
|
* * Linkedin supports `fields`.
|
|
90
90
|
*/
|
|
91
|
-
providerParams?: StringLikeMap | ((request: Request) => StringLikeMap) | undefined;
|
|
91
|
+
providerParams?: StringLikeMap | ((request: Request) => StringLikeMap | Promise<StringLikeMap>) | undefined;
|
|
92
92
|
/**
|
|
93
93
|
* allows passing query parameters from a bell protected endpoint to the auth request.
|
|
94
94
|
* It will merge the query params you pass along with the providerParams and any other predefined ones.
|
|
@@ -129,7 +129,7 @@ export interface OptionalOptions {
|
|
|
129
129
|
* It may be passed either as an object to merge into the query string,
|
|
130
130
|
* or a function which takes the client's request and returns an object.
|
|
131
131
|
*/
|
|
132
|
-
tokenParams?: StringLikeMap | ((request: Request) => StringLikeMap) | undefined;
|
|
132
|
+
tokenParams?: StringLikeMap | ((request: Request) => StringLikeMap | Promise<StringLikeMap>) | undefined;
|
|
133
133
|
/**
|
|
134
134
|
* an object of key-value pairs that specify additional
|
|
135
135
|
* URL query parameters to send with the profile request to the provider.
|
|
@@ -204,6 +204,12 @@ export interface Credentials2 extends Credentials {
|
|
|
204
204
|
expiresIn?: number | undefined;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* an endpoint URI, or a function of the request returning one.
|
|
209
|
+
* @param request the hapi request object being authenticated.
|
|
210
|
+
*/
|
|
211
|
+
export type ProviderUri = string | ((request: Request) => string | Promise<string>);
|
|
212
|
+
|
|
207
213
|
export interface CustomProtocol {
|
|
208
214
|
/**
|
|
209
215
|
* The name of the protocol.
|
|
@@ -213,11 +219,11 @@ export interface CustomProtocol {
|
|
|
213
219
|
/**
|
|
214
220
|
* the authorization endpoint URI.
|
|
215
221
|
*/
|
|
216
|
-
auth:
|
|
222
|
+
auth: ProviderUri;
|
|
217
223
|
/**
|
|
218
224
|
* the access token endpoint URI.
|
|
219
225
|
*/
|
|
220
|
-
token:
|
|
226
|
+
token: ProviderUri;
|
|
221
227
|
/**
|
|
222
228
|
* a headers object with additional headers required by the provider
|
|
223
229
|
* (e.g. GitHub required the 'User-Agent' header which is set by default).
|
|
@@ -233,12 +239,14 @@ export interface CustomProtocol {
|
|
|
233
239
|
* Change the object directly within the function (profile information is typically stored under credentials.profile).
|
|
234
240
|
* @param params the parsed information received from the provider (e.g. token, secret, and other custom fields).
|
|
235
241
|
* @param get an OAuth helper function to make authenticated requests using the credentials received.
|
|
242
|
+
* @param request the hapi request object of the authorization callback.
|
|
236
243
|
*/
|
|
237
244
|
export type ProfileGetter<C extends Credentials> = (
|
|
238
245
|
this: CustomProviderOptions,
|
|
239
246
|
credentials: C,
|
|
240
247
|
params: { [key: string]: string },
|
|
241
248
|
get: AuthedRequest,
|
|
249
|
+
request: Request,
|
|
242
250
|
) => Promise<void>;
|
|
243
251
|
|
|
244
252
|
export interface CustomProtocol1 extends CustomProtocol {
|
|
@@ -256,7 +264,7 @@ export interface CustomProtocol1 extends CustomProtocol {
|
|
|
256
264
|
/**
|
|
257
265
|
* the temporary credentials (request token) endpoint).
|
|
258
266
|
*/
|
|
259
|
-
temporary?:
|
|
267
|
+
temporary?: ProviderUri | undefined;
|
|
260
268
|
|
|
261
269
|
profile: ProfileGetter<Credentials1>;
|
|
262
270
|
}
|
|
@@ -307,4 +315,4 @@ export function simulate(credentialsFunc: RequestPassThrough): void;
|
|
|
307
315
|
* [See docs](https://github.com/hapijs/bell/blob/master/API.md#simulated-authentication)
|
|
308
316
|
* Disables simulation mode
|
|
309
317
|
*/
|
|
310
|
-
export function simulate(state: false): void;
|
|
318
|
+
export function simulate(state: false): void;
|
package/lib/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const Providers = require('./providers');
|
|
|
9
9
|
|
|
10
10
|
const internals = {
|
|
11
11
|
simulate: false,
|
|
12
|
+
endpoint: Joi.alternatives(Joi.string(), Joi.func()),
|
|
12
13
|
flexBoolean: Joi.boolean().truthy('yes', 1, '1').falsy('no', 0, '0')
|
|
13
14
|
};
|
|
14
15
|
|
|
@@ -38,8 +39,8 @@ exports.plugin = {
|
|
|
38
39
|
internals.provider = Joi.object({
|
|
39
40
|
name: Joi.string().optional().default('custom'),
|
|
40
41
|
protocol: ['oauth', 'oauth2'],
|
|
41
|
-
auth:
|
|
42
|
-
token:
|
|
42
|
+
auth: internals.endpoint.required(),
|
|
43
|
+
token: internals.endpoint.required(),
|
|
43
44
|
headers: Joi.object(),
|
|
44
45
|
profile: Joi.func(),
|
|
45
46
|
profileMethod: Joi.valid('get', 'post').default('get')
|
|
@@ -47,7 +48,7 @@ internals.provider = Joi.object({
|
|
|
47
48
|
.when('.protocol', {
|
|
48
49
|
is: 'oauth',
|
|
49
50
|
then: Joi.object({
|
|
50
|
-
temporary:
|
|
51
|
+
temporary: internals.endpoint.required(),
|
|
51
52
|
signatureMethod: Joi.valid('HMAC-SHA1', 'RSA-SHA1').default('HMAC-SHA1')
|
|
52
53
|
}),
|
|
53
54
|
otherwise: Joi.object({
|
package/lib/oauth.js
CHANGED
|
@@ -19,10 +19,16 @@ const internals = {
|
|
|
19
19
|
|
|
20
20
|
exports.v1 = function (settings) {
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// The client uses temporary and token, so we can share one unless either is a function
|
|
23
|
+
|
|
24
|
+
const shared = [settings.provider.temporary, settings.provider.token].some((endpoint) => typeof endpoint === 'function') ?
|
|
25
|
+
null :
|
|
26
|
+
new internals.Client(settings);
|
|
23
27
|
|
|
24
28
|
return async function (request, h) {
|
|
25
29
|
|
|
30
|
+
const client = shared ?? await internals.client(request, settings);
|
|
31
|
+
|
|
26
32
|
const cookie = settings.cookie;
|
|
27
33
|
const name = settings.name;
|
|
28
34
|
const protocol = internals.getProtocol(request, settings);
|
|
@@ -73,12 +79,13 @@ exports.v1 = function (settings) {
|
|
|
73
79
|
h.state(cookie, state);
|
|
74
80
|
|
|
75
81
|
const authQuery = {
|
|
76
|
-
...internals.resolveProviderParams(request, settings.providerParams),
|
|
82
|
+
...await internals.resolveProviderParams(request, settings.providerParams),
|
|
77
83
|
oauth_token: temp.oauth_token,
|
|
78
84
|
...(settings.allowRuntimeProviderParams && request.query)
|
|
79
85
|
};
|
|
80
86
|
|
|
81
|
-
|
|
87
|
+
const authUri = await internals.resolveProviderUri(request, settings.provider.auth);
|
|
88
|
+
return h.redirect(authUri + '?' + internals.queryString(authQuery)).takeover();
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
// Authorization callback
|
|
@@ -130,7 +137,7 @@ exports.v1 = function (settings) {
|
|
|
130
137
|
};
|
|
131
138
|
|
|
132
139
|
try {
|
|
133
|
-
await settings.provider.profile.call(settings, credentials, token, get);
|
|
140
|
+
await settings.provider.profile.call(settings, credentials, token, get, request);
|
|
134
141
|
}
|
|
135
142
|
catch (err) {
|
|
136
143
|
return h.unauthenticated(err, { credentials });
|
|
@@ -178,7 +185,7 @@ exports.v2 = function (settings) {
|
|
|
178
185
|
|
|
179
186
|
const nonce = Cryptiles.randomAlphanumString(internals.nonceLength);
|
|
180
187
|
const query = {
|
|
181
|
-
...internals.resolveProviderParams(request, settings.providerParams),
|
|
188
|
+
...await internals.resolveProviderParams(request, settings.providerParams),
|
|
182
189
|
...(settings.allowRuntimeProviderParams && request.query),
|
|
183
190
|
client_id: settings.clientId,
|
|
184
191
|
response_type: 'code',
|
|
@@ -227,7 +234,9 @@ exports.v2 = function (settings) {
|
|
|
227
234
|
}
|
|
228
235
|
|
|
229
236
|
h.state(cookie, state);
|
|
230
|
-
|
|
237
|
+
|
|
238
|
+
const authUri = await internals.resolveProviderUri(request, settings.provider.auth);
|
|
239
|
+
return h.redirect(authUri + '?' + internals.queryString(query)).takeover();
|
|
231
240
|
}
|
|
232
241
|
|
|
233
242
|
// Authorization callback
|
|
@@ -249,7 +258,7 @@ exports.v2 = function (settings) {
|
|
|
249
258
|
grant_type: 'authorization_code',
|
|
250
259
|
code: request.query.code,
|
|
251
260
|
redirect_uri: internals.location(request, protocol, settings.location),
|
|
252
|
-
...internals.resolveProviderParams(request, settings.tokenParams)
|
|
261
|
+
...await internals.resolveProviderParams(request, settings.tokenParams)
|
|
253
262
|
};
|
|
254
263
|
|
|
255
264
|
if (settings.provider.pkce) {
|
|
@@ -287,8 +296,9 @@ exports.v2 = function (settings) {
|
|
|
287
296
|
|
|
288
297
|
// Obtain token
|
|
289
298
|
|
|
299
|
+
const tokenUri = await internals.resolveProviderUri(request, settings.provider.token);
|
|
290
300
|
try {
|
|
291
|
-
var { res: tokenRes, payload } = await Wreck.post(
|
|
301
|
+
var { res: tokenRes, payload } = await Wreck.post(tokenUri, requestOptions);
|
|
292
302
|
}
|
|
293
303
|
catch (err) {
|
|
294
304
|
return h.unauthenticated(Boom.internal('Failed obtaining ' + name + ' access token', err), { credentials });
|
|
@@ -358,7 +368,7 @@ exports.v2 = function (settings) {
|
|
|
358
368
|
};
|
|
359
369
|
|
|
360
370
|
try {
|
|
361
|
-
await settings.provider.profile.call(settings, credentials, payload, get);
|
|
371
|
+
await settings.provider.profile.call(settings, credentials, payload, get, request);
|
|
362
372
|
}
|
|
363
373
|
catch (err) {
|
|
364
374
|
return h.unauthenticated(err, { credentials });
|
|
@@ -727,7 +737,25 @@ internals.getProtocol = function (request, settings) {
|
|
|
727
737
|
};
|
|
728
738
|
|
|
729
739
|
|
|
730
|
-
internals.resolveProviderParams = function (request, params) {
|
|
740
|
+
internals.resolveProviderParams = async function (request, params) {
|
|
741
|
+
|
|
742
|
+
return (typeof params === 'function' ? await params(request) : params) ?? {};
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
internals.resolveProviderUri = async function (request, uri) {
|
|
747
|
+
|
|
748
|
+
return typeof uri === 'function' ? await uri(request) : uri;
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
internals.client = async function (request, settings) {
|
|
753
|
+
|
|
754
|
+
const provider = {
|
|
755
|
+
...settings.provider,
|
|
756
|
+
temporary: await internals.resolveProviderUri(request, settings.provider.temporary),
|
|
757
|
+
token: await internals.resolveProviderUri(request, settings.provider.token)
|
|
758
|
+
};
|
|
731
759
|
|
|
732
|
-
return
|
|
760
|
+
return new internals.Client({ ...settings, provider });
|
|
733
761
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hapi/bell",
|
|
3
3
|
"description": "Third-party login plugin for hapi",
|
|
4
|
-
"version": "13.
|
|
4
|
+
"version": "13.2.0",
|
|
5
5
|
"repository": "git://github.com/hapijs/bell",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
@@ -51,21 +51,21 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@hapi/boom": "^10.0.1",
|
|
54
|
-
"@hapi/bounce": "^3.0.
|
|
55
|
-
"@hapi/cryptiles": "^6.0.
|
|
56
|
-
"@hapi/hoek": "^11.0.
|
|
57
|
-
"@hapi/wreck": "^18.
|
|
58
|
-
"joi": "^17.7
|
|
54
|
+
"@hapi/bounce": "^3.0.2",
|
|
55
|
+
"@hapi/cryptiles": "^6.0.3",
|
|
56
|
+
"@hapi/hoek": "^11.0.7",
|
|
57
|
+
"@hapi/wreck": "^18.1.2",
|
|
58
|
+
"joi": "^17.13.7"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@hapi/code": "^9.0.3",
|
|
62
62
|
"@hapi/eslint-plugin": "^6.0.0",
|
|
63
|
-
"@hapi/hapi": "^21.
|
|
63
|
+
"@hapi/hapi": "^21.4.10",
|
|
64
64
|
"@hapi/hawk": "^8.0.0",
|
|
65
|
-
"@hapi/lab": "^25.
|
|
66
|
-
"@hapi/teamwork": "^6.0.
|
|
67
|
-
"@types/node": "^20.
|
|
68
|
-
"typescript": "^
|
|
65
|
+
"@hapi/lab": "^25.3.2",
|
|
66
|
+
"@hapi/teamwork": "^6.0.1",
|
|
67
|
+
"@types/node": "^20.19.43",
|
|
68
|
+
"typescript": "^6.0.3"
|
|
69
69
|
},
|
|
70
70
|
"scripts": {
|
|
71
71
|
"test": "lab -a @hapi/code -t 100 -L -m 3000 -Y",
|