@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.
Files changed (45) hide show
  1. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts +2 -0
  2. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts.map +1 -0
  3. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.dev.js +115 -0
  4. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.js +7 -0
  5. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +115 -0
  6. package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +105 -0
  7. package/cf-worker/package.json +4 -0
  8. package/dist/declarations/src/cf-worker/index.d.ts +18 -0
  9. package/dist/declarations/src/cf-worker/index.d.ts.map +1 -0
  10. package/dist/declarations/src/core/api.d.ts +31 -0
  11. package/dist/declarations/src/core/api.d.ts.map +1 -0
  12. package/dist/declarations/src/core/authorize/index.d.ts +18 -0
  13. package/dist/declarations/src/core/authorize/index.d.ts.map +1 -0
  14. package/dist/declarations/src/core/authorize/types.d.ts +11 -0
  15. package/dist/declarations/src/core/authorize/types.d.ts.map +1 -0
  16. package/dist/declarations/src/core/services.d.ts.map +1 -0
  17. package/dist/declarations/src/core/types.d.ts +5 -0
  18. package/dist/declarations/src/core/types.d.ts.map +1 -0
  19. package/dist/declarations/src/index.d.ts +1 -2
  20. package/dist/declarations/src/index.d.ts.map +1 -1
  21. package/dist/declarations/src/node/index.d.ts +16 -0
  22. package/dist/declarations/src/node/index.d.ts.map +1 -0
  23. package/dist/index-294e111f.esm.js +252 -0
  24. package/dist/index-3060948e.cjs.prod.js +254 -0
  25. package/dist/index-fcf69a55.cjs.dev.js +254 -0
  26. package/dist/services-86283509.esm.js +44 -0
  27. package/dist/services-9e185105.cjs.prod.js +49 -0
  28. package/dist/services-a3f36057.cjs.dev.js +49 -0
  29. package/dist/thirdweb-dev-service-utils.cjs.dev.js +5 -284
  30. package/dist/thirdweb-dev-service-utils.cjs.prod.js +5 -284
  31. package/dist/thirdweb-dev-service-utils.esm.js +1 -282
  32. package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts +2 -0
  33. package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts.map +1 -0
  34. package/node/dist/thirdweb-dev-service-utils-node.cjs.dev.js +113 -0
  35. package/node/dist/thirdweb-dev-service-utils-node.cjs.js +7 -0
  36. package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +113 -0
  37. package/node/dist/thirdweb-dev-service-utils-node.esm.js +102 -0
  38. package/node/package.json +4 -0
  39. package/package.json +22 -10
  40. package/dist/declarations/src/auth/index.d.ts +0 -4
  41. package/dist/declarations/src/auth/index.d.ts.map +0 -1
  42. package/dist/declarations/src/auth/types.d.ts +0 -61
  43. package/dist/declarations/src/auth/types.d.ts.map +0 -1
  44. package/dist/declarations/src/services.d.ts.map +0 -1
  45. /package/dist/declarations/src/{services.d.ts → core/services.d.ts} +0 -0
