@thirdweb-dev/service-utils 0.1.1-nightly-4915ac50-20230714041125 → 0.2.0-nightly-5eb6fc1b-20230714082745
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/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts +2 -0
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts.map +1 -0
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.dev.js +115 -0
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.js +7 -0
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +115 -0
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +105 -0
- package/cf-worker/package.json +4 -0
- package/dist/declarations/src/cf-worker/index.d.ts +18 -0
- package/dist/declarations/src/cf-worker/index.d.ts.map +1 -0
- package/dist/declarations/src/core/api.d.ts +31 -0
- package/dist/declarations/src/core/api.d.ts.map +1 -0
- package/dist/declarations/src/core/authorize/index.d.ts +18 -0
- package/dist/declarations/src/core/authorize/index.d.ts.map +1 -0
- package/dist/declarations/src/core/authorize/types.d.ts +11 -0
- package/dist/declarations/src/core/authorize/types.d.ts.map +1 -0
- package/dist/declarations/src/core/services.d.ts.map +1 -0
- package/dist/declarations/src/core/types.d.ts +5 -0
- package/dist/declarations/src/core/types.d.ts.map +1 -0
- package/dist/declarations/src/index.d.ts +1 -2
- package/dist/declarations/src/index.d.ts.map +1 -1
- package/dist/declarations/src/node/index.d.ts +16 -0
- package/dist/declarations/src/node/index.d.ts.map +1 -0
- package/dist/index-294e111f.esm.js +252 -0
- package/dist/index-3060948e.cjs.prod.js +254 -0
- package/dist/index-fcf69a55.cjs.dev.js +254 -0
- package/dist/services-86283509.esm.js +44 -0
- package/dist/services-9e185105.cjs.prod.js +49 -0
- package/dist/services-a3f36057.cjs.dev.js +49 -0
- package/dist/thirdweb-dev-service-utils.cjs.dev.js +5 -284
- package/dist/thirdweb-dev-service-utils.cjs.prod.js +5 -284
- package/dist/thirdweb-dev-service-utils.esm.js +1 -282
- package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts +2 -0
- package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts.map +1 -0
- package/node/dist/thirdweb-dev-service-utils-node.cjs.dev.js +113 -0
- package/node/dist/thirdweb-dev-service-utils-node.cjs.js +7 -0
- package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +113 -0
- package/node/dist/thirdweb-dev-service-utils-node.esm.js +102 -0
- package/node/package.json +4 -0
- package/package.json +22 -10
- package/dist/declarations/src/auth/index.d.ts +0 -4
- package/dist/declarations/src/auth/index.d.ts.map +0 -1
- package/dist/declarations/src/auth/types.d.ts +0 -61
- package/dist/declarations/src/auth/types.d.ts.map +0 -1
- package/dist/declarations/src/services.d.ts.map +0 -1
- /package/dist/declarations/src/{services.d.ts → core/services.d.ts} +0 -0
@@ -2,290 +2,11 @@
|
|
2
2
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
4
4
|
|
5
|
-
|
6
|
-
storage: {
|
7
|
-
name: "storage",
|
8
|
-
title: "Storage",
|
9
|
-
description: "IPFS Upload and Download",
|
10
|
-
actions: [{
|
11
|
-
name: "read",
|
12
|
-
title: "Download",
|
13
|
-
description: "Download a file from Storage"
|
14
|
-
}, {
|
15
|
-
name: "write",
|
16
|
-
title: "Upload",
|
17
|
-
description: "Upload a file to Storage"
|
18
|
-
}]
|
19
|
-
},
|
20
|
-
rpc: {
|
21
|
-
name: "rpc",
|
22
|
-
title: "RPC",
|
23
|
-
description: "Accelerated RPC Edge",
|
24
|
-
// all actions allowed
|
25
|
-
actions: []
|
26
|
-
},
|
27
|
-
bundler: {
|
28
|
-
name: "bundler",
|
29
|
-
title: "Smart Wallets",
|
30
|
-
description: "Bundler & Paymaster services",
|
31
|
-
// all actions allowed
|
32
|
-
actions: []
|
33
|
-
},
|
34
|
-
relayer: {
|
35
|
-
name: "relayer",
|
36
|
-
title: "Gasless Relayer",
|
37
|
-
description: "Enable gasless transactions",
|
38
|
-
// all actions allowed
|
39
|
-
actions: []
|
40
|
-
}
|
41
|
-
};
|
42
|
-
const SERVICE_NAMES = Object.keys(SERVICE_DEFINITIONS);
|
43
|
-
const SERVICES = Object.values(SERVICE_DEFINITIONS);
|
44
|
-
function getServiceByName(name) {
|
45
|
-
return SERVICE_DEFINITIONS[name];
|
46
|
-
}
|
5
|
+
var services = require('./services-9e185105.cjs.prod.js');
|
47
6
|
|
48
|
-
async function authorizeCFWorkerService(options) {
|
49
|
-
const {
|
50
|
-
kvStore,
|
51
|
-
ctx,
|
52
|
-
authOptions,
|
53
|
-
serviceConfig,
|
54
|
-
validations
|
55
|
-
} = options;
|
56
|
-
const {
|
57
|
-
clientId
|
58
|
-
} = authOptions;
|
59
|
-
let cachedKey;
|
60
7
|
|
61
|
-
// first, check if the key is in KV
|
62
|
-
try {
|
63
|
-
const kvKey = await kvStore.get(clientId);
|
64
|
-
if (kvKey) {
|
65
|
-
cachedKey = JSON.parse(kvKey);
|
66
|
-
}
|
67
|
-
} catch (err) {
|
68
|
-
// ignore JSON parse, assuming not valid
|
69
|
-
}
|
70
|
-
const updateKv = async keyData => {
|
71
|
-
kvStore.put(clientId, JSON.stringify(keyData), {
|
72
|
-
expirationTtl: serviceConfig.cacheTtl || 60
|
73
|
-
});
|
74
|
-
};
|
75
|
-
return authorize({
|
76
|
-
authOptions,
|
77
|
-
serviceConfig: {
|
78
|
-
...serviceConfig,
|
79
|
-
cachedKey,
|
80
|
-
onRefetchComplete: keyData => {
|
81
|
-
ctx.waitUntil(updateKv(keyData));
|
82
|
-
}
|
83
|
-
},
|
84
|
-
validations
|
85
|
-
});
|
86
|
-
}
|
87
|
-
async function authorizeNodeService(options) {
|
88
|
-
const {
|
89
|
-
authOptions,
|
90
|
-
serviceConfig,
|
91
|
-
validations
|
92
|
-
} = options;
|
93
|
-
return authorize({
|
94
|
-
authOptions,
|
95
|
-
serviceConfig,
|
96
|
-
validations
|
97
|
-
});
|
98
|
-
}
|
99
8
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
*/
|
105
|
-
async function authorize(options) {
|
106
|
-
try {
|
107
|
-
const {
|
108
|
-
authOptions,
|
109
|
-
serviceConfig,
|
110
|
-
validations
|
111
|
-
} = options;
|
112
|
-
const {
|
113
|
-
clientId
|
114
|
-
} = authOptions;
|
115
|
-
const {
|
116
|
-
apiUrl,
|
117
|
-
scope,
|
118
|
-
serviceKey,
|
119
|
-
cachedKey,
|
120
|
-
onRefetchComplete
|
121
|
-
} = serviceConfig;
|
122
|
-
let keyData = cachedKey;
|
123
|
-
|
124
|
-
// no cached key, re-fetch from API
|
125
|
-
if (!keyData) {
|
126
|
-
const response = await fetch(`${apiUrl}/v1/keys/use?scope=${scope}&clientId=${clientId}`, {
|
127
|
-
method: "GET",
|
128
|
-
headers: {
|
129
|
-
"x-service-api-key": serviceKey,
|
130
|
-
"content-type": "application/json"
|
131
|
-
}
|
132
|
-
});
|
133
|
-
const apiResponse = await response.json();
|
134
|
-
if (!response.ok) {
|
135
|
-
const {
|
136
|
-
error
|
137
|
-
} = apiResponse;
|
138
|
-
return {
|
139
|
-
authorized: false,
|
140
|
-
errorMessage: error.message,
|
141
|
-
errorCode: error.code || "",
|
142
|
-
statusCode: error.statusCode || 401
|
143
|
-
};
|
144
|
-
}
|
145
|
-
keyData = apiResponse.data;
|
146
|
-
if (onRefetchComplete) {
|
147
|
-
onRefetchComplete(keyData);
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
//
|
152
|
-
// Run validations
|
153
|
-
//
|
154
|
-
const authResponse = authAccess(authOptions, keyData);
|
155
|
-
if (!authResponse?.authorized) {
|
156
|
-
return authResponse;
|
157
|
-
}
|
158
|
-
const authzResponse = authzServices(validations, keyData, scope);
|
159
|
-
if (!authzResponse?.authorized) {
|
160
|
-
return authzResponse;
|
161
|
-
}
|
162
|
-
// FIXME: validate bundleId
|
163
|
-
|
164
|
-
return {
|
165
|
-
authorized: true,
|
166
|
-
data: keyData
|
167
|
-
};
|
168
|
-
} catch (err) {
|
169
|
-
console.error("Failed to authorize this key.", err);
|
170
|
-
return {
|
171
|
-
authorized: false,
|
172
|
-
errorMessage: "Internal error",
|
173
|
-
errorCode: "INTERNAL_ERROR",
|
174
|
-
statusCode: 500
|
175
|
-
};
|
176
|
-
}
|
177
|
-
}
|
178
|
-
function authAccess(authOptions, apiKey) {
|
179
|
-
const {
|
180
|
-
origin,
|
181
|
-
secretHash: providedSecretHash
|
182
|
-
} = authOptions;
|
183
|
-
const {
|
184
|
-
domains,
|
185
|
-
secretHash
|
186
|
-
} = apiKey;
|
187
|
-
if (providedSecretHash) {
|
188
|
-
if (secretHash !== providedSecretHash) {
|
189
|
-
return {
|
190
|
-
authorized: false,
|
191
|
-
errorMessage: "The secret is invalid.",
|
192
|
-
errorCode: "SECRET_INVALID",
|
193
|
-
statusCode: 401
|
194
|
-
};
|
195
|
-
}
|
196
|
-
return {
|
197
|
-
authorized: true
|
198
|
-
};
|
199
|
-
}
|
200
|
-
|
201
|
-
// validate domains
|
202
|
-
if (origin) {
|
203
|
-
if (
|
204
|
-
// find matching domain, or if all domains allowed
|
205
|
-
domains.find(d => {
|
206
|
-
if (d === "*") {
|
207
|
-
return true;
|
208
|
-
}
|
209
|
-
|
210
|
-
// If the allowedDomain has a wildcard,
|
211
|
-
// we'll check that the ending of our domain matches the wildcard
|
212
|
-
if (d.startsWith("*.")) {
|
213
|
-
const domainRoot = d.slice(2);
|
214
|
-
return origin.endsWith(domainRoot);
|
215
|
-
}
|
216
|
-
|
217
|
-
// If there's no wildcard, we'll check for an exact match
|
218
|
-
return d === origin;
|
219
|
-
})) {
|
220
|
-
return {
|
221
|
-
authorized: true
|
222
|
-
};
|
223
|
-
}
|
224
|
-
return {
|
225
|
-
authorized: false,
|
226
|
-
errorMessage: "The origin is not authorized for this key.",
|
227
|
-
errorCode: "ORIGIN_UNAUTHORIZED",
|
228
|
-
statusCode: 401
|
229
|
-
};
|
230
|
-
}
|
231
|
-
|
232
|
-
// FIXME: validate bundle id
|
233
|
-
return {
|
234
|
-
authorized: false,
|
235
|
-
errorMessage: "The keys are invalid.",
|
236
|
-
errorCode: "UNAUTHORIZED",
|
237
|
-
statusCode: 401
|
238
|
-
};
|
239
|
-
}
|
240
|
-
function authzServices(validations, apiKey, scope) {
|
241
|
-
const {
|
242
|
-
services
|
243
|
-
} = apiKey;
|
244
|
-
const {
|
245
|
-
serviceTargetAddresses,
|
246
|
-
serviceAction
|
247
|
-
} = validations;
|
248
|
-
|
249
|
-
// validate services
|
250
|
-
const service = services.find(srv => srv.name === scope);
|
251
|
-
if (!service) {
|
252
|
-
return {
|
253
|
-
authorized: false,
|
254
|
-
errorMessage: `The service "${scope}" is not authorized for this key.`,
|
255
|
-
errorCode: "SERVICE_UNAUTHORIZED",
|
256
|
-
statusCode: 403
|
257
|
-
};
|
258
|
-
}
|
259
|
-
|
260
|
-
// validate service actions
|
261
|
-
if (serviceAction) {
|
262
|
-
if (!service.actions.includes(serviceAction)) {
|
263
|
-
return {
|
264
|
-
authorized: false,
|
265
|
-
errorMessage: `The service "${scope}" action "${serviceAction}" is not authorized for this key.`,
|
266
|
-
errorCode: "SERVICE_ACTION_UNAUTHORIZED",
|
267
|
-
statusCode: 403
|
268
|
-
};
|
269
|
-
}
|
270
|
-
}
|
271
|
-
|
272
|
-
// validate service target addresses
|
273
|
-
if (serviceTargetAddresses && !service.targetAddresses.find(addr => addr === "*" || serviceTargetAddresses.includes(addr))) {
|
274
|
-
return {
|
275
|
-
authorized: false,
|
276
|
-
errorMessage: `The service "${scope}" target address is not authorized for this key.`,
|
277
|
-
errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
|
278
|
-
statusCode: 403
|
279
|
-
};
|
280
|
-
}
|
281
|
-
return {
|
282
|
-
authorized: true
|
283
|
-
};
|
284
|
-
}
|
285
|
-
|
286
|
-
exports.SERVICES = SERVICES;
|
287
|
-
exports.SERVICE_DEFINITIONS = SERVICE_DEFINITIONS;
|
288
|
-
exports.SERVICE_NAMES = SERVICE_NAMES;
|
289
|
-
exports.authorizeCFWorkerService = authorizeCFWorkerService;
|
290
|
-
exports.authorizeNodeService = authorizeNodeService;
|
291
|
-
exports.getServiceByName = getServiceByName;
|
9
|
+
exports.SERVICES = services.SERVICES;
|
10
|
+
exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
|
11
|
+
exports.SERVICE_NAMES = services.SERVICE_NAMES;
|
12
|
+
exports.getServiceByName = services.getServiceByName;
|
@@ -1,282 +1 @@
|
|
1
|
-
|
2
|
-
storage: {
|
3
|
-
name: "storage",
|
4
|
-
title: "Storage",
|
5
|
-
description: "IPFS Upload and Download",
|
6
|
-
actions: [{
|
7
|
-
name: "read",
|
8
|
-
title: "Download",
|
9
|
-
description: "Download a file from Storage"
|
10
|
-
}, {
|
11
|
-
name: "write",
|
12
|
-
title: "Upload",
|
13
|
-
description: "Upload a file to Storage"
|
14
|
-
}]
|
15
|
-
},
|
16
|
-
rpc: {
|
17
|
-
name: "rpc",
|
18
|
-
title: "RPC",
|
19
|
-
description: "Accelerated RPC Edge",
|
20
|
-
// all actions allowed
|
21
|
-
actions: []
|
22
|
-
},
|
23
|
-
bundler: {
|
24
|
-
name: "bundler",
|
25
|
-
title: "Smart Wallets",
|
26
|
-
description: "Bundler & Paymaster services",
|
27
|
-
// all actions allowed
|
28
|
-
actions: []
|
29
|
-
},
|
30
|
-
relayer: {
|
31
|
-
name: "relayer",
|
32
|
-
title: "Gasless Relayer",
|
33
|
-
description: "Enable gasless transactions",
|
34
|
-
// all actions allowed
|
35
|
-
actions: []
|
36
|
-
}
|
37
|
-
};
|
38
|
-
const SERVICE_NAMES = Object.keys(SERVICE_DEFINITIONS);
|
39
|
-
const SERVICES = Object.values(SERVICE_DEFINITIONS);
|
40
|
-
function getServiceByName(name) {
|
41
|
-
return SERVICE_DEFINITIONS[name];
|
42
|
-
}
|
43
|
-
|
44
|
-
async function authorizeCFWorkerService(options) {
|
45
|
-
const {
|
46
|
-
kvStore,
|
47
|
-
ctx,
|
48
|
-
authOptions,
|
49
|
-
serviceConfig,
|
50
|
-
validations
|
51
|
-
} = options;
|
52
|
-
const {
|
53
|
-
clientId
|
54
|
-
} = authOptions;
|
55
|
-
let cachedKey;
|
56
|
-
|
57
|
-
// first, check if the key is in KV
|
58
|
-
try {
|
59
|
-
const kvKey = await kvStore.get(clientId);
|
60
|
-
if (kvKey) {
|
61
|
-
cachedKey = JSON.parse(kvKey);
|
62
|
-
}
|
63
|
-
} catch (err) {
|
64
|
-
// ignore JSON parse, assuming not valid
|
65
|
-
}
|
66
|
-
const updateKv = async keyData => {
|
67
|
-
kvStore.put(clientId, JSON.stringify(keyData), {
|
68
|
-
expirationTtl: serviceConfig.cacheTtl || 60
|
69
|
-
});
|
70
|
-
};
|
71
|
-
return authorize({
|
72
|
-
authOptions,
|
73
|
-
serviceConfig: {
|
74
|
-
...serviceConfig,
|
75
|
-
cachedKey,
|
76
|
-
onRefetchComplete: keyData => {
|
77
|
-
ctx.waitUntil(updateKv(keyData));
|
78
|
-
}
|
79
|
-
},
|
80
|
-
validations
|
81
|
-
});
|
82
|
-
}
|
83
|
-
async function authorizeNodeService(options) {
|
84
|
-
const {
|
85
|
-
authOptions,
|
86
|
-
serviceConfig,
|
87
|
-
validations
|
88
|
-
} = options;
|
89
|
-
return authorize({
|
90
|
-
authOptions,
|
91
|
-
serviceConfig,
|
92
|
-
validations
|
93
|
-
});
|
94
|
-
}
|
95
|
-
|
96
|
-
/**
|
97
|
-
* Authorizes a request for a given client ID
|
98
|
-
*
|
99
|
-
* @returns The Promise AuthorizationResponse
|
100
|
-
*/
|
101
|
-
async function authorize(options) {
|
102
|
-
try {
|
103
|
-
const {
|
104
|
-
authOptions,
|
105
|
-
serviceConfig,
|
106
|
-
validations
|
107
|
-
} = options;
|
108
|
-
const {
|
109
|
-
clientId
|
110
|
-
} = authOptions;
|
111
|
-
const {
|
112
|
-
apiUrl,
|
113
|
-
scope,
|
114
|
-
serviceKey,
|
115
|
-
cachedKey,
|
116
|
-
onRefetchComplete
|
117
|
-
} = serviceConfig;
|
118
|
-
let keyData = cachedKey;
|
119
|
-
|
120
|
-
// no cached key, re-fetch from API
|
121
|
-
if (!keyData) {
|
122
|
-
const response = await fetch(`${apiUrl}/v1/keys/use?scope=${scope}&clientId=${clientId}`, {
|
123
|
-
method: "GET",
|
124
|
-
headers: {
|
125
|
-
"x-service-api-key": serviceKey,
|
126
|
-
"content-type": "application/json"
|
127
|
-
}
|
128
|
-
});
|
129
|
-
const apiResponse = await response.json();
|
130
|
-
if (!response.ok) {
|
131
|
-
const {
|
132
|
-
error
|
133
|
-
} = apiResponse;
|
134
|
-
return {
|
135
|
-
authorized: false,
|
136
|
-
errorMessage: error.message,
|
137
|
-
errorCode: error.code || "",
|
138
|
-
statusCode: error.statusCode || 401
|
139
|
-
};
|
140
|
-
}
|
141
|
-
keyData = apiResponse.data;
|
142
|
-
if (onRefetchComplete) {
|
143
|
-
onRefetchComplete(keyData);
|
144
|
-
}
|
145
|
-
}
|
146
|
-
|
147
|
-
//
|
148
|
-
// Run validations
|
149
|
-
//
|
150
|
-
const authResponse = authAccess(authOptions, keyData);
|
151
|
-
if (!authResponse?.authorized) {
|
152
|
-
return authResponse;
|
153
|
-
}
|
154
|
-
const authzResponse = authzServices(validations, keyData, scope);
|
155
|
-
if (!authzResponse?.authorized) {
|
156
|
-
return authzResponse;
|
157
|
-
}
|
158
|
-
// FIXME: validate bundleId
|
159
|
-
|
160
|
-
return {
|
161
|
-
authorized: true,
|
162
|
-
data: keyData
|
163
|
-
};
|
164
|
-
} catch (err) {
|
165
|
-
console.error("Failed to authorize this key.", err);
|
166
|
-
return {
|
167
|
-
authorized: false,
|
168
|
-
errorMessage: "Internal error",
|
169
|
-
errorCode: "INTERNAL_ERROR",
|
170
|
-
statusCode: 500
|
171
|
-
};
|
172
|
-
}
|
173
|
-
}
|
174
|
-
function authAccess(authOptions, apiKey) {
|
175
|
-
const {
|
176
|
-
origin,
|
177
|
-
secretHash: providedSecretHash
|
178
|
-
} = authOptions;
|
179
|
-
const {
|
180
|
-
domains,
|
181
|
-
secretHash
|
182
|
-
} = apiKey;
|
183
|
-
if (providedSecretHash) {
|
184
|
-
if (secretHash !== providedSecretHash) {
|
185
|
-
return {
|
186
|
-
authorized: false,
|
187
|
-
errorMessage: "The secret is invalid.",
|
188
|
-
errorCode: "SECRET_INVALID",
|
189
|
-
statusCode: 401
|
190
|
-
};
|
191
|
-
}
|
192
|
-
return {
|
193
|
-
authorized: true
|
194
|
-
};
|
195
|
-
}
|
196
|
-
|
197
|
-
// validate domains
|
198
|
-
if (origin) {
|
199
|
-
if (
|
200
|
-
// find matching domain, or if all domains allowed
|
201
|
-
domains.find(d => {
|
202
|
-
if (d === "*") {
|
203
|
-
return true;
|
204
|
-
}
|
205
|
-
|
206
|
-
// If the allowedDomain has a wildcard,
|
207
|
-
// we'll check that the ending of our domain matches the wildcard
|
208
|
-
if (d.startsWith("*.")) {
|
209
|
-
const domainRoot = d.slice(2);
|
210
|
-
return origin.endsWith(domainRoot);
|
211
|
-
}
|
212
|
-
|
213
|
-
// If there's no wildcard, we'll check for an exact match
|
214
|
-
return d === origin;
|
215
|
-
})) {
|
216
|
-
return {
|
217
|
-
authorized: true
|
218
|
-
};
|
219
|
-
}
|
220
|
-
return {
|
221
|
-
authorized: false,
|
222
|
-
errorMessage: "The origin is not authorized for this key.",
|
223
|
-
errorCode: "ORIGIN_UNAUTHORIZED",
|
224
|
-
statusCode: 401
|
225
|
-
};
|
226
|
-
}
|
227
|
-
|
228
|
-
// FIXME: validate bundle id
|
229
|
-
return {
|
230
|
-
authorized: false,
|
231
|
-
errorMessage: "The keys are invalid.",
|
232
|
-
errorCode: "UNAUTHORIZED",
|
233
|
-
statusCode: 401
|
234
|
-
};
|
235
|
-
}
|
236
|
-
function authzServices(validations, apiKey, scope) {
|
237
|
-
const {
|
238
|
-
services
|
239
|
-
} = apiKey;
|
240
|
-
const {
|
241
|
-
serviceTargetAddresses,
|
242
|
-
serviceAction
|
243
|
-
} = validations;
|
244
|
-
|
245
|
-
// validate services
|
246
|
-
const service = services.find(srv => srv.name === scope);
|
247
|
-
if (!service) {
|
248
|
-
return {
|
249
|
-
authorized: false,
|
250
|
-
errorMessage: `The service "${scope}" is not authorized for this key.`,
|
251
|
-
errorCode: "SERVICE_UNAUTHORIZED",
|
252
|
-
statusCode: 403
|
253
|
-
};
|
254
|
-
}
|
255
|
-
|
256
|
-
// validate service actions
|
257
|
-
if (serviceAction) {
|
258
|
-
if (!service.actions.includes(serviceAction)) {
|
259
|
-
return {
|
260
|
-
authorized: false,
|
261
|
-
errorMessage: `The service "${scope}" action "${serviceAction}" is not authorized for this key.`,
|
262
|
-
errorCode: "SERVICE_ACTION_UNAUTHORIZED",
|
263
|
-
statusCode: 403
|
264
|
-
};
|
265
|
-
}
|
266
|
-
}
|
267
|
-
|
268
|
-
// validate service target addresses
|
269
|
-
if (serviceTargetAddresses && !service.targetAddresses.find(addr => addr === "*" || serviceTargetAddresses.includes(addr))) {
|
270
|
-
return {
|
271
|
-
authorized: false,
|
272
|
-
errorMessage: `The service "${scope}" target address is not authorized for this key.`,
|
273
|
-
errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
|
274
|
-
statusCode: 403
|
275
|
-
};
|
276
|
-
}
|
277
|
-
return {
|
278
|
-
authorized: true
|
279
|
-
};
|
280
|
-
}
|
281
|
-
|
282
|
-
export { SERVICES, SERVICE_DEFINITIONS, SERVICE_NAMES, authorizeCFWorkerService, authorizeNodeService, getServiceByName };
|
1
|
+
export { b as SERVICES, S as SERVICE_DEFINITIONS, a as SERVICE_NAMES, g as getServiceByName } from './services-86283509.esm.js';
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"thirdweb-dev-service-utils-node.cjs.d.ts","sourceRoot":"","sources":["../../dist/declarations/src/node/index.d.ts"],"names":[],"mappings":"AAAA"}
|
@@ -0,0 +1,113 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
+
|
5
|
+
var node_crypto = require('node:crypto');
|
6
|
+
var index = require('../../dist/index-fcf69a55.cjs.dev.js');
|
7
|
+
var services = require('../../dist/services-a3f36057.cjs.dev.js');
|
8
|
+
|
9
|
+
async function authorizeNode(authInput, serviceConfig) {
|
10
|
+
let authData;
|
11
|
+
try {
|
12
|
+
authData = extractAuthorizationData(authInput);
|
13
|
+
} catch (e) {
|
14
|
+
if (e instanceof Error && e.message === "KEY_CONFLICT") {
|
15
|
+
return {
|
16
|
+
authorized: false,
|
17
|
+
status: 400,
|
18
|
+
errorMessage: "Please pass either a client id or a secret key.",
|
19
|
+
errorCode: "KEY_CONFLICT"
|
20
|
+
};
|
21
|
+
}
|
22
|
+
return {
|
23
|
+
authorized: false,
|
24
|
+
status: 500,
|
25
|
+
errorMessage: "Internal Server Error",
|
26
|
+
errorCode: "INTERNAL_SERVER_ERROR"
|
27
|
+
};
|
28
|
+
}
|
29
|
+
return await index.authorize(authData, serviceConfig);
|
30
|
+
}
|
31
|
+
function getHeader(headers, headerName) {
|
32
|
+
const header = headers[headerName];
|
33
|
+
if (Array.isArray(header)) {
|
34
|
+
return header[0];
|
35
|
+
}
|
36
|
+
return header ?? null;
|
37
|
+
}
|
38
|
+
function extractAuthorizationData(authInput) {
|
39
|
+
if (!authInput.req.url) {
|
40
|
+
throw new Error("no req.url in authInput.req");
|
41
|
+
}
|
42
|
+
const requestUrl = new URL(authInput.req.url, authInput.req.headers.host);
|
43
|
+
const headers = authInput.req.headers;
|
44
|
+
const secretKey = getHeader(headers, "x-secret-key");
|
45
|
+
// prefer clientId that is explicitly passed in
|
46
|
+
let clientId = authInput.clientId ?? null;
|
47
|
+
if (!clientId) {
|
48
|
+
// next preference is clientId from header
|
49
|
+
clientId = getHeader(headers, "x-client-id");
|
50
|
+
}
|
51
|
+
|
52
|
+
// next preference is search param
|
53
|
+
if (!clientId) {
|
54
|
+
clientId = requestUrl.searchParams.get("clientId");
|
55
|
+
}
|
56
|
+
// bundle id from header is first preference
|
57
|
+
let bundleId = getHeader(headers, "x-bundle-id");
|
58
|
+
|
59
|
+
// next preference is search param
|
60
|
+
if (!bundleId) {
|
61
|
+
bundleId = requestUrl.searchParams.get("bundleId");
|
62
|
+
}
|
63
|
+
let origin = getHeader(headers, "origin");
|
64
|
+
// if origin header is not available we'll fall back to referrer;
|
65
|
+
if (!origin) {
|
66
|
+
origin = getHeader(headers, "referer");
|
67
|
+
}
|
68
|
+
// if we have an origin at this point, normalize it
|
69
|
+
if (origin) {
|
70
|
+
try {
|
71
|
+
origin = new URL(origin).hostname;
|
72
|
+
} catch (e) {
|
73
|
+
console.warn("failed to parse origin", origin, e);
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
// handle if we a secret key is passed in the headers
|
78
|
+
let secretKeyHash = null;
|
79
|
+
if (secretKey) {
|
80
|
+
// hash the secret key
|
81
|
+
secretKeyHash = hashSecretKey(secretKey);
|
82
|
+
// derive the client id from the secret key hash
|
83
|
+
const derivedClientId = deriveClientIdFromSecretKeyHash(secretKeyHash);
|
84
|
+
// if we already have a client id passed in we need to make sure they match
|
85
|
+
if (clientId && clientId !== derivedClientId) {
|
86
|
+
throw new Error("KEY_CONFLICT");
|
87
|
+
}
|
88
|
+
// otherwise set the client id to the derived client id (client id based off of secret key)
|
89
|
+
clientId = derivedClientId;
|
90
|
+
}
|
91
|
+
return {
|
92
|
+
secretKeyHash,
|
93
|
+
secretKey,
|
94
|
+
clientId,
|
95
|
+
origin,
|
96
|
+
bundleId
|
97
|
+
};
|
98
|
+
}
|
99
|
+
function hashSecretKey(secretKey) {
|
100
|
+
return node_crypto.createHash("sha256").update(secretKey).digest("hex");
|
101
|
+
}
|
102
|
+
function deriveClientIdFromSecretKeyHash(secretKeyHash) {
|
103
|
+
return secretKeyHash.slice(0, 32);
|
104
|
+
}
|
105
|
+
|
106
|
+
exports.SERVICES = services.SERVICES;
|
107
|
+
exports.SERVICE_DEFINITIONS = services.SERVICE_DEFINITIONS;
|
108
|
+
exports.SERVICE_NAMES = services.SERVICE_NAMES;
|
109
|
+
exports.getServiceByName = services.getServiceByName;
|
110
|
+
exports.authorizeNode = authorizeNode;
|
111
|
+
exports.deriveClientIdFromSecretKeyHash = deriveClientIdFromSecretKeyHash;
|
112
|
+
exports.extractAuthorizationData = extractAuthorizationData;
|
113
|
+
exports.hashSecretKey = hashSecretKey;
|