From 1dfd4a5a157f019b385a9c930187e48e09c5fcc2 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 30 Oct 2024 14:20:44 +0000 Subject: [PATCH] Add site key to headers (#1485) Co-authored-by: prosoponator[bot] --- packages/api/src/api/HttpClientBase.ts | 2 +- packages/api/src/api/ProviderApi.ts | 73 ++++++++++++++++--- packages/provider/src/api/block.ts | 4 +- .../provider/src/tasks/powCaptcha/powTasks.ts | 4 +- packages/server/src/server.ts | 7 +- packages/types/src/api/api.ts | 8 +- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/packages/api/src/api/HttpClientBase.ts b/packages/api/src/api/HttpClientBase.ts index 57031dc52c..49dafcccc0 100644 --- a/packages/api/src/api/HttpClientBase.ts +++ b/packages/api/src/api/HttpClientBase.ts @@ -50,8 +50,8 @@ export class HttpClientBase { const response = await fetch(this.baseURL + input, { method: "POST", body: JSON.stringify(body), - headers, ...init, + headers, }); if ( !response.ok && diff --git a/packages/api/src/api/ProviderApi.ts b/packages/api/src/api/ProviderApi.ts index 9fd6800f03..196081a6ea 100644 --- a/packages/api/src/api/ProviderApi.ts +++ b/packages/api/src/api/ProviderApi.ts @@ -61,7 +61,12 @@ export default class ProviderApi const url: TGetImageCaptchaChallengePathAndParams = `${ApiPaths.GetImageCaptchaChallenge}/${ provider.datasetId }/${userAccount}/${dappAccount}`; - return this.fetch(url); + return this.fetch(url, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": userAccount, + }, + }); } public submitCaptchaSolution( @@ -87,12 +92,18 @@ export default class ProviderApi }, }, }; - return this.post(ApiPaths.SubmitImageCaptchaSolution, body); + return this.post(ApiPaths.SubmitImageCaptchaSolution, body, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": userAccount, + }, + }); } public verifyDappUser( token: ProcaptchaToken, signature: string, + userAccount: string, maxVerifiedTime?: number, ): Promise { const payload: VerifySolutionBodyTypeInput = { @@ -103,7 +114,12 @@ export default class ProviderApi payload[ApiParams.maxVerifiedTime] = maxVerifiedTime; } - return this.post(ApiPaths.VerifyImageCaptchaSolutionDapp, payload); + return this.post(ApiPaths.VerifyImageCaptchaSolutionDapp, payload, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": userAccount, + }, + }); } public getPowCaptchaChallenge( @@ -116,7 +132,12 @@ export default class ProviderApi [ApiParams.dapp]: dapp.toString(), ...(sessionId && { [ApiParams.sessionId]: sessionId }), }; - return this.post(ApiPaths.GetPowCaptchaChallenge, body); + return this.post(ApiPaths.GetPowCaptchaChallenge, body, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": user, + }, + }); } public submitPowCaptchaSolution( @@ -143,7 +164,12 @@ export default class ProviderApi }, }, }); - return this.post(ApiPaths.SubmitPowCaptchaSolution, body); + return this.post(ApiPaths.SubmitPowCaptchaSolution, body, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": userAccount, + }, + }); } public getFrictionlessCaptcha( @@ -156,22 +182,43 @@ export default class ProviderApi [ApiParams.dapp]: dapp, [ApiParams.user]: user, }; - return this.post(ApiPaths.GetFrictionlessCaptchaChallenge, body); + return this.post(ApiPaths.GetFrictionlessCaptchaChallenge, body, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": user, + }, + }); } public submitUserEvents( events: StoredEvents, string: string, ): Promise { - return this.post(ApiPaths.SubmitUserEvents, { events, string }); + return this.post( + ApiPaths.SubmitUserEvents, + { events, string }, + { + headers: { + "Prosopo-Site-Key": this.account, + }, + }, + ); } public getProviderStatus(): Promise { - return this.fetch(ApiPaths.GetProviderStatus); + return this.fetch(ApiPaths.GetProviderStatus, { + headers: { + "Prosopo-Site-Key": this.account, + }, + }); } public getProviderDetails(): Promise { - return this.fetch(ApiPaths.GetProviderDetails); + return this.fetch(ApiPaths.GetProviderDetails, { + headers: { + "Prosopo-Site-Key": this.account, + }, + }); } public updateProviderClients(): Promise { @@ -182,12 +229,18 @@ export default class ProviderApi token: string, signatureHex: string, recencyLimit: number, + user: string, ): Promise { const body: ServerPowCaptchaVerifyRequestBodyType = { [ApiParams.token]: token, [ApiParams.dappSignature]: signatureHex, [ApiParams.verifiedTimeout]: recencyLimit, }; - return this.post(ApiPaths.VerifyPowCaptchaSolution, body); + return this.post(ApiPaths.VerifyPowCaptchaSolution, body, { + headers: { + "Prosopo-Site-Key": this.account, + "Prosopo-User": user, + }, + }); } } diff --git a/packages/provider/src/api/block.ts b/packages/provider/src/api/block.ts index ad54d563d0..b586e6b252 100644 --- a/packages/provider/src/api/block.ts +++ b/packages/provider/src/api/block.ts @@ -39,8 +39,8 @@ export const blockMiddleware = (env: ProviderEnvironment) => { await env.isReady(); const ipAddress = getIPAddress(req.ip || ""); - const userAccount = req.body.user; - const dappAccount = req.body.dapp; + const userAccount = req.headers["Prosopo-User"] || req.body.user; + const dappAccount = req.headers["Prosopo-Site-Key"] || req.body.dapp; const rule = await env.getDb().getIPBlockRuleRecord(ipAddress.bigInt()); if (rule && BigInt(rule.ip) === ipAddress.bigInt()) { // block by IP address globally diff --git a/packages/provider/src/tasks/powCaptcha/powTasks.ts b/packages/provider/src/tasks/powCaptcha/powTasks.ts index 77d1b22426..ad0e3618ed 100644 --- a/packages/provider/src/tasks/powCaptcha/powTasks.ts +++ b/packages/provider/src/tasks/powCaptcha/powTasks.ts @@ -131,8 +131,8 @@ export class PowCaptchaManager { status: CaptchaStatus.disapproved, reason: "CAPTCHA.INVALID_TIMESTAMP", }, - false, - true, + false, //serverchecked + true, // usersubmitted userTimestampSignature, ); return false; diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index a20ad5b1c2..dd0fc0b26a 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -65,6 +65,7 @@ export class ProsopoServer { * @param timeouts * @param providerUrl * @param timestamp + * @param user * @param challenge */ public async verifyProvider( @@ -72,6 +73,7 @@ export class ProsopoServer { timeouts: CaptchaTimeoutOutput, providerUrl: string, timestamp: number, + user: string, challenge?: string, ): Promise { this.logger.info("Verifying with provider."); @@ -98,6 +100,7 @@ export class ProsopoServer { token, signatureHex, timeouts.pow.cachedTimeout, + user, ); } const imageTimeout = this.config.timeouts.image.cachedTimeout; @@ -112,6 +115,7 @@ export class ProsopoServer { return await providerApi.verifyDappUser( token, signatureHex, + user, timeouts.image.cachedTimeout, ); } @@ -127,7 +131,7 @@ export class ProsopoServer { try { const payload = decodeProcaptchaOutput(token); - const { providerUrl, challenge, timestamp } = + const { providerUrl, challenge, timestamp, user } = ProcaptchaOutputSchema.parse(payload); if (providerUrl) { @@ -136,6 +140,7 @@ export class ProsopoServer { this.config.timeouts, providerUrl, Number(timestamp), + user, challenge, ); } diff --git a/packages/types/src/api/api.ts b/packages/types/src/api/api.ts index 95ae1518e8..7e5a2ddb74 100644 --- a/packages/types/src/api/api.ts +++ b/packages/types/src/api/api.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. import type { CaptchaSolution } from "../datasets/index.js"; -import type { StoredEvents } from "../procaptcha/index.js"; +import type { ProcaptchaToken, StoredEvents } from "../procaptcha/index.js"; import type { CaptchaResponseBody, CaptchaSolutionResponse, @@ -39,11 +39,9 @@ export interface ProviderApiInterface { userRequestHashSignature: string, ): Promise; verifyDappUser( - dapp: string, + token: ProcaptchaToken, + signature: string, userAccount: string, - blockNumber: number, - dappUserSignature: string, - commitmentId?: string, maxVerifiedTime?: number, ): Promise; getPowCaptchaChallenge(