@@ -0,0 +1,252 @@
1
+ async function fetchKeyMetadataFromApi(clientId, config) {
2
+ const {
3
+ apiUrl,
4
+ serviceScope,
5
+ serviceApiKey
6
+ } = config;
7
+ const url = new URL(`${apiUrl}/v1/keys/use`);
8
+ url.searchParams.set("clientId", clientId);
9
+ url.searchParams.set("scope", serviceScope);
10
+ const response = await fetch(url, {
11
+ method: "GET",
12
+ headers: {
13
+ "x-service-api-key": serviceApiKey,
14
+ "content-type": "application/json"
15
+ }
16
+ });
17
+ if (!response.ok) {
18
+ throw new Error(`Error fetching key metadata from API: ${response.statusText}`);
19
+ }
20
+ return await response.json();
21
+ }
22
+
23
+ function authorizeClient(authOptions, apiKeyMeta) {
24
+ const {
25
+ origin,
26
+ secretKeyHash: providedSecretHash
27
+ } = authOptions;
28
+ const {
29
+ domains,
30
+ secretHash
31
+ } = apiKeyMeta;
32
+ if (providedSecretHash) {
33
+ if (secretHash !== providedSecretHash) {
34
+ return {
35
+ authorized: false,
36
+ errorMessage: "The secret is invalid.",
37
+ errorCode: "SECRET_INVALID",
38
+ status: 401
39
+ };
40
+ }
41
+ return {
42
+ authorized: true,
43
+ apiKeyMeta
44
+ };
45
+ }
46
+
47
+ // validate domains
48
+ if (origin) {
49
+ if (
50
+ // find matching domain, or if all domains allowed
51
+ domains.find(d => {
52
+ if (d === "*") {
53
+ return true;
54
+ }
55
+
56
+ // If the allowedDomain has a wildcard,
57
+ // we'll check that the ending of our domain matches the wildcard
58
+ if (d.startsWith("*.")) {
59
+ const domainRoot = d.slice(2);
60
+ return origin.endsWith(domainRoot);
61
+ }
62
+
63
+ // If there's no wildcard, we'll check for an exact match
64
+ return d === origin;
65
+ })) {
66
+ return {
67
+ authorized: true,
68
+ apiKeyMeta
69
+ };
70
+ }
71
+ return {
72
+ authorized: false,
73
+ errorMessage: "The origin is not authorized for this key.",
74
+ errorCode: "ORIGIN_UNAUTHORIZED",
75
+ status: 401
76
+ };
77
+ }
78
+
79
+ // FIXME: validate bundle id
80
+ return {
81
+ authorized: false,
82
+ errorMessage: "The keys are invalid.",
83
+ errorCode: "UNAUTHORIZED",
84
+ status: 401
85
+ };
86
+ }
87
+
88
+ function authorizeService(apikeyMetadata, serviceConfig, authorizationPayload) {
89
+ const {
90
+ services
91
+ } = apikeyMetadata;
92
+ // const { serviceTargetAddresses, serviceAction } = validations;
93
+
94
+ // validate services
95
+ const service = services.find(srv => srv.name === serviceConfig.serviceScope);
96
+ if (!service) {
97
+ return {
98
+ authorized: false,
99
+ errorMessage: `The service "${serviceConfig.serviceScope}" is not authorized for this key.`,
100
+ errorCode: "SERVICE_UNAUTHORIZED",
101
+ status: 403
102
+ };
103
+ }
104
+
105
+ // validate service actions
106
+ if (serviceConfig.serviceAction) {
107
+ const isActionAllowed = service.actions.includes(serviceConfig.serviceAction);
108
+ if (!isActionAllowed) {
109
+ return {
110
+ authorized: false,
111
+ errorMessage: `The service "${serviceConfig.serviceScope}" action "${serviceConfig.serviceAction}" is not authorized for this key.`,
112
+ errorCode: "SERVICE_ACTION_UNAUTHORIZED",
113
+ status: 403
114
+ };
115
+ }
116
+ }
117
+
118
+ // validate service target addresses
119
+ // the service has to pass in the target address for this to be validated
120
+ if (authorizationPayload?.targetAddress) {
121
+ const isTargetAddressAllowed = service.targetAddresses.includes(authorizationPayload.targetAddress);
122
+ if (!isTargetAddressAllowed) {
123
+ return {
124
+ authorized: false,
125
+ errorMessage: `The service "${serviceConfig.serviceScope}" target address "${authorizationPayload.targetAddress}" is not authorized for this key.`,
126
+ errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
127
+ status: 403
128
+ };
129
+ }
130
+ }
131
+ return {
132
+ authorized: true,
133
+ apiKeyMeta: apikeyMetadata
134
+ };
135
+ }
136
+
137
+ async function authorize(authData, serviceConfig, cacheOptions) {
138
+ // if we don't have a client id at this point we can't authorize
139
+ if (!authData.clientId) {
140
+ return {
141
+ authorized: false,
142
+ status: 401,
143
+ errorMessage: "Missing clientId or secretKey.",
144
+ errorCode: "MISSING_KEY"
145
+ };
146
+ }
147
+ let apiKeyMeta = null;
148
+ // if we have cache options we want to check the cache first
149
+ if (cacheOptions) {
150
+ try {
151
+ const cachedKey = await cacheOptions.get(authData.clientId);
152
+ if (cachedKey) {
153
+ const parsed = JSON.parse(cachedKey);
154
+ if ("updatedAt" in parsed) {
155
+ // we want to compare the updatedAt time to the current time
156
+ // if the difference is greater than the cacheTtl we want to ignore the cached data
157
+ const now = Date.now();
158
+ const diff = now - parsed.updatedAt;
159
+ const cacheTtl = cacheOptions.cacheTtlSeconds * 1000;
160
+ // only if the diff is less than the cacheTtl do we want to use the cached key
161
+ if (diff < cacheTtl * 1000) {
162
+ apiKeyMeta = parsed.apiKeyMeta;
163
+ }
164
+ } else {
165
+ apiKeyMeta = parsed;
166
+ }
167
+ }
168
+ } catch (err) {
169
+ // ignore errors, proceed as if not in cache
170
+ }
171
+ }
172
+
173
+ // if we don't have a cached key, fetch from the API
174
+ if (!apiKeyMeta) {
175
+ try {
176
+ const {
177
+ data,
178
+ error
179
+ } = await fetchKeyMetadataFromApi(authData.clientId, serviceConfig);
180
+ if (error) {
181
+ return {
182
+ authorized: false,
183
+ errorCode: error.code,
184
+ errorMessage: error.message,
185
+ status: error.statusCode
186
+ };
187
+ } else if (!data) {
188
+ return {
189
+ authorized: false,
190
+ errorCode: "NO_KEY",
191
+ errorMessage: "No error but also no key returned.",
192
+ status: 500
193
+ };
194
+ }
195
+ // if we have a key for sure then assign it
196
+ apiKeyMeta = data;
197
+
198
+ // cache the retrieved key if we have cache options
199
+ if (cacheOptions) {
200
+ // we await this always because it can be a promise or not
201
+ await cacheOptions.put(authData.clientId, data);
202
+ }
203
+ } catch (err) {
204
+ console.warn("failed to fetch key metadata from api", err);
205
+ return {
206
+ authorized: false,
207
+ status: 500,
208
+ errorMessage: "Failed to fetch key metadata.",
209
+ errorCode: "FAILED_TO_FETCH_KEY"
210
+ };
211
+ }
212
+ }
213
+ if (!apiKeyMeta) {
214
+ return {
215
+ authorized: false,
216
+ status: 401,
217
+ errorMessage: "Key is invalid.",
218
+ errorCode: "INVALID_KEY"
219
+ };
220
+ }
221
+ // now we can validate the key itself
222
+ const clientAuth = authorizeClient(authData, apiKeyMeta);
223
+ if (!clientAuth.authorized) {
224
+ return {
225
+ errorCode: clientAuth.errorCode,
226
+ authorized: false,
227
+ status: 401,
228
+ errorMessage: clientAuth.errorMessage
229
+ };
230
+ }
231
+
232
+ // if we've made it this far we need to check service specific authorization
233
+ const serviceAuth = authorizeService(apiKeyMeta, serviceConfig, {
234
+ targetAddress: authData.targetAddress
235
+ });
236
+ if (!serviceAuth.authorized) {
237
+ return {
238
+ errorCode: serviceAuth.errorCode,
239
+ authorized: false,
240
+ status: 403,
241
+ errorMessage: serviceAuth.errorMessage
242
+ };
243
+ }
244
+
245
+ // if we reach this point we are authorized!
246
+ return {
247
+ authorized: true,
248
+ apiKeyMeta
249
+ };
250
+ }
251
+
252
+ export { authorize as a };
@@ -0,0 +1,254 @@
1
+ 'use strict';
2
+
3
+ async function fetchKeyMetadataFromApi(clientId, config) {
4
+ const {
5
+ apiUrl,
6
+ serviceScope,
7
+ serviceApiKey
8
+ } = config;
9
+ const url = new URL(`${apiUrl}/v1/keys/use`);
10
+ url.searchParams.set("clientId", clientId);
11
+ url.searchParams.set("scope", serviceScope);
12
+ const response = await fetch(url, {
13
+ method: "GET",
14
+ headers: {
15
+ "x-service-api-key": serviceApiKey,
16
+ "content-type": "application/json"
17
+ }
18
+ });
19
+ if (!response.ok) {
20
+ throw new Error(`Error fetching key metadata from API: ${response.statusText}`);
21
+ }
22
+ return await response.json();
23
+ }
24
+
25
+ function authorizeClient(authOptions, apiKeyMeta) {
26
+ const {
27
+ origin,
28
+ secretKeyHash: providedSecretHash
29
+ } = authOptions;
30
+ const {
31
+ domains,
32
+ secretHash
33
+ } = apiKeyMeta;
34
+ if (providedSecretHash) {
35
+ if (secretHash !== providedSecretHash) {
36
+ return {
37
+ authorized: false,
38
+ errorMessage: "The secret is invalid.",
39
+ errorCode: "SECRET_INVALID",
40
+ status: 401
41
+ };
42
+ }
43
+ return {
44
+ authorized: true,
45
+ apiKeyMeta
46
+ };
47
+ }
48
+
49
+ // validate domains
50
+ if (origin) {
51
+ if (
52
+ // find matching domain, or if all domains allowed
53
+ domains.find(d => {
54
+ if (d === "*") {
55
+ return true;
56
+ }
57
+
58
+ // If the allowedDomain has a wildcard,
59
+ // we'll check that the ending of our domain matches the wildcard
60
+ if (d.startsWith("*.")) {
61
+ const domainRoot = d.slice(2);
62
+ return origin.endsWith(domainRoot);
63
+ }
64
+
65
+ // If there's no wildcard, we'll check for an exact match
66
+ return d === origin;
67
+ })) {
68
+ return {
69
+ authorized: true,
70
+ apiKeyMeta
71
+ };
72
+ }
73
+ return {
74
+ authorized: false,
75
+ errorMessage: "The origin is not authorized for this key.",
76
+ errorCode: "ORIGIN_UNAUTHORIZED",
77
+ status: 401
78
+ };
79
+ }
80
+
81
+ // FIXME: validate bundle id
82
+ return {
83
+ authorized: false,
84
+ errorMessage: "The keys are invalid.",
85
+ errorCode: "UNAUTHORIZED",
86
+ status: 401
87
+ };
88
+ }
89
+
90
+ function authorizeService(apikeyMetadata, serviceConfig, authorizationPayload) {
91
+ const {
92
+ services
93
+ } = apikeyMetadata;
94
+ // const { serviceTargetAddresses, serviceAction } = validations;
95
+
96
+ // validate services
97
+ const service = services.find(srv => srv.name === serviceConfig.serviceScope);
98
+ if (!service) {
99
+ return {
100
+ authorized: false,
101
+ errorMessage: `The service "${serviceConfig.serviceScope}" is not authorized for this key.`,
102
+ errorCode: "SERVICE_UNAUTHORIZED",
103
+ status: 403
104
+ };
105
+ }
106
+
107
+ // validate service actions
108
+ if (serviceConfig.serviceAction) {
109
+ const isActionAllowed = service.actions.includes(serviceConfig.serviceAction);
110
+ if (!isActionAllowed) {
111
+ return {
112
+ authorized: false,
113
+ errorMessage: `The service "${serviceConfig.serviceScope}" action "${serviceConfig.serviceAction}" is not authorized for this key.`,
114
+ errorCode: "SERVICE_ACTION_UNAUTHORIZED",
115
+ status: 403
116
+ };
117
+ }
118
+ }
119
+
120
+ // validate service target addresses
121
+ // the service has to pass in the target address for this to be validated
122
+ if (authorizationPayload?.targetAddress) {
123
+ const isTargetAddressAllowed = service.targetAddresses.includes(authorizationPayload.targetAddress);
124
+ if (!isTargetAddressAllowed) {
125
+ return {
126
+ authorized: false,
127
+ errorMessage: `The service "${serviceConfig.serviceScope}" target address "${authorizationPayload.targetAddress}" is not authorized for this key.`,
128
+ errorCode: "SERVICE_TARGET_ADDRESS_UNAUTHORIZED",
129
+ status: 403
130
+ };
131
+ }
132
+ }
133
+ return {
134
+ authorized: true,
135
+ apiKeyMeta: apikeyMetadata
136
+ };
137
+ }
138
+
139
+ async function authorize(authData, serviceConfig, cacheOptions) {
140
+ // if we don't have a client id at this point we can't authorize
141
+ if (!authData.clientId) {
142
+ return {
143
+ authorized: false,
144
+ status: 401,
145
+ errorMessage: "Missing clientId or secretKey.",
146
+ errorCode: "MISSING_KEY"
147
+ };
148
+ }
149
+ let apiKeyMeta = null;
150
+ // if we have cache options we want to check the cache first
151
+ if (cacheOptions) {
152
+ try {
153
+ const cachedKey = await cacheOptions.get(authData.clientId);
154
+ if (cachedKey) {
155
+ const parsed = JSON.parse(cachedKey);
156
+ if ("updatedAt" in parsed) {
157
+ // we want to compare the updatedAt time to the current time
158
+ // if the difference is greater than the cacheTtl we want to ignore the cached data
159
+ const now = Date.now();
160
+ const diff = now - parsed.updatedAt;
161
+ const cacheTtl = cacheOptions.cacheTtlSeconds * 1000;
162
+ // only if the diff is less than the cacheTtl do we want to use the cached key
163
+ if (diff < cacheTtl * 1000) {
164
+ apiKeyMeta = parsed.apiKeyMeta;
165
+ }
166
+ } else {
167
+ apiKeyMeta = parsed;
168
+ }
169
+ }
170
+ } catch (err) {
171
+ // ignore errors, proceed as if not in cache
172
+ }
173
+ }
174
+
175
+ // if we don't have a cached key, fetch from the API
176
+ if (!apiKeyMeta) {
177
+ try {
178
+ const {
179
+ data,
180
+ error
181
+ } = await fetchKeyMetadataFromApi(authData.clientId, serviceConfig);
182
+ if (error) {
183
+ return {
184
+ authorized: false,
185
+ errorCode: error.code,
186
+ errorMessage: error.message,
187
+ status: error.statusCode
188
+ };
189
+ } else if (!data) {
190
+ return {
191
+ authorized: false,
192
+ errorCode: "NO_KEY",
193
+ errorMessage: "No error but also no key returned.",
194
+ status: 500
195
+ };
196
+ }
197
+ // if we have a key for sure then assign it
198
+ apiKeyMeta = data;
199
+
200
+ // cache the retrieved key if we have cache options
201
+ if (cacheOptions) {
202
+ // we await this always because it can be a promise or not
203
+ await cacheOptions.put(authData.clientId, data);
204
+ }
205
+ } catch (err) {
206
+ console.warn("failed to fetch key metadata from api", err);
207
+ return {
208
+ authorized: false,
209
+ status: 500,
210
+ errorMessage: "Failed to fetch key metadata.",
211
+ errorCode: "FAILED_TO_FETCH_KEY"
212
+ };
213
+ }
214
+ }
215
+ if (!apiKeyMeta) {
216
+ return {
217
+ authorized: false,
218
+ status: 401,
219
+ errorMessage: "Key is invalid.",
220
+ errorCode: "INVALID_KEY"
221
+ };
222
+ }
223
+ // now we can validate the key itself
224
+ const clientAuth = authorizeClient(authData, apiKeyMeta);
225
+ if (!clientAuth.authorized) {
226
+ return {
227
+ errorCode: clientAuth.errorCode,
228
+ authorized: false,
229
+ status: 401,
230
+ errorMessage: clientAuth.errorMessage
231
+ };
232
+ }
233
+
234
+ // if we've made it this far we need to check service specific authorization
235
+ const serviceAuth = authorizeService(apiKeyMeta, serviceConfig, {
236
+ targetAddress: authData.targetAddress
237
+ });
238
+ if (!serviceAuth.authorized) {
239
+ return {
240
+ errorCode: serviceAuth.errorCode,
241
+ authorized: false,
242
+ status: 403,
243
+ errorMessage: serviceAuth.errorMessage
244
+ };
245
+ }
246
+
247
+ // if we reach this point we are authorized!
248
+ return {
249
+ authorized: true,
250
+ apiKeyMeta
251
+ };
252
+ }
253
+
254
+ exports.authorize = authorize;