@gr4vy/sdk 0.18.4 → 0.18.8
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/bin/mcp-server.js +6 -6
- package/bin/mcp-server.js.map +4 -4
- package/index.d.ts +3 -3
- package/index.d.ts.map +1 -1
- package/index.js +5 -4
- package/index.js.map +1 -1
- package/jsr.json +1 -1
- package/lib/auth.d.ts +10 -0
- package/lib/auth.d.ts.map +1 -1
- package/lib/auth.js +16 -2
- package/lib/auth.js.map +1 -1
- package/lib/config.d.ts +3 -3
- package/lib/config.js +3 -3
- package/mcp-server/mcp-server.js +1 -1
- package/mcp-server/server.js +1 -1
- package/package.json +3 -1
- package/src/index.ts +11 -4
- package/src/lib/auth.ts +35 -3
- package/src/lib/config.ts +3 -3
- package/src/mcp-server/mcp-server.ts +1 -1
- package/src/mcp-server/server.ts +1 -1
- package/tests/authentication.test.js +207 -0
- package/tests/webhook.test.ts +120 -0
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from "./sdk";
|
|
2
1
|
export * from "./lib/config";
|
|
3
|
-
export
|
|
4
|
-
export {
|
|
2
|
+
export * from "./sdk";
|
|
3
|
+
export { getEmbedToken, getToken, JWTScope, updateToken, withToken } from "./lib/auth";
|
|
5
4
|
export type { EmbedParams } from "./lib/auth";
|
|
5
|
+
export { verifyWebhook } from "./lib/webhooks";
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAIA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC;AAC7B,cAAc,OAAO,CAAC;AAEtB,OAAO,EACH,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,SAAS,EACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
package/index.js
CHANGED
|
@@ -17,14 +17,15 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.verifyWebhook = exports.
|
|
21
|
-
__exportStar(require("./sdk"), exports);
|
|
20
|
+
exports.verifyWebhook = exports.withToken = exports.updateToken = exports.JWTScope = exports.getToken = exports.getEmbedToken = void 0;
|
|
22
21
|
__exportStar(require("./lib/config"), exports);
|
|
22
|
+
__exportStar(require("./sdk"), exports);
|
|
23
23
|
var auth_1 = require("./lib/auth");
|
|
24
|
-
Object.defineProperty(exports, "getToken", { enumerable: true, get: function () { return auth_1.getToken; } });
|
|
25
24
|
Object.defineProperty(exports, "getEmbedToken", { enumerable: true, get: function () { return auth_1.getEmbedToken; } });
|
|
26
|
-
Object.defineProperty(exports, "
|
|
25
|
+
Object.defineProperty(exports, "getToken", { enumerable: true, get: function () { return auth_1.getToken; } });
|
|
27
26
|
Object.defineProperty(exports, "JWTScope", { enumerable: true, get: function () { return auth_1.JWTScope; } });
|
|
27
|
+
Object.defineProperty(exports, "updateToken", { enumerable: true, get: function () { return auth_1.updateToken; } });
|
|
28
|
+
Object.defineProperty(exports, "withToken", { enumerable: true, get: function () { return auth_1.withToken; } });
|
|
28
29
|
var webhooks_1 = require("./lib/webhooks");
|
|
29
30
|
Object.defineProperty(exports, "verifyWebhook", { enumerable: true, get: function () { return webhooks_1.verifyWebhook; } });
|
|
30
31
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;AAEH,wCAAsB;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;;AAEH,+CAA6B;AAC7B,wCAAsB;AAEtB,mCAMoB;AALhB,qGAAA,aAAa,OAAA;AACb,gGAAA,QAAQ,OAAA;AACR,gGAAA,QAAQ,OAAA;AACR,mGAAA,WAAW,OAAA;AACX,iGAAA,SAAS,OAAA;AAGb,2CAA+C;AAAtC,yGAAA,aAAa,OAAA"}
|
package/jsr.json
CHANGED
package/lib/auth.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CartItem } from "../models/components";
|
|
1
2
|
/**
|
|
2
3
|
* Helper method for generating a bearer token for use with the SDK
|
|
3
4
|
*/
|
|
@@ -16,6 +17,14 @@ export declare const getToken: (options: {
|
|
|
16
17
|
embedParams?: EmbedParams;
|
|
17
18
|
checkoutSessionId?: string;
|
|
18
19
|
}) => Promise<string>;
|
|
20
|
+
export declare const updateToken: (options: {
|
|
21
|
+
token: string;
|
|
22
|
+
privateKey: string;
|
|
23
|
+
expiresIn?: string;
|
|
24
|
+
scopes?: JWTScope[] | string[];
|
|
25
|
+
embedParams?: EmbedParams;
|
|
26
|
+
checkoutSessionId?: string;
|
|
27
|
+
}) => Promise<string>;
|
|
19
28
|
/**
|
|
20
29
|
* Helper method for generating a bearer token for use with Embed
|
|
21
30
|
*/
|
|
@@ -78,6 +87,7 @@ export type EmbedParams = {
|
|
|
78
87
|
buyerId?: string;
|
|
79
88
|
buyerExternalIdentifier?: string;
|
|
80
89
|
metadata?: Record<string, string>;
|
|
90
|
+
cartItems?: Array<CartItem>;
|
|
81
91
|
merchantAccountId?: string;
|
|
82
92
|
connectionOptions?: Record<string, any>;
|
|
83
93
|
};
|
package/lib/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/lib/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
package/lib/auth.js
CHANGED
|
@@ -3,12 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.JWTScope = exports.getEmbedToken = exports.getToken = exports.withToken = void 0;
|
|
6
|
+
exports.JWTScope = exports.getEmbedToken = exports.updateToken = exports.getToken = exports.withToken = void 0;
|
|
7
7
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
8
|
const snakecase_keys_1 = __importDefault(require("snakecase-keys"));
|
|
9
9
|
const uuid_1 = require("uuid");
|
|
10
10
|
const config_1 = require("./config");
|
|
11
|
-
// import { CartItem } from "../models/components/cartitem";
|
|
12
11
|
const helpers_1 = require("./helpers");
|
|
13
12
|
const ua = (0, helpers_1.getRuntime)();
|
|
14
13
|
const issuer = `Gr4vy Node SDK ${config_1.SDK_METADATA.sdkVersion} - ${ua}`;
|
|
@@ -48,6 +47,21 @@ const getToken = async (options) => {
|
|
|
48
47
|
});
|
|
49
48
|
};
|
|
50
49
|
exports.getToken = getToken;
|
|
50
|
+
const updateToken = async (options) => {
|
|
51
|
+
const { token, privateKey, scopes, checkoutSessionId, embedParams, expiresIn = "30s", } = options;
|
|
52
|
+
const payload = jsonwebtoken_1.default.verify(token, privateKey, {
|
|
53
|
+
algorithms: ['ES512'],
|
|
54
|
+
ignoreExpiration: true,
|
|
55
|
+
});
|
|
56
|
+
return (0, exports.getToken)({
|
|
57
|
+
privateKey,
|
|
58
|
+
scopes: scopes ?? payload.scopes,
|
|
59
|
+
expiresIn,
|
|
60
|
+
embedParams: embedParams ?? payload.embed,
|
|
61
|
+
checkoutSessionId: checkoutSessionId ?? payload.checkout_session_id
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
exports.updateToken = updateToken;
|
|
51
65
|
/**
|
|
52
66
|
* Helper method for generating a bearer token for use with Embed
|
|
53
67
|
*/
|
package/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/lib/auth.ts"],"names":[],"mappings":";;;;;;AAAA,gEAA+
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
package/lib/config.d.ts
CHANGED
|
@@ -40,8 +40,8 @@ export declare function serverURLFromOptions(options: SDKOptions): URL | null;
|
|
|
40
40
|
export declare const SDK_METADATA: {
|
|
41
41
|
readonly language: "typescript";
|
|
42
42
|
readonly openapiDocVersion: "1.0.0";
|
|
43
|
-
readonly sdkVersion: "0.18.
|
|
44
|
-
readonly genVersion: "2.
|
|
45
|
-
readonly userAgent: "speakeasy-sdk/typescript 0.18.
|
|
43
|
+
readonly sdkVersion: "0.18.8";
|
|
44
|
+
readonly genVersion: "2.593.3";
|
|
45
|
+
readonly userAgent: "speakeasy-sdk/typescript 0.18.8 2.593.3 1.0.0 @gr4vy/sdk";
|
|
46
46
|
};
|
|
47
47
|
//# sourceMappingURL=config.d.ts.map
|
package/lib/config.js
CHANGED
|
@@ -37,8 +37,8 @@ function serverURLFromOptions(options) {
|
|
|
37
37
|
exports.SDK_METADATA = {
|
|
38
38
|
language: "typescript",
|
|
39
39
|
openapiDocVersion: "1.0.0",
|
|
40
|
-
sdkVersion: "0.18.
|
|
41
|
-
genVersion: "2.
|
|
42
|
-
userAgent: "speakeasy-sdk/typescript 0.18.
|
|
40
|
+
sdkVersion: "0.18.8",
|
|
41
|
+
genVersion: "2.593.3",
|
|
42
|
+
userAgent: "speakeasy-sdk/typescript 0.18.8 2.593.3 1.0.0 @gr4vy/sdk",
|
|
43
43
|
};
|
|
44
44
|
//# sourceMappingURL=config.js.map
|
package/mcp-server/mcp-server.js
CHANGED
|
@@ -22,7 +22,7 @@ const routes = (0, core_1.buildRouteMap)({
|
|
|
22
22
|
exports.app = (0, core_1.buildApplication)(routes, {
|
|
23
23
|
name: "mcp",
|
|
24
24
|
versionInfo: {
|
|
25
|
-
currentVersion: "0.18.
|
|
25
|
+
currentVersion: "0.18.8",
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
28
|
(0, core_1.run)(exports.app, node_process_1.default.argv.slice(2), (0, cli_js_1.buildContext)(node_process_1.default));
|
package/mcp-server/server.js
CHANGED
|
@@ -75,7 +75,7 @@ const transactionsVoid_js_1 = require("./tools/transactionsVoid.js");
|
|
|
75
75
|
function createMCPServer(deps) {
|
|
76
76
|
const server = new mcp_js_1.McpServer({
|
|
77
77
|
name: "Gr4vy",
|
|
78
|
-
version: "0.18.
|
|
78
|
+
version: "0.18.8",
|
|
79
79
|
});
|
|
80
80
|
const client = new core_js_1.Gr4vyCore({
|
|
81
81
|
bearerAuth: deps.bearerAuth,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gr4vy/sdk",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8",
|
|
4
4
|
"author": "Gr4vy",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mcp": "bin/mcp-server.js"
|
|
@@ -37,8 +37,10 @@
|
|
|
37
37
|
"eslint": "^9.19.0",
|
|
38
38
|
"express": "^4.21.2",
|
|
39
39
|
"globals": "^15.14.0",
|
|
40
|
+
"timekeeper": "^2.3.1",
|
|
40
41
|
"typescript": "^5.4.5",
|
|
41
42
|
"typescript-eslint": "^8.22.0",
|
|
43
|
+
"vitest": "^3.1.2",
|
|
42
44
|
"zod": "^3.23.4"
|
|
43
45
|
},
|
|
44
46
|
"dependencies": {
|
package/src/index.ts
CHANGED
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
* Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export * from "./sdk";
|
|
6
5
|
export * from "./lib/config";
|
|
6
|
+
export * from "./sdk";
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
getEmbedToken,
|
|
10
|
+
getToken,
|
|
11
|
+
JWTScope,
|
|
12
|
+
updateToken,
|
|
13
|
+
withToken
|
|
14
|
+
} from "./lib/auth";
|
|
15
|
+
export type { EmbedParams } from "./lib/auth";
|
|
16
|
+
export { verifyWebhook } from "./lib/webhooks";
|
|
7
17
|
|
|
8
|
-
export { getToken, getEmbedToken, withToken, JWTScope } from "./lib/auth"
|
|
9
|
-
export { verifyWebhook } from "./lib/webhooks"
|
|
10
|
-
export type { EmbedParams } from "./lib/auth"
|
package/src/lib/auth.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import jwt from "jsonwebtoken";
|
|
1
|
+
import jwt, { JwtPayload } from "jsonwebtoken";
|
|
2
2
|
import snakeCaseKeys from "snakecase-keys";
|
|
3
3
|
import { v4 as uuid } from "uuid";
|
|
4
4
|
|
|
5
|
+
import { CartItem } from "../models/components";
|
|
5
6
|
import { SDK_METADATA } from "./config";
|
|
6
|
-
// import { CartItem } from "../models/components/cartitem";
|
|
7
7
|
import { getKeyId, getRuntime } from "./helpers";
|
|
8
8
|
|
|
9
9
|
const ua = getRuntime();
|
|
@@ -71,6 +71,38 @@ export const getToken = async (options: {
|
|
|
71
71
|
});
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
+
export const updateToken = async (options: {
|
|
75
|
+
token: string
|
|
76
|
+
privateKey: string;
|
|
77
|
+
expiresIn?: string;
|
|
78
|
+
scopes?: JWTScope[] | string[];
|
|
79
|
+
embedParams?: EmbedParams;
|
|
80
|
+
checkoutSessionId?: string;
|
|
81
|
+
}): Promise<string> => {
|
|
82
|
+
const {
|
|
83
|
+
token,
|
|
84
|
+
privateKey,
|
|
85
|
+
scopes,
|
|
86
|
+
checkoutSessionId,
|
|
87
|
+
embedParams,
|
|
88
|
+
expiresIn = "30s",
|
|
89
|
+
} = options;
|
|
90
|
+
|
|
91
|
+
const payload = jwt.verify(token, privateKey, {
|
|
92
|
+
algorithms: ['ES512'],
|
|
93
|
+
ignoreExpiration: true,
|
|
94
|
+
}) as JwtPayload | Claims
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
return getToken({
|
|
98
|
+
privateKey,
|
|
99
|
+
scopes: scopes ?? payload.scopes,
|
|
100
|
+
expiresIn,
|
|
101
|
+
embedParams: embedParams ?? payload.embed,
|
|
102
|
+
checkoutSessionId: checkoutSessionId ?? payload.checkout_session_id
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
74
106
|
/**
|
|
75
107
|
* Helper method for generating a bearer token for use with Embed
|
|
76
108
|
*/
|
|
@@ -141,7 +173,7 @@ export type EmbedParams = {
|
|
|
141
173
|
buyerId?: string;
|
|
142
174
|
buyerExternalIdentifier?: string;
|
|
143
175
|
metadata?: Record<string, string>;
|
|
144
|
-
|
|
176
|
+
cartItems?: Array<CartItem>;
|
|
145
177
|
merchantAccountId?: string;
|
|
146
178
|
connectionOptions?: Record<string, any>;
|
|
147
179
|
};
|
package/src/lib/config.ts
CHANGED
|
@@ -73,7 +73,7 @@ export function serverURLFromOptions(options: SDKOptions): URL | null {
|
|
|
73
73
|
export const SDK_METADATA = {
|
|
74
74
|
language: "typescript",
|
|
75
75
|
openapiDocVersion: "1.0.0",
|
|
76
|
-
sdkVersion: "0.18.
|
|
77
|
-
genVersion: "2.
|
|
78
|
-
userAgent: "speakeasy-sdk/typescript 0.18.
|
|
76
|
+
sdkVersion: "0.18.8",
|
|
77
|
+
genVersion: "2.593.3",
|
|
78
|
+
userAgent: "speakeasy-sdk/typescript 0.18.8 2.593.3 1.0.0 @gr4vy/sdk",
|
|
79
79
|
} as const;
|
package/src/mcp-server/server.ts
CHANGED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import jwt from "jsonwebtoken";
|
|
2
|
+
import snakecaseKeys from "snakecase-keys";
|
|
3
|
+
import timekeeper from "timekeeper";
|
|
4
|
+
import { describe, expect, test } from "vitest";
|
|
5
|
+
import { version } from "../package.json";
|
|
6
|
+
import { getEmbedToken, getToken, JWTScope, updateToken } from "../src";
|
|
7
|
+
|
|
8
|
+
const privateKey = `-----BEGIN PRIVATE KEY-----
|
|
9
|
+
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBABM9jQu+HT87oIik
|
|
10
|
+
O6DiJjYeghr3V+VMBVNU2hCM3X/OAS6TUTylMbnjDnwWdmu7anVSnjvEY1a4KxQ9
|
|
11
|
+
WZ8E/PKhgYkDgYYABABRdv5VAtOsGb6THxeK/p7RAARPm6Zwb7FF4sZAYkkSB7h0
|
|
12
|
+
2jpj3UHSpyl92BQkiF/xakz7hMMD1A0ZTn5SuXWp3AG9qPHO3eB9WrZhPGYixwyo
|
|
13
|
+
XNjhnPEDhmkItKXteke9iBOTOOXB7AFQSh7EXRBmhBs4u3ZlTmrl+8VdBc3+jwAY
|
|
14
|
+
rw==
|
|
15
|
+
-----END PRIVATE KEY-----`;
|
|
16
|
+
|
|
17
|
+
const thumbprint = "va-SLs5AxJNfqKXD8LI5Y38BflpNvjZjY4RSWz66U1w";
|
|
18
|
+
|
|
19
|
+
const embedParams = {
|
|
20
|
+
amount: 9000,
|
|
21
|
+
currency: "USD",
|
|
22
|
+
buyerExternalIdentifier: "user-123",
|
|
23
|
+
connectionOptions: {
|
|
24
|
+
"stripe-card": {
|
|
25
|
+
stripe_connect: {
|
|
26
|
+
key: "value",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
metadata: {
|
|
31
|
+
camelCaseKey: "value1",
|
|
32
|
+
snake_case_key: "value2",
|
|
33
|
+
},
|
|
34
|
+
cartItems: [
|
|
35
|
+
{
|
|
36
|
+
name: "Joust Duffle Bag",
|
|
37
|
+
quantity: 1,
|
|
38
|
+
unitAmount: 9000,
|
|
39
|
+
taxAmount: 0,
|
|
40
|
+
categories: ["Gear", "Bags", "Test"],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const checkoutSessionId = "0ebde6a1-f66c-43ea-bb8b-73751864c604";
|
|
46
|
+
|
|
47
|
+
describe(".getToken", () => {
|
|
48
|
+
test("should create a valid signed JWT token", async () => {
|
|
49
|
+
const token = await getToken({
|
|
50
|
+
privateKey,
|
|
51
|
+
scopes: [JWTScope.ReadAll, JWTScope.WriteAll],
|
|
52
|
+
expiresIn: "1m",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const decoded = jwt.verify(token, privateKey, {
|
|
56
|
+
algorithms: ["ES512"],
|
|
57
|
+
complete: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(decoded.header.alg).toBe("ES512");
|
|
61
|
+
expect(decoded.header.typ).toBe("JWT");
|
|
62
|
+
expect(decoded.header.kid).toBe(thumbprint);
|
|
63
|
+
expect(decoded.payload.scopes).toEqual(["*.read", "*.write"]);
|
|
64
|
+
expect(typeof decoded.payload.iat).toBe("number");
|
|
65
|
+
expect(typeof decoded.payload.nbf).toBe("number");
|
|
66
|
+
expect(typeof decoded.payload.exp).toBe("number");
|
|
67
|
+
expect(decoded.payload.iss.startsWith("Gr4vy Node SDK")).toBeTruthy();
|
|
68
|
+
expect(decoded.payload.iss).toMatch("Gr4vy Node SDK");
|
|
69
|
+
expect(decoded.payload.iss).toMatch(version);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("should accept optional embed data", async () => {
|
|
73
|
+
const token = await getToken({
|
|
74
|
+
privateKey,
|
|
75
|
+
scopes: [JWTScope.Embed],
|
|
76
|
+
embedParams,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const decoded = jwt.verify(token, privateKey, {
|
|
80
|
+
algorithms: ["ES512"],
|
|
81
|
+
complete: true,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const connOptions =
|
|
85
|
+
embedParams.connectionOptions || embedParams["connection_options"];
|
|
86
|
+
const expected = snakecaseKeys(embedParams, { exclude: ["metadata"] });
|
|
87
|
+
expected["connection_options"] = connOptions;
|
|
88
|
+
|
|
89
|
+
expect(decoded.payload.scopes).toEqual(["embed"]);
|
|
90
|
+
expect(decoded.payload.embed).toEqual(expected);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("should ignore embed data if the embed scope was not set", async () => {
|
|
94
|
+
const token = await getToken({
|
|
95
|
+
privateKey,
|
|
96
|
+
scopes: [JWTScope.ReadAll],
|
|
97
|
+
embedParams,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const decoded = jwt.verify(token, privateKey, {
|
|
101
|
+
algorithms: ["ES512"],
|
|
102
|
+
complete: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(decoded.payload.scopes).toEqual(["*.read"]);
|
|
106
|
+
expect(decoded.payload.embed).toBeUndefined();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe(".getEmbedToken", () => {
|
|
111
|
+
test("should create a JWT token for use with Embed", async () => {
|
|
112
|
+
const token = await getEmbedToken({
|
|
113
|
+
privateKey,
|
|
114
|
+
embedParams,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const decoded = jwt.verify(token, privateKey, {
|
|
118
|
+
algorithms: ["ES512"],
|
|
119
|
+
complete: true,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const connOptions =
|
|
123
|
+
embedParams.connectionOptions || embedParams["connection_options"];
|
|
124
|
+
const expected = snakecaseKeys(embedParams, { exclude: ["metadata"] });
|
|
125
|
+
expected["connection_options"] = connOptions;
|
|
126
|
+
|
|
127
|
+
expect(decoded.payload.scopes).toEqual(["embed"]);
|
|
128
|
+
expect(decoded.payload.embed).toEqual(expected);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("should take an optional checkout session ID", async () => {
|
|
132
|
+
const token = await getEmbedToken({
|
|
133
|
+
privateKey,
|
|
134
|
+
embedParams,
|
|
135
|
+
checkoutSessionId,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const decoded = jwt.verify(token, privateKey, {
|
|
139
|
+
algorithms: ["ES512"],
|
|
140
|
+
complete: true,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(decoded.payload.checkout_session_id).toEqual(checkoutSessionId);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe(".updateToken", () => {
|
|
148
|
+
test("should resign a token with a new signature and expiration", async () => {
|
|
149
|
+
timekeeper.freeze(Date.now());
|
|
150
|
+
|
|
151
|
+
const originalToken = await getToken({ privateKey, expiresIn: "1m" });
|
|
152
|
+
|
|
153
|
+
timekeeper.travel(Date.now() + 1000 * 90);
|
|
154
|
+
|
|
155
|
+
const newToken = await updateToken({
|
|
156
|
+
privateKey,
|
|
157
|
+
token: originalToken,
|
|
158
|
+
expiresIn: "1m",
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const originalDecoded = jwt.decode(originalToken, { complete: true });
|
|
162
|
+
const newDecoded = jwt.decode(newToken, { complete: true });
|
|
163
|
+
|
|
164
|
+
expect(newDecoded.header).toEqual(originalDecoded.header);
|
|
165
|
+
expect(newDecoded.payload.scopes).toEqual(originalDecoded.payload.scopes);
|
|
166
|
+
expect(newDecoded.payload.embed).toEqual(originalDecoded.payload.embed);
|
|
167
|
+
expect(newDecoded.payload.checkout_session_id).toEqual(
|
|
168
|
+
originalDecoded.payload.checkout_session_id
|
|
169
|
+
);
|
|
170
|
+
expect(newDecoded.payload.iat).toBeGreaterThan(originalDecoded.payload.iat);
|
|
171
|
+
expect(newDecoded.payload.exp).toBeGreaterThan(originalDecoded.payload.exp);
|
|
172
|
+
expect(newDecoded.payload.nbf).toBeGreaterThan(originalDecoded.payload.nbf);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("should allow an Embed token to be updated with new Embed params", async () => {
|
|
176
|
+
timekeeper.freeze(Date.now());
|
|
177
|
+
|
|
178
|
+
const originalToken = await getEmbedToken({
|
|
179
|
+
privateKey,
|
|
180
|
+
embedParams,
|
|
181
|
+
checkoutSessionId,
|
|
182
|
+
expiresIn: "1m",
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
timekeeper.travel(Date.now() + 1000 * 90);
|
|
186
|
+
|
|
187
|
+
const newEmbedParams = {
|
|
188
|
+
amount: 1299,
|
|
189
|
+
currency: "USD",
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const newToken = await updateToken({
|
|
193
|
+
token: originalToken,
|
|
194
|
+
expiresIn: "1m",
|
|
195
|
+
embedParams: newEmbedParams,
|
|
196
|
+
privateKey,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const originalDecoded = jwt.decode(originalToken, { complete: true });
|
|
200
|
+
const newDecoded = jwt.decode(newToken, { complete: true });
|
|
201
|
+
|
|
202
|
+
expect(newDecoded.payload.embed).toEqual(newEmbedParams);
|
|
203
|
+
expect(newDecoded.payload.checkout_session_id).toEqual(
|
|
204
|
+
originalDecoded.payload.checkout_session_id
|
|
205
|
+
);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { verifyWebhook } from "../src";
|
|
3
|
+
|
|
4
|
+
describe(".verifyWebook()", () => {
|
|
5
|
+
test("should verify a webhook signature", async () => {
|
|
6
|
+
const secret =
|
|
7
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
8
|
+
const signatureHeader =
|
|
9
|
+
"78aca0c78005107a654a957b8566fa6e0e5e06aea92d7da72a6da9e5a690d013,other";
|
|
10
|
+
const timestampHeader = "1744018920";
|
|
11
|
+
const payload = "payload";
|
|
12
|
+
const timestampTolerance = 0; // no timestamp validation
|
|
13
|
+
|
|
14
|
+
verifyWebhook(
|
|
15
|
+
payload,
|
|
16
|
+
secret,
|
|
17
|
+
signatureHeader,
|
|
18
|
+
timestampHeader,
|
|
19
|
+
timestampTolerance
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("should raise an error for an old timestamp", async () => {
|
|
24
|
+
const secret =
|
|
25
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
26
|
+
const signatureHeader =
|
|
27
|
+
"78aca0c78005107a654a957b8566fa6e0e5e06aea92d7da72a6da9e5a690d013,other";
|
|
28
|
+
const timestampHeader = "1744018920";
|
|
29
|
+
const payload = "payload";
|
|
30
|
+
const timestampTolerance = 60; // 1 minute tolerance
|
|
31
|
+
|
|
32
|
+
expect(() => {
|
|
33
|
+
verifyWebhook(
|
|
34
|
+
payload,
|
|
35
|
+
secret,
|
|
36
|
+
signatureHeader,
|
|
37
|
+
timestampHeader,
|
|
38
|
+
timestampTolerance
|
|
39
|
+
);
|
|
40
|
+
}).toThrow("Timestamp too old");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("should raise an error for a wrong signature", async () => {
|
|
44
|
+
const secret =
|
|
45
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
46
|
+
const signatureHeader = "other";
|
|
47
|
+
const timestampHeader = "1744018920";
|
|
48
|
+
const payload = "payload";
|
|
49
|
+
const timestampTolerance = 0; // no timestamp validation
|
|
50
|
+
|
|
51
|
+
expect(() => {
|
|
52
|
+
verifyWebhook(
|
|
53
|
+
payload,
|
|
54
|
+
secret,
|
|
55
|
+
signatureHeader,
|
|
56
|
+
timestampHeader,
|
|
57
|
+
timestampTolerance
|
|
58
|
+
);
|
|
59
|
+
}).toThrow("No matching signature found");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("should raise an error for an invalid timestamp", async () => {
|
|
63
|
+
const secret =
|
|
64
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
65
|
+
const signatureHeader =
|
|
66
|
+
"78aca0c78005107a654a957b8566fa6e0e5e06aea92d7da72a6da9e5a690d013,other";
|
|
67
|
+
const timestampHeader = "wrong";
|
|
68
|
+
const payload = "payload";
|
|
69
|
+
const timestampTolerance = 0; // no timestamp validation
|
|
70
|
+
|
|
71
|
+
expect(() => {
|
|
72
|
+
verifyWebhook(
|
|
73
|
+
payload,
|
|
74
|
+
secret,
|
|
75
|
+
signatureHeader,
|
|
76
|
+
timestampHeader,
|
|
77
|
+
timestampTolerance
|
|
78
|
+
);
|
|
79
|
+
}).toThrow("Invalid header timestamp");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("should raise an error for a missing signature header", async () => {
|
|
83
|
+
const secret =
|
|
84
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
85
|
+
const signatureHeader = null;
|
|
86
|
+
const timestampHeader = "wrong";
|
|
87
|
+
const payload = "payload";
|
|
88
|
+
const timestampTolerance = 0; // no timestamp validation
|
|
89
|
+
|
|
90
|
+
expect(() => {
|
|
91
|
+
verifyWebhook(
|
|
92
|
+
payload,
|
|
93
|
+
secret,
|
|
94
|
+
signatureHeader,
|
|
95
|
+
timestampHeader,
|
|
96
|
+
timestampTolerance
|
|
97
|
+
);
|
|
98
|
+
}).toThrow("Missing header values");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("should raise an error for a missing timestamp header", async () => {
|
|
102
|
+
const secret =
|
|
103
|
+
"Ik4L-8FH0ihWczctcIPXZRR_8F0fPNgmhEfVBbZ3zNwqQVa1Or4tBz4Pgw2eNaVDod7H56Y268h_wohEUaWbUg";
|
|
104
|
+
const signatureHeader =
|
|
105
|
+
"78aca0c78005107a654a957b8566fa6e0e5e06aea92d7da72a6da9e5a690d013,other";
|
|
106
|
+
const timestampHeader = null;
|
|
107
|
+
const payload = "payload";
|
|
108
|
+
const timestampTolerance = 0; // no timestamp validation
|
|
109
|
+
|
|
110
|
+
expect(() => {
|
|
111
|
+
verifyWebhook(
|
|
112
|
+
payload,
|
|
113
|
+
secret,
|
|
114
|
+
signatureHeader,
|
|
115
|
+
timestampHeader,
|
|
116
|
+
timestampTolerance
|
|
117
|
+
);
|
|
118
|
+
}).toThrow("Missing header values");
|
|
119
|
+
});
|
|
120
|
+
});
|