Skip to content

Commit df46c0a

Browse files
committed
feat: allow PublicWeb2 source on testnets
1 parent 6a67a2e commit df46c0a

File tree

4 files changed

+74
-54
lines changed

4 files changed

+74
-54
lines changed
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
import { AuthType, HTTP_METHOD, Web2JsonSource } from '../interfaces/web2-json';
22

3+
/**
4+
* Special source allowing access to any public Web2 JSON endpoint without restrictions.
5+
* Only available on testnets.
6+
*/
7+
export const PUBLIC_WEB2: Web2JsonSource = {
8+
sourceId: 'PublicWeb2',
9+
endpoints: [],
10+
};
11+
312
/** Allowed Web2Json sources definitions for testnet deployments. */
413
export const WEB2_JSON_TEST_SOURCES: Web2JsonSource[] = [
14+
PUBLIC_WEB2,
515
{
616
sourceId: 'testIgnite',
717
endpoints: [
@@ -17,14 +27,4 @@ export const WEB2_JSON_TEST_SOURCES: Web2JsonSource[] = [
1727
},
1828
],
1929
},
20-
{
21-
sourceId: 'testAPIs',
22-
endpoints: [
23-
{
24-
host: 'jsonplaceholder.typicode.com',
25-
paths: ['/todos'],
26-
methods: [HTTP_METHOD.GET],
27-
},
28-
],
29-
},
3030
];

src/services/web2-json-verifier.service.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
Web2Json_Response,
1313
} from '../dtos/attestation-types/Web2Json.dto';
1414
import {
15+
decodeAttestationName,
1516
encodeAttestationName,
1617
serializeBigInts,
1718
} from '../external-libs/utils';
@@ -50,21 +51,22 @@ export class Web2JsonVerifierService extends BaseVerifierService<
5051
}
5152

