@thirdweb-dev/service-utils 0.4.38 → 0.4.39
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/cjs/cf-worker/index.js +155 -0
- package/dist/cjs/cf-worker/index.js.map +1 -0
- package/dist/cjs/cf-worker/usage.js +55 -0
- package/dist/cjs/cf-worker/usage.js.map +1 -0
- package/dist/cjs/core/api.js +65 -0
- package/dist/cjs/core/api.js.map +1 -0
- package/dist/cjs/core/authorize/client.js +115 -0
- package/dist/cjs/core/authorize/client.js.map +1 -0
- package/dist/cjs/core/authorize/index.js +215 -0
- package/dist/cjs/core/authorize/index.js.map +1 -0
- package/dist/cjs/core/authorize/service.js +58 -0
- package/dist/cjs/core/authorize/service.js.map +1 -0
- package/dist/cjs/core/authorize/types.js +3 -0
- package/dist/cjs/core/authorize/types.js.map +1 -0
- package/dist/cjs/core/rateLimit/index.js +64 -0
- package/dist/cjs/core/rateLimit/index.js.map +1 -0
- package/dist/cjs/core/rateLimit/types.js +3 -0
- package/dist/cjs/core/rateLimit/types.js.map +1 -0
- package/dist/cjs/core/services.js +71 -0
- package/dist/cjs/core/services.js.map +1 -0
- package/dist/cjs/core/types.js +3 -0
- package/dist/cjs/core/types.js.map +1 -0
- package/dist/cjs/core/usage.js +93 -0
- package/dist/cjs/core/usage.js.map +1 -0
- package/dist/cjs/core/usageLimit/index.js +45 -0
- package/dist/cjs/core/usageLimit/index.js.map +1 -0
- package/dist/cjs/core/usageLimit/types.js +3 -0
- package/dist/cjs/core/usageLimit/types.js.map +1 -0
- package/dist/cjs/index.js +10 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/mocks.js +53 -0
- package/dist/cjs/mocks.js.map +1 -0
- package/dist/cjs/node/index.js +173 -0
- package/dist/cjs/node/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/cf-worker/index.js +147 -0
- package/dist/esm/cf-worker/index.js.map +1 -0
- package/dist/esm/cf-worker/usage.js +54 -0
- package/dist/esm/cf-worker/usage.js.map +1 -0
- package/dist/esm/core/api.js +60 -0
- package/dist/esm/core/api.js.map +1 -0
- package/dist/esm/core/authorize/client.js +110 -0
- package/dist/esm/core/authorize/client.js.map +1 -0
- package/dist/esm/core/authorize/index.js +212 -0
- package/dist/esm/core/authorize/index.js.map +1 -0
- package/dist/esm/core/authorize/service.js +55 -0
- package/dist/esm/core/authorize/service.js.map +1 -0
- package/dist/esm/core/authorize/types.js +2 -0
- package/dist/esm/core/authorize/types.js.map +1 -0
- package/dist/esm/core/rateLimit/index.js +61 -0
- package/dist/esm/core/rateLimit/index.js.map +1 -0
- package/dist/esm/core/rateLimit/types.js +2 -0
- package/dist/esm/core/rateLimit/types.js.map +1 -0
- package/dist/esm/core/services.js +67 -0
- package/dist/esm/core/services.js.map +1 -0
- package/dist/esm/core/types.js +2 -0
- package/dist/esm/core/types.js.map +1 -0
- package/dist/esm/core/usage.js +90 -0
- package/dist/esm/core/usage.js.map +1 -0
- package/dist/esm/core/usageLimit/index.js +42 -0
- package/dist/esm/core/usageLimit/index.js.map +1 -0
- package/dist/esm/core/usageLimit/types.js +2 -0
- package/dist/esm/core/usageLimit/types.js.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/mocks.js +50 -0
- package/dist/esm/mocks.js.map +1 -0
- package/dist/esm/node/index.js +165 -0
- package/dist/esm/node/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/{declarations/src → types}/cf-worker/index.d.ts +8 -8
- package/dist/types/cf-worker/index.d.ts.map +1 -0
- package/dist/{declarations/src → types}/cf-worker/usage.d.ts +3 -2
- package/dist/types/cf-worker/usage.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/api.d.ts +1 -1
- package/dist/types/core/api.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/authorize/client.d.ts +2 -2
- package/dist/types/core/authorize/client.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/authorize/index.d.ts +2 -2
- package/dist/types/core/authorize/index.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/authorize/service.d.ts +2 -2
- package/dist/types/core/authorize/service.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/authorize/types.d.ts +1 -1
- package/dist/types/core/authorize/types.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/rateLimit/index.d.ts +3 -3
- package/dist/types/core/rateLimit/index.d.ts.map +1 -0
- package/dist/types/core/rateLimit/types.d.ts.map +1 -0
- package/dist/types/core/services.d.ts.map +1 -0
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/{declarations/src → types}/core/usage.d.ts +2 -2
- package/dist/types/core/usage.d.ts.map +1 -0
- package/dist/types/core/usageLimit/index.d.ts +5 -0
- package/dist/types/core/usageLimit/index.d.ts.map +1 -0
- package/dist/types/core/usageLimit/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/mocks.d.ts +5 -0
- package/dist/types/mocks.d.ts.map +1 -0
- package/dist/{declarations/src → types}/node/index.d.ts +8 -8
- package/dist/types/node/index.d.ts.map +1 -0
- package/package.json +36 -29
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts +0 -2
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.d.ts.map +0 -1
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.dev.js +0 -226
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.js +0 -7
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.cjs.prod.js +0 -226
- package/cf-worker/dist/thirdweb-dev-service-utils-cf-worker.esm.js +0 -212
- package/cf-worker/package.json +0 -4
- package/dist/client-8440b8fb.esm.js +0 -195
- package/dist/client-84e46164.cjs.prod.js +0 -203
- package/dist/client-a5cc5822.cjs.dev.js +0 -203
- package/dist/declarations/src/cf-worker/index.d.ts.map +0 -1
- package/dist/declarations/src/cf-worker/usage.d.ts.map +0 -1
- package/dist/declarations/src/core/api.d.ts.map +0 -1
- package/dist/declarations/src/core/authorize/client.d.ts.map +0 -1
- package/dist/declarations/src/core/authorize/index.d.ts.map +0 -1
- package/dist/declarations/src/core/authorize/service.d.ts.map +0 -1
- package/dist/declarations/src/core/authorize/types.d.ts.map +0 -1
- package/dist/declarations/src/core/rateLimit/index.d.ts.map +0 -1
- package/dist/declarations/src/core/rateLimit/types.d.ts.map +0 -1
- package/dist/declarations/src/core/services.d.ts.map +0 -1
- package/dist/declarations/src/core/types.d.ts.map +0 -1
- package/dist/declarations/src/core/usage.d.ts.map +0 -1
- package/dist/declarations/src/core/usageLimit/index.d.ts +0 -5
- package/dist/declarations/src/core/usageLimit/index.d.ts.map +0 -1
- package/dist/declarations/src/core/usageLimit/types.d.ts.map +0 -1
- package/dist/declarations/src/index.d.ts +0 -3
- package/dist/declarations/src/index.d.ts.map +0 -1
- package/dist/declarations/src/node/index.d.ts.map +0 -1
- package/dist/index-23f268d8.cjs.prod.js +0 -540
- package/dist/index-5dc16842.esm.js +0 -535
- package/dist/index-88f1ffb6.cjs.dev.js +0 -540
- package/dist/thirdweb-dev-service-utils.cjs.d.ts +0 -2
- package/dist/thirdweb-dev-service-utils.cjs.d.ts.map +0 -1
- package/dist/thirdweb-dev-service-utils.cjs.dev.js +0 -14
- package/dist/thirdweb-dev-service-utils.cjs.js +0 -7
- package/dist/thirdweb-dev-service-utils.cjs.prod.js +0 -14
- package/dist/thirdweb-dev-service-utils.esm.js +0 -1
- package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts +0 -2
- package/node/dist/thirdweb-dev-service-utils-node.cjs.d.ts.map +0 -1
- package/node/dist/thirdweb-dev-service-utils-node.cjs.dev.js +0 -190
- package/node/dist/thirdweb-dev-service-utils-node.cjs.js +0 -7
- package/node/dist/thirdweb-dev-service-utils-node.cjs.prod.js +0 -190
- package/node/dist/thirdweb-dev-service-utils-node.esm.js +0 -176
- package/node/package.json +0 -4
- /package/dist/{declarations/src → types}/core/rateLimit/types.d.ts +0 -0
- /package/dist/{declarations/src → types}/core/services.d.ts +0 -0
- /package/dist/{declarations/src → types}/core/types.d.ts +0 -0
- /package/dist/{declarations/src → types}/core/usageLimit/types.d.ts +0 -0
@@ -1,226 +0,0 @@
|
|
1
|
-
'use strict';
|
2
|
-
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
4
|
-
|
5
|
-
var index = require('../../dist/index-23f268d8.cjs.prod.js');
|
6
|
-
var aws4fetch = require('aws4fetch');
|
7
|
-
var client = require('../../dist/client-84e46164.cjs.prod.js');
|
8
|
-
require('zod');
|
9
|
-
|
10
|
-
// Initialize a singleton for AWS usage.
|
11
|
-
let _aws;
|
12
|
-
function getAws(options) {
|
13
|
-
if (!_aws) {
|
14
|
-
_aws = new aws4fetch.AwsClient(options);
|
15
|
-
}
|
16
|
-
return _aws;
|
17
|
-
}
|
18
|
-
|
19
|
-
/**
|
20
|
-
* Publish usage events. Provide the relevant fields for your application.
|
21
|
-
*
|
22
|
-
* Usage in Cloudflare Workers:
|
23
|
-
* ctx.waitUntil(
|
24
|
-
* publishUsageEvents(
|
25
|
-
* [event1, event2],
|
26
|
-
* { queueUrl, accessKeyId, secretAccessKey },
|
27
|
-
* )
|
28
|
-
* )
|
29
|
-
*
|
30
|
-
* @param usageEvents
|
31
|
-
* @param config
|
32
|
-
*/
|
33
|
-
async function publishUsageEvents(usageEvents, config) {
|
34
|
-
const {
|
35
|
-
queueUrl,
|
36
|
-
accessKeyId,
|
37
|
-
secretAccessKey,
|
38
|
-
region = "us-west-2"
|
39
|
-
} = config;
|
40
|
-
const entries = usageEvents.map(event => {
|
41
|
-
// Enforce schema of usage event.
|
42
|
-
const parsed = index.usageEventSchema.parse(event);
|
43
|
-
return {
|
44
|
-
Id: crypto.randomUUID(),
|
45
|
-
MessageBody: JSON.stringify(parsed)
|
46
|
-
};
|
47
|
-
});
|
48
|
-
const aws = getAws({
|
49
|
-
accessKeyId,
|
50
|
-
secretAccessKey,
|
51
|
-
region
|
52
|
-
});
|
53
|
-
await aws.fetch(`https://sqs.${region}.amazonaws.com`, {
|
54
|
-
headers: {
|
55
|
-
"X-Amz-Target": "AmazonSQS.SendMessageBatch",
|
56
|
-
"X-Amz-Date": new Date().toISOString(),
|
57
|
-
"Content-Type": "application/x-amz-json-1.0"
|
58
|
-
},
|
59
|
-
body: JSON.stringify({
|
60
|
-
QueueUrl: queueUrl,
|
61
|
-
Entries: entries
|
62
|
-
})
|
63
|
-
});
|
64
|
-
}
|
65
|
-
|
66
|
-
const DEFAULT_CACHE_TTL_SECONDS = 60;
|
67
|
-
async function authorizeWorker(authInput, serviceConfig) {
|
68
|
-
let authData;
|
69
|
-
try {
|
70
|
-
authData = await extractAuthorizationData(authInput);
|
71
|
-
} catch (e) {
|
72
|
-
if (e instanceof Error && e.message === "KEY_CONFLICT") {
|
73
|
-
return {
|
74
|
-
authorized: false,
|
75
|
-
status: 400,
|
76
|
-
errorMessage: "Please pass either a client id or a secret key.",
|
77
|
-
errorCode: "KEY_CONFLICT"
|
78
|
-
};
|
79
|
-
}
|
80
|
-
return {
|
81
|
-
authorized: false,
|
82
|
-
status: 500,
|
83
|
-
errorMessage: "Internal Server Error",
|
84
|
-
errorCode: "INTERNAL_SERVER_ERROR"
|
85
|
-
};
|
86
|
-
}
|
87
|
-
return await index.authorize(authData, serviceConfig, {
|
88
|
-
get: async clientId => serviceConfig.kvStore.get(clientId),
|
89
|
-
put: (clientId, apiKeyMeta) => serviceConfig.ctx.waitUntil(serviceConfig.kvStore.put(clientId, JSON.stringify({
|
90
|
-
updatedAt: Date.now(),
|
91
|
-
apiKeyMeta
|
92
|
-
}), {
|
93
|
-
expirationTtl: serviceConfig.cacheTtlSeconds && serviceConfig.cacheTtlSeconds >= DEFAULT_CACHE_TTL_SECONDS ? serviceConfig.cacheTtlSeconds : DEFAULT_CACHE_TTL_SECONDS
|
94
|
-
})),
|
95
|
-
cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
|
96
|
-
});
|
97
|
-
}
|
98
|
-
async function extractAuthorizationData(authInput) {
|
99
|
-
const requestUrl = new URL(authInput.req.url);
|
100
|
-
const headers = authInput.req.headers;
|
101
|
-
const secretKey = headers.get("x-secret-key");
|
102
|
-
|
103
|
-
// prefer clientId that is explicitly passed in
|
104
|
-
let clientId = authInput.clientId ?? null;
|
105
|
-
if (!clientId) {
|
106
|
-
// next preference is clientId from header
|
107
|
-
clientId = headers.get("x-client-id");
|
108
|
-
}
|
109
|
-
|
110
|
-
// next preference is search param
|
111
|
-
if (!clientId) {
|
112
|
-
clientId = requestUrl.searchParams.get("clientId");
|
113
|
-
}
|
114
|
-
// bundle id from header is first preference
|
115
|
-
let bundleId = headers.get("x-bundle-id");
|
116
|
-
|
117
|
-
// next preference is search param
|
118
|
-
if (!bundleId) {
|
119
|
-
bundleId = requestUrl.searchParams.get("bundleId");
|
120
|
-
}
|
121
|
-
let origin = headers.get("origin");
|
122
|
-
// if origin header is not available we'll fall back to referrer;
|
123
|
-
if (!origin) {
|
124
|
-
origin = headers.get("referer");
|
125
|
-
}
|
126
|
-
// if we have an origin at this point, normalize it
|
127
|
-
if (origin) {
|
128
|
-
try {
|
129
|
-
origin = new URL(origin).host;
|
130
|
-
} catch (e) {
|
131
|
-
console.warn("failed to parse origin", origin, e);
|
132
|
-
}
|
133
|
-
}
|
134
|
-
|
135
|
-
// handle if we a secret key is passed in the headers
|
136
|
-
let secretKeyHash = null;
|
137
|
-
if (secretKey) {
|
138
|
-
// hash the secret key
|
139
|
-
secretKeyHash = await hashSecretKey(secretKey);
|
140
|
-
// derive the client id from the secret key hash
|
141
|
-
const derivedClientId = deriveClientIdFromSecretKeyHash(secretKeyHash);
|
142
|
-
// if we already have a client id passed in we need to make sure they match
|
143
|
-
if (clientId && clientId !== derivedClientId) {
|
144
|
-
throw new Error("KEY_CONFLICT");
|
145
|
-
}
|
146
|
-
// otherwise set the client id to the derived client id (client id based off of secret key)
|
147
|
-
clientId = derivedClientId;
|
148
|
-
}
|
149
|
-
let jwt = null;
|
150
|
-
if (headers.has("authorization")) {
|
151
|
-
const authHeader = headers.get("authorization");
|
152
|
-
if (authHeader) {
|
153
|
-
const [type, token] = authHeader.split(" ");
|
154
|
-
if (type?.toLowerCase() === "bearer" && !!token) {
|
155
|
-
jwt = token;
|
156
|
-
}
|
157
|
-
}
|
158
|
-
}
|
159
|
-
return {
|
160
|
-
jwt,
|
161
|
-
hashedJWT: jwt ? await hashSecretKey(jwt) : null,
|
162
|
-
secretKey,
|
163
|
-
clientId,
|
164
|
-
origin,
|
165
|
-
bundleId,
|
166
|
-
secretKeyHash,
|
167
|
-
targetAddress: authInput.targetAddress
|
168
|
-
};
|
169
|
-
}
|
170
|
-
async function hashSecretKey(secretKey) {
|
171
|
-
return bufferToHex(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(secretKey)));
|
172
|
-
}
|
173
|
-
function deriveClientIdFromSecretKeyHash(secretKeyHash) {
|
174
|
-
return secretKeyHash.slice(0, 32);
|
175
|
-
}
|
176
|
-
function bufferToHex(buffer) {
|
177
|
-
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join("");
|
178
|
-
}
|
179
|
-
async function logHttpRequest(_ref) {
|
180
|
-
let {
|
181
|
-
clientId,
|
182
|
-
req,
|
183
|
-
res,
|
184
|
-
isAuthed,
|
185
|
-
statusMessage,
|
186
|
-
latencyMs
|
187
|
-
} = _ref;
|
188
|
-
try {
|
189
|
-
const authorizationData = await extractAuthorizationData({
|
190
|
-
req,
|
191
|
-
clientId
|
192
|
-
});
|
193
|
-
const headers = req.headers;
|
194
|
-
console.log(JSON.stringify({
|
195
|
-
method: req.method,
|
196
|
-
pathname: req.url,
|
197
|
-
hasSecretKey: !!authorizationData.secretKey,
|
198
|
-
hasClientId: !!authorizationData.clientId,
|
199
|
-
hasJwt: !!authorizationData.jwt,
|
200
|
-
clientId: authorizationData.clientId,
|
201
|
-
isAuthed,
|
202
|
-
status: res.status,
|
203
|
-
sdkName: headers.get("x-sdk-name") ?? undefined,
|
204
|
-
sdkVersion: headers.get("x-sdk-version") ?? undefined,
|
205
|
-
platform: headers.get("x-sdk-platform") ?? undefined,
|
206
|
-
os: headers.get("x-sdk-os") ?? undefined,
|
207
|
-
latencyMs
|
208
|
-
}));
|
209
|
-
if (statusMessage) {
|
210
|
-
console.log(`statusMessage=${statusMessage}`);
|
211
|
-
}
|
212
|
-
} catch (err) {}
|
213
|
-
}
|
214
|
-
|
215
|
-
exports.rateLimit = index.rateLimit;
|
216
|
-
exports.usageLimit = index.usageLimit;
|
217
|
-
exports.SERVICES = client.SERVICES;
|
218
|
-
exports.SERVICE_DEFINITIONS = client.SERVICE_DEFINITIONS;
|
219
|
-
exports.SERVICE_NAMES = client.SERVICE_NAMES;
|
220
|
-
exports.getServiceByName = client.getServiceByName;
|
221
|
-
exports.authorizeWorker = authorizeWorker;
|
222
|
-
exports.deriveClientIdFromSecretKeyHash = deriveClientIdFromSecretKeyHash;
|
223
|
-
exports.extractAuthorizationData = extractAuthorizationData;
|
224
|
-
exports.hashSecretKey = hashSecretKey;
|
225
|
-
exports.logHttpRequest = logHttpRequest;
|
226
|
-
exports.publishUsageEvents = publishUsageEvents;
|
@@ -1,212 +0,0 @@
|
|
1
|
-
import { u as usageEventSchema, a as authorize } from '../../dist/index-5dc16842.esm.js';
|
2
|
-
export { r as rateLimit, b as usageLimit } from '../../dist/index-5dc16842.esm.js';
|
3
|
-
import { AwsClient } from 'aws4fetch';
|
4
|
-
export { d as SERVICES, S as SERVICE_DEFINITIONS, c as SERVICE_NAMES, g as getServiceByName } from '../../dist/client-8440b8fb.esm.js';
|
5
|
-
import 'zod';
|
6
|
-
|
7
|
-
// Initialize a singleton for AWS usage.
|
8
|
-
let _aws;
|
9
|
-
function getAws(options) {
|
10
|
-
if (!_aws) {
|
11
|
-
_aws = new AwsClient(options);
|
12
|
-
}
|
13
|
-
return _aws;
|
14
|
-
}
|
15
|
-
|
16
|
-
/**
|
17
|
-
* Publish usage events. Provide the relevant fields for your application.
|
18
|
-
*
|
19
|
-
* Usage in Cloudflare Workers:
|
20
|
-
* ctx.waitUntil(
|
21
|
-
* publishUsageEvents(
|
22
|
-
* [event1, event2],
|
23
|
-
* { queueUrl, accessKeyId, secretAccessKey },
|
24
|
-
* )
|
25
|
-
* )
|
26
|
-
*
|
27
|
-
* @param usageEvents
|
28
|
-
* @param config
|
29
|
-
*/
|
30
|
-
async function publishUsageEvents(usageEvents, config) {
|
31
|
-
const {
|
32
|
-
queueUrl,
|
33
|
-
accessKeyId,
|
34
|
-
secretAccessKey,
|
35
|
-
region = "us-west-2"
|
36
|
-
} = config;
|
37
|
-
const entries = usageEvents.map(event => {
|
38
|
-
// Enforce schema of usage event.
|
39
|
-
const parsed = usageEventSchema.parse(event);
|
40
|
-
return {
|
41
|
-
Id: crypto.randomUUID(),
|
42
|
-
MessageBody: JSON.stringify(parsed)
|
43
|
-
};
|
44
|
-
});
|
45
|
-
const aws = getAws({
|
46
|
-
accessKeyId,
|
47
|
-
secretAccessKey,
|
48
|
-
region
|
49
|
-
});
|
50
|
-
await aws.fetch(`https://sqs.${region}.amazonaws.com`, {
|
51
|
-
headers: {
|
52
|
-
"X-Amz-Target": "AmazonSQS.SendMessageBatch",
|
53
|
-
"X-Amz-Date": new Date().toISOString(),
|
54
|
-
"Content-Type": "application/x-amz-json-1.0"
|
55
|
-
},
|
56
|
-
body: JSON.stringify({
|
57
|
-
QueueUrl: queueUrl,
|
58
|
-
Entries: entries
|
59
|
-
})
|
60
|
-
});
|
61
|
-
}
|
62
|
-
|
63
|
-
const DEFAULT_CACHE_TTL_SECONDS = 60;
|
64
|
-
async function authorizeWorker(authInput, serviceConfig) {
|
65
|
-
let authData;
|
66
|
-
try {
|
67
|
-
authData = await extractAuthorizationData(authInput);
|
68
|
-
} catch (e) {
|
69
|
-
if (e instanceof Error && e.message === "KEY_CONFLICT") {
|
70
|
-
return {
|
71
|
-
authorized: false,
|
72
|
-
status: 400,
|
73
|
-
errorMessage: "Please pass either a client id or a secret key.",
|
74
|
-
errorCode: "KEY_CONFLICT"
|
75
|
-
};
|
76
|
-
}
|
77
|
-
return {
|
78
|
-
authorized: false,
|
79
|
-
status: 500,
|
80
|
-
errorMessage: "Internal Server Error",
|
81
|
-
errorCode: "INTERNAL_SERVER_ERROR"
|
82
|
-
};
|
83
|
-
}
|
84
|
-
return await authorize(authData, serviceConfig, {
|
85
|
-
get: async clientId => serviceConfig.kvStore.get(clientId),
|
86
|
-
put: (clientId, apiKeyMeta) => serviceConfig.ctx.waitUntil(serviceConfig.kvStore.put(clientId, JSON.stringify({
|
87
|
-
updatedAt: Date.now(),
|
88
|
-
apiKeyMeta
|
89
|
-
}), {
|
90
|
-
expirationTtl: serviceConfig.cacheTtlSeconds && serviceConfig.cacheTtlSeconds >= DEFAULT_CACHE_TTL_SECONDS ? serviceConfig.cacheTtlSeconds : DEFAULT_CACHE_TTL_SECONDS
|
91
|
-
})),
|
92
|
-
cacheTtlSeconds: serviceConfig.cacheTtlSeconds ?? DEFAULT_CACHE_TTL_SECONDS
|
93
|
-
});
|
94
|
-
}
|
95
|
-
async function extractAuthorizationData(authInput) {
|
96
|
-
const requestUrl = new URL(authInput.req.url);
|
97
|
-
const headers = authInput.req.headers;
|
98
|
-
const secretKey = headers.get("x-secret-key");
|
99
|
-
|
100
|
-
// prefer clientId that is explicitly passed in
|
101
|
-
let clientId = authInput.clientId ?? null;
|
102
|
-
if (!clientId) {
|
103
|
-
// next preference is clientId from header
|
104
|
-
clientId = headers.get("x-client-id");
|
105
|
-
}
|
106
|
-
|
107
|
-
// next preference is search param
|
108
|
-
if (!clientId) {
|
109
|
-
clientId = requestUrl.searchParams.get("clientId");
|
110
|
-
}
|
111
|
-
// bundle id from header is first preference
|
112
|
-
let bundleId = headers.get("x-bundle-id");
|
113
|
-
|
114
|
-
// next preference is search param
|
115
|
-
if (!bundleId) {
|
116
|
-
bundleId = requestUrl.searchParams.get("bundleId");
|
117
|
-
}
|
118
|
-
let origin = headers.get("origin");
|
119
|
-
// if origin header is not available we'll fall back to referrer;
|
120
|
-
if (!origin) {
|
121
|
-
origin = headers.get("referer");
|
122
|
-
}
|
123
|
-
// if we have an origin at this point, normalize it
|
124
|
-
if (origin) {
|
125
|
-
try {
|
126
|
-
origin = new URL(origin).host;
|
127
|
-
} catch (e) {
|
128
|
-
console.warn("failed to parse origin", origin, e);
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
// handle if we a secret key is passed in the headers
|
133
|
-
let secretKeyHash = null;
|
134
|
-
if (secretKey) {
|
135
|
-
// hash the secret key
|
136
|
-
secretKeyHash = await hashSecretKey(secretKey);
|
137
|
-
// derive the client id from the secret key hash
|
138
|
-
const derivedClientId = deriveClientIdFromSecretKeyHash(secretKeyHash);
|
139
|
-
// if we already have a client id passed in we need to make sure they match
|
140
|
-
if (clientId && clientId !== derivedClientId) {
|
141
|
-
throw new Error("KEY_CONFLICT");
|
142
|
-
}
|
143
|
-
// otherwise set the client id to the derived client id (client id based off of secret key)
|
144
|
-
clientId = derivedClientId;
|
145
|
-
}
|
146
|
-
let jwt = null;
|
147
|
-
if (headers.has("authorization")) {
|
148
|
-
const authHeader = headers.get("authorization");
|
149
|
-
if (authHeader) {
|
150
|
-
const [type, token] = authHeader.split(" ");
|
151
|
-
if (type?.toLowerCase() === "bearer" && !!token) {
|
152
|
-
jwt = token;
|
153
|
-
}
|
154
|
-
}
|
155
|
-
}
|
156
|
-
return {
|
157
|
-
jwt,
|
158
|
-
hashedJWT: jwt ? await hashSecretKey(jwt) : null,
|
159
|
-
secretKey,
|
160
|
-
clientId,
|
161
|
-
origin,
|
162
|
-
bundleId,
|
163
|
-
secretKeyHash,
|
164
|
-
targetAddress: authInput.targetAddress
|
165
|
-
};
|
166
|
-
}
|
167
|
-
async function hashSecretKey(secretKey) {
|
168
|
-
return bufferToHex(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(secretKey)));
|
169
|
-
}
|
170
|
-
function deriveClientIdFromSecretKeyHash(secretKeyHash) {
|
171
|
-
return secretKeyHash.slice(0, 32);
|
172
|
-
}
|
173
|
-
function bufferToHex(buffer) {
|
174
|
-
return [...new Uint8Array(buffer)].map(x => x.toString(16).padStart(2, "0")).join("");
|
175
|
-
}
|
176
|
-
async function logHttpRequest(_ref) {
|
177
|
-
let {
|
178
|
-
clientId,
|
179
|
-
req,
|
180
|
-
res,
|
181
|
-
isAuthed,
|
182
|
-
statusMessage,
|
183
|
-
latencyMs
|
184
|
-
} = _ref;
|
185
|
-
try {
|
186
|
-
const authorizationData = await extractAuthorizationData({
|
187
|
-
req,
|
188
|
-
clientId
|
189
|
-
});
|
190
|
-
const headers = req.headers;
|
191
|
-
console.log(JSON.stringify({
|
192
|
-
method: req.method,
|
193
|
-
pathname: req.url,
|
194
|
-
hasSecretKey: !!authorizationData.secretKey,
|
195
|
-
hasClientId: !!authorizationData.clientId,
|
196
|
-
hasJwt: !!authorizationData.jwt,
|
197
|
-
clientId: authorizationData.clientId,
|
198
|
-
isAuthed,
|
199
|
-
status: res.status,
|
200
|
-
sdkName: headers.get("x-sdk-name") ?? undefined,
|
201
|
-
sdkVersion: headers.get("x-sdk-version") ?? undefined,
|
202
|
-
platform: headers.get("x-sdk-platform") ?? undefined,
|
203
|
-
os: headers.get("x-sdk-os") ?? undefined,
|
204
|
-
latencyMs
|
205
|
-
}));
|
206
|
-
if (statusMessage) {
|
207
|
-
console.log(`statusMessage=${statusMessage}`);
|
208
|
-
}
|
209
|
-
} catch (err) {}
|
210
|
-
}
|
211
|
-
|
212
|
-
export { authorizeWorker, deriveClientIdFromSecretKeyHash, extractAuthorizationData, hashSecretKey, logHttpRequest, publishUsageEvents };
|
package/cf-worker/package.json
DELETED
@@ -1,195 +0,0 @@
|
|
1
|
-
const SERVICE_DEFINITIONS = {
|
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: "Account Abstraction",
|
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
|
-
embeddedWallets: {
|
38
|
-
name: "embeddedWallets",
|
39
|
-
title: "In-App Wallets",
|
40
|
-
description: "E-mail and social login wallets for easy web3 onboarding",
|
41
|
-
// all actions allowed
|
42
|
-
actions: []
|
43
|
-
},
|
44
|
-
pay: {
|
45
|
-
name: "pay",
|
46
|
-
title: "Pay",
|
47
|
-
description: "Pay for a blockchain transaction with any currency",
|
48
|
-
// all actions allowed
|
49
|
-
actions: []
|
50
|
-
},
|
51
|
-
chainsaw: {
|
52
|
-
name: "chainsaw",
|
53
|
-
title: "Chainsaw",
|
54
|
-
description: "Indexed data for any EVM chain",
|
55
|
-
// all actions allowed
|
56
|
-
actions: []
|
57
|
-
}
|
58
|
-
};
|
59
|
-
const SERVICE_NAMES = Object.keys(SERVICE_DEFINITIONS);
|
60
|
-
const SERVICES = Object.values(SERVICE_DEFINITIONS);
|
61
|
-
function getServiceByName(name) {
|
62
|
-
return SERVICE_DEFINITIONS[name];
|
63
|
-
}
|
64
|
-
|
65
|
-
function authorizeClient(authOptions, apiKeyMeta) {
|
66
|
-
const {
|
67
|
-
origin,
|
68
|
-
bundleId,
|
69
|
-
secretKeyHash: providedSecretHash
|
70
|
-
} = authOptions;
|
71
|
-
const {
|
72
|
-
domains,
|
73
|
-
bundleIds,
|
74
|
-
secretHash
|
75
|
-
} = apiKeyMeta;
|
76
|
-
const authResult = {
|
77
|
-
authorized: true,
|
78
|
-
apiKeyMeta,
|
79
|
-
accountMeta: {
|
80
|
-
id: apiKeyMeta.accountId,
|
81
|
-
// TODO update this later
|
82
|
-
name: "",
|
83
|
-
creatorWalletAddress: apiKeyMeta.creatorWalletAddress,
|
84
|
-
limits: apiKeyMeta.limits,
|
85
|
-
rateLimits: apiKeyMeta.rateLimits,
|
86
|
-
usage: apiKeyMeta.usage
|
87
|
-
}
|
88
|
-
};
|
89
|
-
|
90
|
-
// check for public restrictions
|
91
|
-
if (domains.includes("*")) {
|
92
|
-
return authResult;
|
93
|
-
}
|
94
|
-
|
95
|
-
// check for secretHash
|
96
|
-
if (providedSecretHash) {
|
97
|
-
if (secretHash !== providedSecretHash) {
|
98
|
-
return {
|
99
|
-
authorized: false,
|
100
|
-
errorMessage: "Incorrect key provided. You can view your active API keys at https://thirdweb.com/dashboard/settings",
|
101
|
-
errorCode: "SECRET_INVALID",
|
102
|
-
status: 401
|
103
|
-
};
|
104
|
-
}
|
105
|
-
return authResult;
|
106
|
-
}
|
107
|
-
|
108
|
-
// validate domains
|
109
|
-
if (origin) {
|
110
|
-
if (authorizeDomain({
|
111
|
-
domains,
|
112
|
-
origin
|
113
|
-
})) {
|
114
|
-
return authResult;
|
115
|
-
}
|
116
|
-
return {
|
117
|
-
authorized: false,
|
118
|
-
errorMessage: `Invalid request: Unauthorized domain: ${origin}. You can view the restrictions on this API key at https://thirdweb.com/create-api-key`,
|
119
|
-
errorCode: "ORIGIN_UNAUTHORIZED",
|
120
|
-
status: 401
|
121
|
-
};
|
122
|
-
}
|
123
|
-
|
124
|
-
// validate bundleId
|
125
|
-
if (bundleId) {
|
126
|
-
if (authorizeBundleId({
|
127
|
-
bundleIds,
|
128
|
-
bundleId
|
129
|
-
})) {
|
130
|
-
return authResult;
|
131
|
-
}
|
132
|
-
return {
|
133
|
-
authorized: false,
|
134
|
-
errorMessage: `Invalid request: Unauthorized Bundle ID: ${bundleId}. You can view the restrictions on this API key at https://thirdweb.com/create-api-key`,
|
135
|
-
errorCode: "BUNDLE_UNAUTHORIZED",
|
136
|
-
status: 401
|
137
|
-
};
|
138
|
-
}
|
139
|
-
return {
|
140
|
-
authorized: false,
|
141
|
-
errorMessage: "The keys are invalid. Please check the secret-key/clientId and try again.",
|
142
|
-
errorCode: "UNAUTHORIZED",
|
143
|
-
status: 401
|
144
|
-
};
|
145
|
-
}
|
146
|
-
|
147
|
-
// Exposed for use in validating ecosystem partners settings
|
148
|
-
function authorizeDomain(_ref) {
|
149
|
-
let {
|
150
|
-
domains,
|
151
|
-
origin
|
152
|
-
} = _ref;
|
153
|
-
// find matching domain, or if all domains allowed
|
154
|
-
// embedded-wallet.thirdweb(-dev).com is automatically allowed
|
155
|
-
// because the rpc is passed from user's domain to embedded-wallet.thirdweb.com iframe for use.
|
156
|
-
// Note this doesn't allow embedded-wallets from being used if it's disabled. The service check that runs after enforces that.
|
157
|
-
return !![...domains, "embedded-wallet.thirdweb.com", "embedded-wallet.thirdweb-dev.com"].find(d => {
|
158
|
-
// if any domain is allowed, we'll return true
|
159
|
-
if (d === "*") {
|
160
|
-
return true;
|
161
|
-
}
|
162
|
-
|
163
|
-
// special rule for `localhost`
|
164
|
-
// if the domain is localhost, we'll allow any origin that starts with localhost
|
165
|
-
if (d === "localhost" && origin.startsWith("localhost")) {
|
166
|
-
return true;
|
167
|
-
}
|
168
|
-
|
169
|
-
// If the allowedDomain has a wildcard,
|
170
|
-
// we'll check that the ending of our domain matches the wildcard
|
171
|
-
if (d.startsWith("*.")) {
|
172
|
-
// get rid of the * and check if it ends with the `.<domain>.<tld>`
|
173
|
-
const domainRoot = d.slice(1);
|
174
|
-
return origin.endsWith(domainRoot);
|
175
|
-
}
|
176
|
-
|
177
|
-
// If there's no wildcard, we'll check for an exact match
|
178
|
-
return d === origin;
|
179
|
-
});
|
180
|
-
}
|
181
|
-
function authorizeBundleId(_ref2) {
|
182
|
-
let {
|
183
|
-
bundleIds,
|
184
|
-
bundleId
|
185
|
-
} = _ref2;
|
186
|
-
// find matching bundle id, or if all bundles allowed
|
187
|
-
return !!bundleIds.find(b => {
|
188
|
-
if (b === "*") {
|
189
|
-
return true;
|
190
|
-
}
|
191
|
-
return b === bundleId;
|
192
|
-
});
|
193
|
-
}
|
194
|
-
|
195
|
-
export { SERVICE_DEFINITIONS as S, authorizeBundleId as a, authorizeDomain as b, SERVICE_NAMES as c, SERVICES as d, authorizeClient as e, getServiceByName as g };
|