@drawbridge/drawbridge-utils 0.0.48 → 0.0.50
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/oauth/index.cjs +9 -1
- package/dist/oauth/index.d.cts +23 -3
- package/dist/oauth/index.d.ts +23 -3
- package/dist/oauth/index.js +9 -1
- package/dist/oauth/server.cjs +29 -28
- package/dist/oauth/server.d.cts +41 -32
- package/dist/oauth/server.d.ts +41 -32
- package/dist/oauth/server.js +29 -28
- package/package.json +1 -1
package/dist/oauth/index.cjs
CHANGED
|
@@ -115,7 +115,15 @@ var cookieOptions = ({
|
|
|
115
115
|
secure: process.env.NODE_ENV !== "development",
|
|
116
116
|
...expiresAt && { expires: new Date(expiresAt) }
|
|
117
117
|
});
|
|
118
|
-
var menuEndpoint = (type,
|
|
118
|
+
var menuEndpoint = (type, ...ids) => {
|
|
119
|
+
if (type === "campaign") {
|
|
120
|
+
const [organization, campaign] = ids;
|
|
121
|
+
return "/menu/organization/" + organization + "/campaign/" + campaign;
|
|
122
|
+
}
|
|
123
|
+
;
|
|
124
|
+
const [id] = ids;
|
|
125
|
+
return "/menu/" + type + (id ? "/" + id : "");
|
|
126
|
+
};
|
|
119
127
|
var scopes = [
|
|
120
128
|
"profile:read",
|
|
121
129
|
"profile:write",
|
package/dist/oauth/index.d.cts
CHANGED
|
@@ -74,9 +74,29 @@ const cookieOptions = ({
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
// Path builder for the API menu endpoints. Single source of truth for
|
|
77
|
-
// the /menu
|
|
78
|
-
//
|
|
79
|
-
|
|
77
|
+
// the /menu/<...> shape — drawbridge-api routes and drawbridge-app-web's
|
|
78
|
+
// ProviderLayout wrappers both read from here.
|
|
79
|
+
//
|
|
80
|
+
// menuEndpoint('account') → /menu/account
|
|
81
|
+
// menuEndpoint('admin') → /menu/admin
|
|
82
|
+
// menuEndpoint('organization', orgId) → /menu/organization/abc
|
|
83
|
+
// menuEndpoint('campaign', orgId, campaignId) → /menu/organization/abc/campaign/xyz
|
|
84
|
+
// (campaign menus piggyback on the org URL prefix so the standard
|
|
85
|
+
// hasOrganizationAccess → hasCampaignAccess middleware chain works.)
|
|
86
|
+
const menuEndpoint = ( type, ...ids ) => {
|
|
87
|
+
|
|
88
|
+
if( type === 'campaign' ){
|
|
89
|
+
|
|
90
|
+
const [ organization, campaign ] = ids;
|
|
91
|
+
|
|
92
|
+
return '/menu/organization/' + organization + '/campaign/' + campaign;
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
const [ id ] = ids;
|
|
96
|
+
|
|
97
|
+
return '/menu/' + type + ( id ? '/' + id : '' );
|
|
98
|
+
|
|
99
|
+
};
|
|
80
100
|
|
|
81
101
|
// ─────────────────────────────────────────────────────────────────────────
|
|
82
102
|
// Scope vocabulary (locked — 15 scopes, 10 in the developer-allowed subset)
|
package/dist/oauth/index.d.ts
CHANGED
|
@@ -74,9 +74,29 @@ const cookieOptions = ({
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
// Path builder for the API menu endpoints. Single source of truth for
|
|
77
|
-
// the /menu
|
|
78
|
-
//
|
|
79
|
-
|
|
77
|
+
// the /menu/<...> shape — drawbridge-api routes and drawbridge-app-web's
|
|
78
|
+
// ProviderLayout wrappers both read from here.
|
|
79
|
+
//
|
|
80
|
+
// menuEndpoint('account') → /menu/account
|
|
81
|
+
// menuEndpoint('admin') → /menu/admin
|
|
82
|
+
// menuEndpoint('organization', orgId) → /menu/organization/abc
|
|
83
|
+
// menuEndpoint('campaign', orgId, campaignId) → /menu/organization/abc/campaign/xyz
|
|
84
|
+
// (campaign menus piggyback on the org URL prefix so the standard
|
|
85
|
+
// hasOrganizationAccess → hasCampaignAccess middleware chain works.)
|
|
86
|
+
const menuEndpoint = ( type, ...ids ) => {
|
|
87
|
+
|
|
88
|
+
if( type === 'campaign' ){
|
|
89
|
+
|
|
90
|
+
const [ organization, campaign ] = ids;
|
|
91
|
+
|
|
92
|
+
return '/menu/organization/' + organization + '/campaign/' + campaign;
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
const [ id ] = ids;
|
|
96
|
+
|
|
97
|
+
return '/menu/' + type + ( id ? '/' + id : '' );
|
|
98
|
+
|
|
99
|
+
};
|
|
80
100
|
|
|
81
101
|
// ─────────────────────────────────────────────────────────────────────────
|
|
82
102
|
// Scope vocabulary (locked — 15 scopes, 10 in the developer-allowed subset)
|
package/dist/oauth/index.js
CHANGED
|
@@ -61,7 +61,15 @@ var cookieOptions = ({
|
|
|
61
61
|
secure: process.env.NODE_ENV !== "development",
|
|
62
62
|
...expiresAt && { expires: new Date(expiresAt) }
|
|
63
63
|
});
|
|
64
|
-
var menuEndpoint = (type,
|
|
64
|
+
var menuEndpoint = (type, ...ids) => {
|
|
65
|
+
if (type === "campaign") {
|
|
66
|
+
const [organization, campaign] = ids;
|
|
67
|
+
return "/menu/organization/" + organization + "/campaign/" + campaign;
|
|
68
|
+
}
|
|
69
|
+
;
|
|
70
|
+
const [id] = ids;
|
|
71
|
+
return "/menu/" + type + (id ? "/" + id : "");
|
|
72
|
+
};
|
|
65
73
|
var scopes = [
|
|
66
74
|
"profile:read",
|
|
67
75
|
"profile:write",
|
package/dist/oauth/server.cjs
CHANGED
|
@@ -146,19 +146,20 @@ var hashToken = (raw) => hash(raw, process.env.OAUTH_TOKEN_HMAC_KEY);
|
|
|
146
146
|
var generateToken = () => generate(32, "base64url");
|
|
147
147
|
|
|
148
148
|
// lib/oauth/server.js
|
|
149
|
+
var SUPPORTED_GRANTS = ["authorization_code", "client_credentials", "refresh_token"];
|
|
149
150
|
var createOAuthModel = ({ controller }) => ({
|
|
150
151
|
getClient: async (clientId, clientSecret) => {
|
|
151
152
|
var _a;
|
|
152
|
-
const
|
|
153
|
+
const record = await controller.get({
|
|
153
154
|
collection: "oauth",
|
|
154
155
|
query: {
|
|
155
|
-
clientId,
|
|
156
|
+
client: clientId,
|
|
156
157
|
status: "active"
|
|
157
158
|
}
|
|
158
159
|
});
|
|
159
|
-
if (!
|
|
160
|
+
if (!record) return false;
|
|
160
161
|
if (clientSecret) {
|
|
161
|
-
const validSecret = (_a =
|
|
162
|
+
const validSecret = (_a = record.hashes) == null ? void 0 : _a.some((entry) => {
|
|
162
163
|
if (entry.retiredAt) return false;
|
|
163
164
|
return compare(hashToken(clientSecret), entry.hash);
|
|
164
165
|
});
|
|
@@ -166,11 +167,11 @@ var createOAuthModel = ({ controller }) => ({
|
|
|
166
167
|
}
|
|
167
168
|
;
|
|
168
169
|
return {
|
|
169
|
-
clientId: client
|
|
170
|
-
grants:
|
|
171
|
-
id:
|
|
172
|
-
redirectUris:
|
|
173
|
-
scopes:
|
|
170
|
+
clientId: record.client,
|
|
171
|
+
grants: SUPPORTED_GRANTS,
|
|
172
|
+
id: record.id,
|
|
173
|
+
redirectUris: record.redirects ?? [],
|
|
174
|
+
scopes: record.scopes ?? []
|
|
174
175
|
};
|
|
175
176
|
},
|
|
176
177
|
saveAuthorizationCode: async (code, client, user) => {
|
|
@@ -375,17 +376,16 @@ var createOAuthServer = ({ controller }) => new import_oauth2_server.default({
|
|
|
375
376
|
}
|
|
376
377
|
});
|
|
377
378
|
var createClient = async ({
|
|
378
|
-
allowedScopes = [],
|
|
379
379
|
controller,
|
|
380
380
|
createdBy = null,
|
|
381
381
|
description = null,
|
|
382
|
-
grantTypes = ["authorization_code"],
|
|
383
382
|
name,
|
|
384
383
|
organization = null,
|
|
385
|
-
|
|
386
|
-
|
|
384
|
+
redirects = [],
|
|
385
|
+
scopes: scopes2 = [],
|
|
386
|
+
origins = []
|
|
387
387
|
}) => {
|
|
388
|
-
const invalid =
|
|
388
|
+
const invalid = scopes2.filter((scope) => !developer.includes(scope));
|
|
389
389
|
if (invalid.length > 0) {
|
|
390
390
|
const error = new Error("Scopes not permitted for developer apps: " + invalid.join(", "));
|
|
391
391
|
error.status = 400;
|
|
@@ -393,37 +393,38 @@ var createClient = async ({
|
|
|
393
393
|
}
|
|
394
394
|
;
|
|
395
395
|
const rawClientId = generateToken();
|
|
396
|
-
const
|
|
396
|
+
const client = "drawbridge." + rawClientId;
|
|
397
397
|
const rawSecret = generateToken();
|
|
398
398
|
const secretHash = hashToken(rawSecret);
|
|
399
399
|
const now = /* @__PURE__ */ new Date();
|
|
400
|
-
const
|
|
400
|
+
const record = await controller.create({
|
|
401
401
|
collection: "oauth",
|
|
402
402
|
data: {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
403
|
+
client,
|
|
404
|
+
createdBy,
|
|
405
|
+
description,
|
|
406
|
+
endpoint: {
|
|
407
|
+
auth: "client_secret_basic"
|
|
408
|
+
},
|
|
409
|
+
hashes: [
|
|
406
410
|
{
|
|
407
411
|
createdAt: now,
|
|
408
412
|
hash: secretHash,
|
|
409
413
|
retiredAt: null
|
|
410
414
|
}
|
|
411
415
|
],
|
|
412
|
-
|
|
413
|
-
createdBy,
|
|
414
|
-
description,
|
|
415
|
-
grantTypes,
|
|
416
|
+
limits: null,
|
|
416
417
|
name,
|
|
417
418
|
organization,
|
|
418
|
-
|
|
419
|
-
|
|
419
|
+
origins,
|
|
420
|
+
redirects,
|
|
421
|
+
scopes: scopes2,
|
|
420
422
|
status: "active",
|
|
421
|
-
|
|
422
|
-
webOrigins
|
|
423
|
+
type: "confidential"
|
|
423
424
|
}
|
|
424
425
|
});
|
|
425
426
|
return {
|
|
426
|
-
|
|
427
|
+
record,
|
|
427
428
|
rawSecret
|
|
428
429
|
};
|
|
429
430
|
};
|
package/dist/oauth/server.d.cts
CHANGED
|
@@ -14,34 +14,43 @@ import 'crypto';
|
|
|
14
14
|
// { collection, query, data } works. drawbridge-api passes its base
|
|
15
15
|
// controller; tests can pass an in-memory mock.
|
|
16
16
|
//
|
|
17
|
+
// Boundary translation: the DB uses our renamed schema (client,
|
|
18
|
+
// scopes, redirects, hashes, ...), but the @node-oauth library
|
|
19
|
+
// expects spec-named keys (clientId, scope, redirectUris, ...).
|
|
20
|
+
// Each model method translates at the return boundary.
|
|
21
|
+
//
|
|
17
22
|
// - createOAuthServer({ controller })
|
|
18
23
|
// Convenience: creates the model + wraps it in an OAuth2Server with
|
|
19
24
|
// the standard Drawbridge lifetimes (1h access / 30d refresh) and
|
|
20
25
|
// client-authentication requirements.
|
|
21
26
|
//
|
|
22
|
-
// - createClient({
|
|
27
|
+
// - createClient({ controller, scopes, name, organization, ... })
|
|
23
28
|
// Inserts a new oauth client row. Validates scopes against the
|
|
24
29
|
// developer set; throws 400 on invalid. Returns
|
|
25
|
-
// {
|
|
30
|
+
// { record, rawSecret } — secret is plaintext, return ONCE.
|
|
31
|
+
|
|
26
32
|
|
|
33
|
+
// Hardcoded — the supported grants don't vary per client today. If they
|
|
34
|
+
// ever need to, store `grants` on the oauth doc and read it here.
|
|
35
|
+
const SUPPORTED_GRANTS = [ 'authorization_code', 'client_credentials', 'refresh_token' ];
|
|
27
36
|
|
|
28
37
|
const createOAuthModel = ({ controller }) => ({
|
|
29
38
|
|
|
30
39
|
getClient : async ( clientId, clientSecret ) => {
|
|
31
40
|
|
|
32
|
-
const
|
|
41
|
+
const record = await controller.get({
|
|
33
42
|
collection : 'oauth',
|
|
34
43
|
query : {
|
|
35
|
-
clientId,
|
|
44
|
+
client : clientId,
|
|
36
45
|
status : 'active'
|
|
37
46
|
}
|
|
38
47
|
});
|
|
39
48
|
|
|
40
|
-
if( !
|
|
49
|
+
if( ! record ) return false;
|
|
41
50
|
|
|
42
51
|
if( clientSecret ){
|
|
43
52
|
|
|
44
|
-
const validSecret =
|
|
53
|
+
const validSecret = record.hashes?.some( ( entry ) => {
|
|
45
54
|
|
|
46
55
|
if( entry.retiredAt ) return false;
|
|
47
56
|
|
|
@@ -53,11 +62,11 @@ const createOAuthModel = ({ controller }) => ({
|
|
|
53
62
|
|
|
54
63
|
}
|
|
55
64
|
return {
|
|
56
|
-
clientId : client
|
|
57
|
-
grants :
|
|
58
|
-
id :
|
|
59
|
-
redirectUris :
|
|
60
|
-
scopes :
|
|
65
|
+
clientId : record.client,
|
|
66
|
+
grants : SUPPORTED_GRANTS,
|
|
67
|
+
id : record.id,
|
|
68
|
+
redirectUris : record.redirects ?? [],
|
|
69
|
+
scopes : record.scopes ?? []
|
|
61
70
|
};
|
|
62
71
|
|
|
63
72
|
},
|
|
@@ -312,23 +321,22 @@ const createOAuthServer = ({ controller }) => new OAuth2Server({
|
|
|
312
321
|
}
|
|
313
322
|
});
|
|
314
323
|
|
|
315
|
-
// Inserts a new oauth client row. Validates
|
|
324
|
+
// Inserts a new oauth client row. Validates scopes against the
|
|
316
325
|
// developer-allowed subset; throws a 400-flagged error on invalid scopes.
|
|
317
|
-
// Returns {
|
|
326
|
+
// Returns { record: <inserted-doc>, rawSecret: <plaintext> }. The raw
|
|
318
327
|
// secret is only available here — store immediately.
|
|
319
328
|
const createClient = async ({
|
|
320
|
-
allowedScopes = [],
|
|
321
329
|
controller,
|
|
322
330
|
createdBy = null,
|
|
323
331
|
description = null,
|
|
324
|
-
grantTypes = [ 'authorization_code' ],
|
|
325
332
|
name,
|
|
326
333
|
organization = null,
|
|
327
|
-
|
|
328
|
-
|
|
334
|
+
redirects = [],
|
|
335
|
+
scopes = [],
|
|
336
|
+
origins = []
|
|
329
337
|
}) => {
|
|
330
338
|
|
|
331
|
-
const invalid =
|
|
339
|
+
const invalid = scopes.filter( ( scope ) => ! developer.includes( scope ) );
|
|
332
340
|
|
|
333
341
|
if( invalid.length > 0 ){
|
|
334
342
|
|
|
@@ -340,41 +348,42 @@ const createClient = async ({
|
|
|
340
348
|
|
|
341
349
|
}
|
|
342
350
|
const rawClientId = generateToken();
|
|
343
|
-
const
|
|
351
|
+
const client = 'drawbridge.' + rawClientId;
|
|
344
352
|
|
|
345
353
|
const rawSecret = generateToken();
|
|
346
354
|
const secretHash = hashToken( rawSecret );
|
|
347
355
|
|
|
348
356
|
const now = new Date();
|
|
349
357
|
|
|
350
|
-
const
|
|
358
|
+
const record = await controller.create({
|
|
351
359
|
collection : 'oauth',
|
|
352
360
|
data : {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
361
|
+
client,
|
|
362
|
+
createdBy,
|
|
363
|
+
description,
|
|
364
|
+
endpoint : {
|
|
365
|
+
auth : 'client_secret_basic'
|
|
366
|
+
},
|
|
367
|
+
hashes : [
|
|
356
368
|
{
|
|
357
369
|
createdAt : now,
|
|
358
370
|
hash : secretHash,
|
|
359
371
|
retiredAt : null
|
|
360
372
|
}
|
|
361
373
|
],
|
|
362
|
-
|
|
363
|
-
createdBy,
|
|
364
|
-
description,
|
|
365
|
-
grantTypes,
|
|
374
|
+
limits : null,
|
|
366
375
|
name,
|
|
367
376
|
organization,
|
|
368
|
-
|
|
369
|
-
|
|
377
|
+
origins,
|
|
378
|
+
redirects,
|
|
379
|
+
scopes,
|
|
370
380
|
status : 'active',
|
|
371
|
-
|
|
372
|
-
webOrigins
|
|
381
|
+
type : 'confidential'
|
|
373
382
|
}
|
|
374
383
|
});
|
|
375
384
|
|
|
376
385
|
return {
|
|
377
|
-
|
|
386
|
+
record,
|
|
378
387
|
rawSecret
|
|
379
388
|
};
|
|
380
389
|
|
package/dist/oauth/server.d.ts
CHANGED
|
@@ -14,34 +14,43 @@ import 'crypto';
|
|
|
14
14
|
// { collection, query, data } works. drawbridge-api passes its base
|
|
15
15
|
// controller; tests can pass an in-memory mock.
|
|
16
16
|
//
|
|
17
|
+
// Boundary translation: the DB uses our renamed schema (client,
|
|
18
|
+
// scopes, redirects, hashes, ...), but the @node-oauth library
|
|
19
|
+
// expects spec-named keys (clientId, scope, redirectUris, ...).
|
|
20
|
+
// Each model method translates at the return boundary.
|
|
21
|
+
//
|
|
17
22
|
// - createOAuthServer({ controller })
|
|
18
23
|
// Convenience: creates the model + wraps it in an OAuth2Server with
|
|
19
24
|
// the standard Drawbridge lifetimes (1h access / 30d refresh) and
|
|
20
25
|
// client-authentication requirements.
|
|
21
26
|
//
|
|
22
|
-
// - createClient({
|
|
27
|
+
// - createClient({ controller, scopes, name, organization, ... })
|
|
23
28
|
// Inserts a new oauth client row. Validates scopes against the
|
|
24
29
|
// developer set; throws 400 on invalid. Returns
|
|
25
|
-
// {
|
|
30
|
+
// { record, rawSecret } — secret is plaintext, return ONCE.
|
|
31
|
+
|
|
26
32
|
|
|
33
|
+
// Hardcoded — the supported grants don't vary per client today. If they
|
|
34
|
+
// ever need to, store `grants` on the oauth doc and read it here.
|
|
35
|
+
const SUPPORTED_GRANTS = [ 'authorization_code', 'client_credentials', 'refresh_token' ];
|
|
27
36
|
|
|
28
37
|
const createOAuthModel = ({ controller }) => ({
|
|
29
38
|
|
|
30
39
|
getClient : async ( clientId, clientSecret ) => {
|
|
31
40
|
|
|
32
|
-
const
|
|
41
|
+
const record = await controller.get({
|
|
33
42
|
collection : 'oauth',
|
|
34
43
|
query : {
|
|
35
|
-
clientId,
|
|
44
|
+
client : clientId,
|
|
36
45
|
status : 'active'
|
|
37
46
|
}
|
|
38
47
|
});
|
|
39
48
|
|
|
40
|
-
if( !
|
|
49
|
+
if( ! record ) return false;
|
|
41
50
|
|
|
42
51
|
if( clientSecret ){
|
|
43
52
|
|
|
44
|
-
const validSecret =
|
|
53
|
+
const validSecret = record.hashes?.some( ( entry ) => {
|
|
45
54
|
|
|
46
55
|
if( entry.retiredAt ) return false;
|
|
47
56
|
|
|
@@ -53,11 +62,11 @@ const createOAuthModel = ({ controller }) => ({
|
|
|
53
62
|
|
|
54
63
|
}
|
|
55
64
|
return {
|
|
56
|
-
clientId : client
|
|
57
|
-
grants :
|
|
58
|
-
id :
|
|
59
|
-
redirectUris :
|
|
60
|
-
scopes :
|
|
65
|
+
clientId : record.client,
|
|
66
|
+
grants : SUPPORTED_GRANTS,
|
|
67
|
+
id : record.id,
|
|
68
|
+
redirectUris : record.redirects ?? [],
|
|
69
|
+
scopes : record.scopes ?? []
|
|
61
70
|
};
|
|
62
71
|
|
|
63
72
|
},
|
|
@@ -312,23 +321,22 @@ const createOAuthServer = ({ controller }) => new OAuth2Server({
|
|
|
312
321
|
}
|
|
313
322
|
});
|
|
314
323
|
|
|
315
|
-
// Inserts a new oauth client row. Validates
|
|
324
|
+
// Inserts a new oauth client row. Validates scopes against the
|
|
316
325
|
// developer-allowed subset; throws a 400-flagged error on invalid scopes.
|
|
317
|
-
// Returns {
|
|
326
|
+
// Returns { record: <inserted-doc>, rawSecret: <plaintext> }. The raw
|
|
318
327
|
// secret is only available here — store immediately.
|
|
319
328
|
const createClient = async ({
|
|
320
|
-
allowedScopes = [],
|
|
321
329
|
controller,
|
|
322
330
|
createdBy = null,
|
|
323
331
|
description = null,
|
|
324
|
-
grantTypes = [ 'authorization_code' ],
|
|
325
332
|
name,
|
|
326
333
|
organization = null,
|
|
327
|
-
|
|
328
|
-
|
|
334
|
+
redirects = [],
|
|
335
|
+
scopes = [],
|
|
336
|
+
origins = []
|
|
329
337
|
}) => {
|
|
330
338
|
|
|
331
|
-
const invalid =
|
|
339
|
+
const invalid = scopes.filter( ( scope ) => ! developer.includes( scope ) );
|
|
332
340
|
|
|
333
341
|
if( invalid.length > 0 ){
|
|
334
342
|
|
|
@@ -340,41 +348,42 @@ const createClient = async ({
|
|
|
340
348
|
|
|
341
349
|
}
|
|
342
350
|
const rawClientId = generateToken();
|
|
343
|
-
const
|
|
351
|
+
const client = 'drawbridge.' + rawClientId;
|
|
344
352
|
|
|
345
353
|
const rawSecret = generateToken();
|
|
346
354
|
const secretHash = hashToken( rawSecret );
|
|
347
355
|
|
|
348
356
|
const now = new Date();
|
|
349
357
|
|
|
350
|
-
const
|
|
358
|
+
const record = await controller.create({
|
|
351
359
|
collection : 'oauth',
|
|
352
360
|
data : {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
361
|
+
client,
|
|
362
|
+
createdBy,
|
|
363
|
+
description,
|
|
364
|
+
endpoint : {
|
|
365
|
+
auth : 'client_secret_basic'
|
|
366
|
+
},
|
|
367
|
+
hashes : [
|
|
356
368
|
{
|
|
357
369
|
createdAt : now,
|
|
358
370
|
hash : secretHash,
|
|
359
371
|
retiredAt : null
|
|
360
372
|
}
|
|
361
373
|
],
|
|
362
|
-
|
|
363
|
-
createdBy,
|
|
364
|
-
description,
|
|
365
|
-
grantTypes,
|
|
374
|
+
limits : null,
|
|
366
375
|
name,
|
|
367
376
|
organization,
|
|
368
|
-
|
|
369
|
-
|
|
377
|
+
origins,
|
|
378
|
+
redirects,
|
|
379
|
+
scopes,
|
|
370
380
|
status : 'active',
|
|
371
|
-
|
|
372
|
-
webOrigins
|
|
381
|
+
type : 'confidential'
|
|
373
382
|
}
|
|
374
383
|
});
|
|
375
384
|
|
|
376
385
|
return {
|
|
377
|
-
|
|
386
|
+
record,
|
|
378
387
|
rawSecret
|
|
379
388
|
};
|
|
380
389
|
|
package/dist/oauth/server.js
CHANGED
|
@@ -111,19 +111,20 @@ var hashToken = (raw) => hash(raw, process.env.OAUTH_TOKEN_HMAC_KEY);
|
|
|
111
111
|
var generateToken = () => generate(32, "base64url");
|
|
112
112
|
|
|
113
113
|
// lib/oauth/server.js
|
|
114
|
+
var SUPPORTED_GRANTS = ["authorization_code", "client_credentials", "refresh_token"];
|
|
114
115
|
var createOAuthModel = ({ controller }) => ({
|
|
115
116
|
getClient: async (clientId, clientSecret) => {
|
|
116
117
|
var _a;
|
|
117
|
-
const
|
|
118
|
+
const record = await controller.get({
|
|
118
119
|
collection: "oauth",
|
|
119
120
|
query: {
|
|
120
|
-
clientId,
|
|
121
|
+
client: clientId,
|
|
121
122
|
status: "active"
|
|
122
123
|
}
|
|
123
124
|
});
|
|
124
|
-
if (!
|
|
125
|
+
if (!record) return false;
|
|
125
126
|
if (clientSecret) {
|
|
126
|
-
const validSecret = (_a =
|
|
127
|
+
const validSecret = (_a = record.hashes) == null ? void 0 : _a.some((entry) => {
|
|
127
128
|
if (entry.retiredAt) return false;
|
|
128
129
|
return compare(hashToken(clientSecret), entry.hash);
|
|
129
130
|
});
|
|
@@ -131,11 +132,11 @@ var createOAuthModel = ({ controller }) => ({
|
|
|
131
132
|
}
|
|
132
133
|
;
|
|
133
134
|
return {
|
|
134
|
-
clientId: client
|
|
135
|
-
grants:
|
|
136
|
-
id:
|
|
137
|
-
redirectUris:
|
|
138
|
-
scopes:
|
|
135
|
+
clientId: record.client,
|
|
136
|
+
grants: SUPPORTED_GRANTS,
|
|
137
|
+
id: record.id,
|
|
138
|
+
redirectUris: record.redirects ?? [],
|
|
139
|
+
scopes: record.scopes ?? []
|
|
139
140
|
};
|
|
140
141
|
},
|
|
141
142
|
saveAuthorizationCode: async (code, client, user) => {
|
|
@@ -340,17 +341,16 @@ var createOAuthServer = ({ controller }) => new OAuth2Server({
|
|
|
340
341
|
}
|
|
341
342
|
});
|
|
342
343
|
var createClient = async ({
|
|
343
|
-
allowedScopes = [],
|
|
344
344
|
controller,
|
|
345
345
|
createdBy = null,
|
|
346
346
|
description = null,
|
|
347
|
-
grantTypes = ["authorization_code"],
|
|
348
347
|
name,
|
|
349
348
|
organization = null,
|
|
350
|
-
|
|
351
|
-
|
|
349
|
+
redirects = [],
|
|
350
|
+
scopes: scopes2 = [],
|
|
351
|
+
origins = []
|
|
352
352
|
}) => {
|
|
353
|
-
const invalid =
|
|
353
|
+
const invalid = scopes2.filter((scope) => !developer.includes(scope));
|
|
354
354
|
if (invalid.length > 0) {
|
|
355
355
|
const error = new Error("Scopes not permitted for developer apps: " + invalid.join(", "));
|
|
356
356
|
error.status = 400;
|
|
@@ -358,37 +358,38 @@ var createClient = async ({
|
|
|
358
358
|
}
|
|
359
359
|
;
|
|
360
360
|
const rawClientId = generateToken();
|
|
361
|
-
const
|
|
361
|
+
const client = "drawbridge." + rawClientId;
|
|
362
362
|
const rawSecret = generateToken();
|
|
363
363
|
const secretHash = hashToken(rawSecret);
|
|
364
364
|
const now = /* @__PURE__ */ new Date();
|
|
365
|
-
const
|
|
365
|
+
const record = await controller.create({
|
|
366
366
|
collection: "oauth",
|
|
367
367
|
data: {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
368
|
+
client,
|
|
369
|
+
createdBy,
|
|
370
|
+
description,
|
|
371
|
+
endpoint: {
|
|
372
|
+
auth: "client_secret_basic"
|
|
373
|
+
},
|
|
374
|
+
hashes: [
|
|
371
375
|
{
|
|
372
376
|
createdAt: now,
|
|
373
377
|
hash: secretHash,
|
|
374
378
|
retiredAt: null
|
|
375
379
|
}
|
|
376
380
|
],
|
|
377
|
-
|
|
378
|
-
createdBy,
|
|
379
|
-
description,
|
|
380
|
-
grantTypes,
|
|
381
|
+
limits: null,
|
|
381
382
|
name,
|
|
382
383
|
organization,
|
|
383
|
-
|
|
384
|
-
|
|
384
|
+
origins,
|
|
385
|
+
redirects,
|
|
386
|
+
scopes: scopes2,
|
|
385
387
|
status: "active",
|
|
386
|
-
|
|
387
|
-
webOrigins
|
|
388
|
+
type: "confidential"
|
|
388
389
|
}
|
|
389
390
|
});
|
|
390
391
|
return {
|
|
391
|
-
|
|
392
|
+
record,
|
|
392
393
|
rawSecret
|
|
393
394
|
};
|
|
394
395
|
};
|
package/package.json
CHANGED