@friendlycaptcha/server-sdk 0.1.2 → 0.2.0
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/CHANGELOG.md +6 -0
- package/README.md +1 -1
- package/dist/api/types.d.ts +13 -1
- package/dist/api/typesRiskIntelligence.d.ts +778 -0
- package/dist/api/typesRiskIntelligence.js +25 -0
- package/dist/api/typesRiskIntelligence.js.map +1 -0
- package/dist/client/client.d.ts +15 -0
- package/dist/client/client.js +28 -8
- package/dist/client/client.js.map +1 -1
- package/dist/client/version.gen.d.ts +1 -1
- package/dist/client/version.gen.js +1 -1
- package/dist/index.d.ts +829 -0
- package/package.json +16 -2
- package/.github/workflows/ci.yml +0 -50
- package/.github/workflows/publish.yml +0 -18
- package/.prettierrc +0 -3
- package/docs/index.md +0 -12
- package/docs/server-sdk.failed_due_to_client_error_code.md +0 -15
- package/docs/server-sdk.failed_to_decode_response_error_code.md +0 -13
- package/docs/server-sdk.failed_to_encode_error_code.md +0 -13
- package/docs/server-sdk.friendlycaptchaclient._constructor_.md +0 -20
- package/docs/server-sdk.friendlycaptchaclient.md +0 -26
- package/docs/server-sdk.friendlycaptchaclient.verifycaptcharesponse.md +0 -30
- package/docs/server-sdk.friendlycaptchaoptions.apikey.md +0 -13
- package/docs/server-sdk.friendlycaptchaoptions.fetch.md +0 -13
- package/docs/server-sdk.friendlycaptchaoptions.md +0 -24
- package/docs/server-sdk.friendlycaptchaoptions.sitekey.md +0 -11
- package/docs/server-sdk.friendlycaptchaoptions.siteverifyendpoint.md +0 -15
- package/docs/server-sdk.friendlycaptchaoptions.strict.md +0 -15
- package/docs/server-sdk.md +0 -41
- package/docs/server-sdk.request_failed_error_code.md +0 -13
- package/docs/server-sdk.request_failed_timeout_error_code.md +0 -13
- package/docs/server-sdk.siteverifyerrorresponse.error.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponse.md +0 -20
- package/docs/server-sdk.siteverifyerrorresponse.success.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.detail.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.error_code.md +0 -11
- package/docs/server-sdk.siteverifyerrorresponseerrordata.md +0 -20
- package/docs/server-sdk.siteverifyresponse.md +0 -14
- package/docs/server-sdk.siteverifyresponsechallengedata.md +0 -20
- package/docs/server-sdk.siteverifyresponsechallengedata.origin.md +0 -13
- package/docs/server-sdk.siteverifyresponsechallengedata.timestamp.md +0 -13
- package/docs/server-sdk.siteverifyresponsedata.challenge.md +0 -11
- package/docs/server-sdk.siteverifyresponsedata.md +0 -19
- package/docs/server-sdk.siteverifysuccessresponse.data.md +0 -11
- package/docs/server-sdk.siteverifysuccessresponse.md +0 -20
- package/docs/server-sdk.siteverifysuccessresponse.success.md +0 -11
- package/docs/server-sdk.verifyclienterrorcode.md +0 -14
- package/docs/server-sdk.verifyresult._constructor_.md +0 -20
- package/docs/server-sdk.verifyresult.clienterrortype.md +0 -11
- package/docs/server-sdk.verifyresult.geterrorcode.md +0 -15
- package/docs/server-sdk.verifyresult.getresponse.md +0 -17
- package/docs/server-sdk.verifyresult.getresponseerror.md +0 -17
- package/docs/server-sdk.verifyresult.isclienterror.md +0 -19
- package/docs/server-sdk.verifyresult.isdecodeerror.md +0 -17
- package/docs/server-sdk.verifyresult.isencodeerror.md +0 -17
- package/docs/server-sdk.verifyresult.isrequestortimeouterror.md +0 -17
- package/docs/server-sdk.verifyresult.isstrict.md +0 -17
- package/docs/server-sdk.verifyresult.md +0 -44
- package/docs/server-sdk.verifyresult.response.md +0 -13
- package/docs/server-sdk.verifyresult.shouldaccept.md +0 -17
- package/docs/server-sdk.verifyresult.shouldreject.md +0 -17
- package/docs/server-sdk.verifyresult.status.md +0 -13
- package/docs/server-sdk.verifyresult.wasabletoverify.md +0 -17
- package/example/README.md +0 -29
- package/example/package-lock.json +0 -1404
- package/example/package.json +0 -24
- package/example/src/index.ts +0 -84
- package/example/tsconfig.json +0 -13
- package/example/views/index.ejs +0 -86
- package/src/api/errors.ts +0 -77
- package/src/api/index.ts +0 -1
- package/src/api/types.ts +0 -66
- package/src/client/client.ts +0 -157
- package/src/client/errors.ts +0 -42
- package/src/client/index.ts +0 -3
- package/src/client/result.ts +0 -152
- package/src/client/version.gen.ts +0 -3
- package/src/index.ts +0 -2
- package/test/client/client.test.ts +0 -47
- package/test/client/mock.test.ts +0 -44
- package/tsconfig.json +0 -20
package/src/client/result.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import type { SiteverifyErrorResponseErrorData, SiteverifyResponse } from "../api/index.js";
|
|
2
|
-
import {
|
|
3
|
-
FAILED_DUE_TO_CLIENT_ERROR_CODE,
|
|
4
|
-
FAILED_TO_DECODE_RESPONSE_ERROR_CODE,
|
|
5
|
-
FAILED_TO_ENCODE_ERROR_CODE,
|
|
6
|
-
REQUEST_FAILED_ERROR_CODE,
|
|
7
|
-
REQUEST_FAILED_TIMEOUT_ERROR_CODE,
|
|
8
|
-
VerifyClientErrorCode,
|
|
9
|
-
} from "./errors.js";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The result of a captcha siteverify request.
|
|
13
|
-
*
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export class VerifyResult {
|
|
17
|
-
private strict: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* The HTTP status code of the response.
|
|
20
|
-
* `-1` if there was no response.
|
|
21
|
-
*/
|
|
22
|
-
public status: number = -1;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The response from the Friendly Captcha API, or null if the request was not made at all.
|
|
26
|
-
*/
|
|
27
|
-
public response: SiteverifyResponse | null = null;
|
|
28
|
-
public clientErrorType: VerifyClientErrorCode | null = null;
|
|
29
|
-
|
|
30
|
-
constructor(strict: boolean) {
|
|
31
|
-
this.strict = strict;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @returns Whether strict mode was enabled for this verification.
|
|
36
|
-
*/
|
|
37
|
-
public isStrict(): boolean {
|
|
38
|
-
return this.strict;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @returns Whether the captcha should be accepted.
|
|
43
|
-
* Note that this does not necessarily mean it was verified.
|
|
44
|
-
*/
|
|
45
|
-
public shouldAccept(): boolean {
|
|
46
|
-
if (this.wasAbleToVerify()) {
|
|
47
|
-
// We want to reject in case we were not able to encode the captcha response sent by the client.
|
|
48
|
-
// This is because an attacker could send malformed data that can not be encoded, and if we would accept that
|
|
49
|
-
// they could circumvent the captcha.
|
|
50
|
-
if (this.isEncodeError()) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return this.response!.success === true;
|
|
55
|
-
}
|
|
56
|
-
if (this.clientErrorType !== null) {
|
|
57
|
-
if (this.strict) {
|
|
58
|
-
// In strict mode we reject on any error.
|
|
59
|
-
return false;
|
|
60
|
-
} else if (
|
|
61
|
-
this.clientErrorType === REQUEST_FAILED_ERROR_CODE ||
|
|
62
|
-
this.clientErrorType === REQUEST_FAILED_TIMEOUT_ERROR_CODE ||
|
|
63
|
-
this.clientErrorType === FAILED_DUE_TO_CLIENT_ERROR_CODE ||
|
|
64
|
-
this.clientErrorType === FAILED_TO_DECODE_RESPONSE_ERROR_CODE
|
|
65
|
-
) {
|
|
66
|
-
// In case of failures that are not the captcha response being invalid or rejected, we accept.
|
|
67
|
-
// This is because we don't want to lock out all users in case of a temporary network outage or a misconfiguration.
|
|
68
|
-
return true;
|
|
69
|
-
} else {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
throw new Error(
|
|
75
|
-
"Implementation error in @friendlycaptcha/server-sdk shouldAccept: errorCode should never be undefined if success is false. " +
|
|
76
|
-
JSON.stringify(this),
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @returns The reverse of `shouldAccept()`.
|
|
82
|
-
*/
|
|
83
|
-
public shouldReject(): boolean {
|
|
84
|
-
return !this.shouldAccept();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Was unable to encode the captcha response. This means the captcha response was invalid and should never be accepted.
|
|
89
|
-
*/
|
|
90
|
-
public isEncodeError(): boolean {
|
|
91
|
-
return this.clientErrorType === FAILED_TO_ENCODE_ERROR_CODE;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Something went wrong making the request to the Friendly Captcha API, perhaps there is a network connection issue?
|
|
96
|
-
*/
|
|
97
|
-
public isRequestOrTimeoutError(): boolean {
|
|
98
|
-
return (
|
|
99
|
-
this.clientErrorType === REQUEST_FAILED_ERROR_CODE || this.clientErrorType === REQUEST_FAILED_TIMEOUT_ERROR_CODE
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Something went wrong decoding the response from the Friendly Captcha API.
|
|
105
|
-
*/
|
|
106
|
-
public isDecodeError(): boolean {
|
|
107
|
-
return this.clientErrorType === FAILED_TO_DECODE_RESPONSE_ERROR_CODE;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Something went wrong on the client side, this generally means your configuration is wrong.
|
|
112
|
-
* Check your secrets (API key) and sitekey.
|
|
113
|
-
*
|
|
114
|
-
* See `getResponseError()` for more information.
|
|
115
|
-
*/
|
|
116
|
-
public isClientError(): boolean {
|
|
117
|
-
return this.clientErrorType === FAILED_DUE_TO_CLIENT_ERROR_CODE;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* @returns The response from the Friendly Captcha API, or null if the request was not made at all.
|
|
121
|
-
*/
|
|
122
|
-
public getResponse(): SiteverifyResponse | null {
|
|
123
|
-
return this.response;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @returns The `error` field form the response, or null if it is not present.
|
|
128
|
-
*/
|
|
129
|
-
public getResponseError(): SiteverifyErrorResponseErrorData | null {
|
|
130
|
-
if (!this.response || this.response.success) return null;
|
|
131
|
-
return this.response.error;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
public getErrorCode(): VerifyClientErrorCode | null {
|
|
135
|
-
return this.clientErrorType;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Whether the request to verify the captcha was completed. In other words: the API responded with status 200.'
|
|
140
|
-
* If this is false, you should notify yourself and use `getErrorCode()` and `getResponseError()` to see what is wrong.
|
|
141
|
-
*/
|
|
142
|
-
public wasAbleToVerify(): boolean {
|
|
143
|
-
// If we failed to encode, we actually consider `wasAbleToVerify` to be true. This is because we don't want to
|
|
144
|
-
// alert on failed encoding: an attacker could send such malformed data that it fails to encode.
|
|
145
|
-
if (this.isEncodeError()) {
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// We got a status 200, and we were able to actually make the request and decode its response.
|
|
150
|
-
return this.status === 200 && !this.isRequestOrTimeoutError() && !this.isDecodeError();
|
|
151
|
-
}
|
|
152
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import test from "ava";
|
|
2
|
-
import { FriendlyCaptchaClient } from "../../src/client/index.js";
|
|
3
|
-
|
|
4
|
-
// More of a test pre-assertion than anything else.
|
|
5
|
-
test("globalThis.fetch is present", (t) => {
|
|
6
|
-
t.assert(globalThis.fetch);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test("client without API key throws", (t) => {
|
|
10
|
-
t.throws(() => {
|
|
11
|
-
const client = new FriendlyCaptchaClient({} as any);
|
|
12
|
-
});
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("client with API key does not throw", (t) => {
|
|
16
|
-
const client = new FriendlyCaptchaClient({ apiKey: "test" });
|
|
17
|
-
t.assert(client);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("unencodable response gets rejected", async (t) => {
|
|
21
|
-
const circularReference = { self: undefined as any };
|
|
22
|
-
circularReference.self = circularReference;
|
|
23
|
-
|
|
24
|
-
const client = new FriendlyCaptchaClient({ apiKey: "my-api-key" });
|
|
25
|
-
const result = await client.verifyCaptchaResponse(circularReference as any);
|
|
26
|
-
|
|
27
|
-
t.true(result.isEncodeError());
|
|
28
|
-
t.false(result.isClientError());
|
|
29
|
-
t.false(result.isRequestOrTimeoutError());
|
|
30
|
-
t.false(result.isDecodeError());
|
|
31
|
-
|
|
32
|
-
t.false(result.shouldAccept());
|
|
33
|
-
t.true(result.shouldReject());
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("request failure gets accepted", async (t) => {
|
|
37
|
-
const client = new FriendlyCaptchaClient({ apiKey: "my-api-key", siteverifyEndpoint: "http://localhost:9999" }); // Assumes nothing is listening on port 9999
|
|
38
|
-
const result = await client.verifyCaptchaResponse("something");
|
|
39
|
-
|
|
40
|
-
t.false(result.isEncodeError());
|
|
41
|
-
t.false(result.isClientError());
|
|
42
|
-
t.true(result.isRequestOrTimeoutError());
|
|
43
|
-
t.false(result.isDecodeError());
|
|
44
|
-
|
|
45
|
-
t.true(result.shouldAccept());
|
|
46
|
-
t.false(result.shouldReject());
|
|
47
|
-
});
|
package/test/client/mock.test.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import test from "ava";
|
|
2
|
-
import request from "sync-request";
|
|
3
|
-
import { FriendlyCaptchaClient } from "../../src/client/index.js";
|
|
4
|
-
|
|
5
|
-
// Tests served from the SDK test mock server
|
|
6
|
-
const mockServerUrl = "http://localhost:1090";
|
|
7
|
-
|
|
8
|
-
type TestCase = {
|
|
9
|
-
name: string;
|
|
10
|
-
response: string;
|
|
11
|
-
strict: boolean;
|
|
12
|
-
|
|
13
|
-
siteverify_response: any;
|
|
14
|
-
siteverify_status_code: number;
|
|
15
|
-
|
|
16
|
-
expectation: {
|
|
17
|
-
should_accept: boolean;
|
|
18
|
-
was_able_to_verify: boolean;
|
|
19
|
-
is_client_error: boolean;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
type TestCasesFile = {
|
|
24
|
-
version: number;
|
|
25
|
-
tests: TestCase[];
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const casesFile: TestCasesFile = JSON.parse(request("GET", `${mockServerUrl}/api/v1/tests`).getBody("utf8"));
|
|
29
|
-
|
|
30
|
-
for (const testCase of casesFile.tests) {
|
|
31
|
-
test(testCase.name, async (t) => {
|
|
32
|
-
const client = new FriendlyCaptchaClient({
|
|
33
|
-
apiKey: "some-api-key",
|
|
34
|
-
siteverifyEndpoint: `${mockServerUrl}/api/v2/captcha/siteverify`,
|
|
35
|
-
strict: testCase.strict,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const result = await client.verifyCaptchaResponse(testCase.response);
|
|
39
|
-
|
|
40
|
-
t.is(result.shouldAccept(), testCase.expectation.should_accept);
|
|
41
|
-
t.is(result.wasAbleToVerify(), testCase.expectation.was_able_to_verify);
|
|
42
|
-
t.is(result.isClientError(), testCase.expectation.is_client_error);
|
|
43
|
-
});
|
|
44
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"moduleResolution": "node",
|
|
4
|
-
"target": "es6",
|
|
5
|
-
"module":"es2015",
|
|
6
|
-
"lib": ["es2015", "es2016", "es2017", "dom"],
|
|
7
|
-
"strict": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"allowSyntheticDefaultImports": true,
|
|
11
|
-
"outDir": "build/",
|
|
12
|
-
"typeRoots": [
|
|
13
|
-
"node_modules/@types"
|
|
14
|
-
]
|
|
15
|
-
},
|
|
16
|
-
"include": [
|
|
17
|
-
"src",
|
|
18
|
-
"test"
|
|
19
|
-
]
|
|
20
|
-
}
|