5253
protected checkSupportedType(request: Web2Json_Request) {
53-
const supportedAttestation = encodeAttestationName(
54-
Web2JsonVerifierService.attestationName,
54+
const requestType = decodeAttestationName(request.attestationType);
55+
const requestSourceId = decodeAttestationName(request.sourceId);
56+
const supportedSourceIds = this.web2JsonConfig.sources.map(
57+
(s) => s.sourceId,
5558
);
56-
const supportedSources = this.web2JsonConfig.sources.map((s) => s.sourceId);
5759

5860
if (
59-
request.attestationType !== supportedAttestation ||
60-
!supportedSources.some(
61-
(s) => request.sourceId == encodeAttestationName(s),
62-
)
61+
requestType !== Web2JsonVerifierService.attestationName ||
62+
!supportedSourceIds.some((s) => requestSourceId == s)
6363
) {
64+
const errorMsg = `Attestation type and source id combination not supported: ${requestType}/${requestSourceId}. Supported attestation type: '${Web2JsonVerifierService.attestationName}'. Supported source ids: [${supportedSourceIds.join(', ')}].`;
65+
this.logger.debug(errorMsg);
6466
throw new HttpException(
6567
{
6668
status: HttpStatus.BAD_REQUEST,
67-
error: `Attestation type and source id combination not supported: (${request.attestationType}, ${request.sourceId}). Supported attestation: '${Web2JsonVerifierService.attestationName}' (${supportedAttestation}). Supported source ids: [${supportedSources.join(', ')}] ([${supportedSources.map(encodeAttestationName).join(', ')}]).`,
69+
error: errorMsg,
6870
},
6971
HttpStatus.BAD_REQUEST,
7072
);

src/verification/web-2-json/validate-request.ts

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {
22
CheckedUrl,
33
parseUrl,
4-
validatePath,
54
validateHttpMethod,
5+
validatePath,
66
validateUrl,
77
} from './validate-url';
88
import { Web2Json_Request } from '../../dtos/attestation-types/Web2Json.dto';
@@ -18,6 +18,7 @@ import { validateJqFilter } from './validate-jq';
1818
import { ParamType } from 'ethers';
1919
import { parseAndValidateAbiType } from './validate-abi';
2020
import { Web2JsonValidationError } from './utils';
21+
import { PUBLIC_WEB2 } from '../../config/web2/web2-json-test-sources';
2122

2223
export interface ParsedRequestBody {
2324
validSourceUrl: CheckedUrl;
@@ -47,18 +48,6 @@ export async function parseAndValidateRequest(
4748
`Invalid source URL: ${(e as Error).message}`,
4849
);
4950
}
50-
const endpoint = source.endpoints.find((e) => e.host === parsedUrl.hostname);
51-
if (!endpoint) {
52-
throw new Web2JsonValidationError(
53-
AttestationResponseStatus.INVALID_SOURCE_URL,
54-
'Source URL host not allowed',
55-
);
56-
}
57-
// validate endpoint path
58-
validatePath(parsedUrl, endpoint);
59-
// validate HTTP method
60-
const sourceMethod = requestBody.httpMethod;
61-
validateHttpMethod(sourceMethod, endpoint.methods);
6251
// validate headers
6352
const sourceHeaders =
6453
parseJsonWithDepthAndKeysValidation(
@@ -80,37 +69,58 @@ export async function parseAndValidateRequest(
8069
AttestationResponseStatus.INVALID_QUERY_PARAMS,
8170
) ?? {};
8271

83-
// validate jq filter length and content
84-
const jqFilter = requestBody.postProcessJq;
85-
validateJqFilter(requestBody.postProcessJq, securityParams.maxJqFilterLength);
86-
// validate ABI signature
87-
const abiType = parseAndValidateAbiType(
88-
requestBody.abiSignature,
89-
securityParams.maxAbiSignatureLength,
90-
);
72+
const sourceMethod = requestBody.httpMethod;
9173

92-
// Inject authentication token from endpoint.auth if configured
93-
if (endpoint.auth) {
94-
const token = process.env[endpoint.auth.env];
95-
if (!token) {
96-
throw Error(
97-
`Missing API key in environment variable ${endpoint.auth.env} for host ${endpoint.host}`,
74+
if (source === PUBLIC_WEB2) {
75+
// validate HTTP method
76+
validateHttpMethod(sourceMethod, [HTTP_METHOD.GET, HTTP_METHOD.POST]);
77+
} else {
78+
const endpoint = source.endpoints.find(
79+
(e) => e.host === parsedUrl.hostname,
80+
);
81+
if (!endpoint) {
82+
throw new Web2JsonValidationError(
83+
AttestationResponseStatus.INVALID_SOURCE_URL,
84+
'Source URL host not allowed',
9885
);
9986
}
10087

101-
if (endpoint.auth.type === AuthType.BEARER) {
102-
sourceHeaders['Authorization'] = `Bearer ${token}`;
103-
} else if (endpoint.auth.type === AuthType.APIKEY) {
104-
if (endpoint.auth.header) {
105-
sourceHeaders[endpoint.auth.header] = token;
88+
// validate endpoint path
89+
validatePath(parsedUrl, endpoint);
90+
// validate HTTP method
91+
validateHttpMethod(sourceMethod, endpoint.methods);
92+
// Inject authentication token from endpoint.auth if configured
93+
if (endpoint.auth) {
94+
const token = process.env[endpoint.auth.env];
95+
if (!token) {
96+
throw Error(
97+
`Missing API key in environment variable ${endpoint.auth.env} for host ${endpoint.host}`,
98+
);
99+
}
100+
101+
if (endpoint.auth.type === AuthType.BEARER) {
102+
sourceHeaders['Authorization'] = `Bearer ${token}`;
103+
} else if (endpoint.auth.type === AuthType.APIKEY) {
104+
if (endpoint.auth.header) {
105+
sourceHeaders[endpoint.auth.header] = token;
106+
} else {
107+
sourceQueryParams[endpoint.auth.query] = token;
108+
}
106109
} else {
107-
sourceQueryParams[endpoint.auth.query] = token;
110+
throw new Error(`Unsupported auth type for host ${endpoint.host}`);
108111
}
109-
} else {
110-
throw new Error(`Unsupported auth type for host ${endpoint.host}`);
111112
}
112113
}
113114

115+
// validate jq filter length and content
116+
const jqFilter = requestBody.postProcessJq;
117+
validateJqFilter(requestBody.postProcessJq, securityParams.maxJqFilterLength);
118+
// validate ABI signature
119+
const abiType = parseAndValidateAbiType(
120+
requestBody.abiSignature,
121+
securityParams.maxAbiSignatureLength,
122+
);
123+
114124
// validate body
115125
const sourceBody = parseJsonWithDepthAndKeysValidation(
116126
requestBody.body,

test/unit/web2/verify-sources.unit.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,17 @@ describe('Web2Json source validation', () => {
3838
});
3939
});
4040
describe('host and path validation', () => {
41-
const allSources = WEB2_JSON_SOURCES.concat(WEB2_JSON_TEST_SOURCES);
41+
it('endpoints should be defined for mainnet sources', () => {
42+
for (const source of WEB2_JSON_SOURCES) {
43+
expect(
44+
source.endpoints.length > 0,
45+
`No endpoints defined for sourceId=${source.sourceId}`,
46+
).to.be.true;
47+
}
48+
});
4249

4350
it('all endpoint host+path combinations should form valid URLs', () => {
51+
const allSources = WEB2_JSON_SOURCES.concat(WEB2_JSON_TEST_SOURCES);
4452
for (const source of allSources) {
4553
for (const endpoint of source.endpoints) {
4654
const host = endpoint.host;

0 commit comments

Comments
 (0)