@scalekit-sdk/node 1.0.7 → 1.0.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/buf.gen.yaml +2 -1
- package/lib/core.js +1 -1
- package/lib/directory.d.ts +78 -0
- package/lib/directory.js +126 -0
- package/lib/directory.js.map +1 -0
- package/lib/organization.d.ts +8 -0
- package/lib/organization.js +20 -0
- package/lib/organization.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.d.ts +118 -0
- package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js +126 -0
- package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js.map +1 -0
- package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.d.ts +960 -0
- package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js +1429 -0
- package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js.map +1 -0
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.d.ts +10 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js +9 -0
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js.map +1 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.d.ts +81 -0
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js +113 -1
- package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js.map +1 -1
- package/lib/scalekit.d.ts +27 -1
- package/lib/scalekit.js +67 -1
- package/lib/scalekit.js.map +1 -1
- package/lib/types/organization.d.ts +7 -0
- package/lib/types/organization.js +3 -0
- package/lib/types/organization.js.map +1 -0
- package/package.json +1 -1
- package/src/core.ts +1 -1
- package/src/directory.ts +173 -0
- package/src/organization.ts +24 -1
- package/src/pkg/grpc/scalekit/v1/directories/directories_connect.ts +125 -0
- package/src/pkg/grpc/scalekit/v1/directories/directories_pb.ts +1838 -0
- package/src/pkg/grpc/scalekit/v1/organizations/organizations_connect.ts +10 -1
- package/src/pkg/grpc/scalekit/v1/organizations/organizations_pb.ts +155 -0
- package/src/scalekit.ts +78 -3
- package/src/types/organization.ts +8 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
// @ts-nocheck
|
|
5
5
|
|
|
6
|
-
import { CreateOrganizationRequest, CreateOrganizationResponse, DeleteOrganizationRequest, DeletePortalLinkByIdRequest, DeletePortalLinkRequest, GeneratePortalLinkRequest, GeneratePortalLinkResponse, GetOrganizationRequest, GetOrganizationResponse, GetPortalLinkRequest, GetPortalLinksResponse, ListOrganizationsRequest, ListOrganizationsResponse, SearchOrganizationsRequest, SearchOrganizationsResponse, UpdateOrganizationRequest, UpdateOrganizationResponse } from "./organizations_pb.js";
|
|
6
|
+
import { CreateOrganizationRequest, CreateOrganizationResponse, DeleteOrganizationRequest, DeletePortalLinkByIdRequest, DeletePortalLinkRequest, GeneratePortalLinkRequest, GeneratePortalLinkResponse, GetOrganizationRequest, GetOrganizationResponse, GetPortalLinkRequest, GetPortalLinksResponse, ListOrganizationsRequest, ListOrganizationsResponse, SearchOrganizationsRequest, SearchOrganizationsResponse, UpdateOrganizationRequest, UpdateOrganizationResponse, UpdateOrganizationSettingsRequest } from "./organizations_pb.js";
|
|
7
7
|
import { Empty, MethodKind } from "@bufbuild/protobuf";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -108,6 +108,15 @@ export const OrganizationService = {
|
|
|
108
108
|
O: GetPortalLinksResponse,
|
|
109
109
|
kind: MethodKind.Unary,
|
|
110
110
|
},
|
|
111
|
+
/**
|
|
112
|
+
* @generated from rpc scalekit.v1.organizations.OrganizationService.UpdateOrganizationSettings
|
|
113
|
+
*/
|
|
114
|
+
updateOrganizationSettings: {
|
|
115
|
+
name: "UpdateOrganizationSettings",
|
|
116
|
+
I: UpdateOrganizationSettingsRequest,
|
|
117
|
+
O: GetOrganizationResponse,
|
|
118
|
+
kind: MethodKind.Unary,
|
|
119
|
+
},
|
|
111
120
|
}
|
|
112
121
|
} as const;
|
|
113
122
|
|
|
@@ -199,6 +199,13 @@ export class Organization extends Message<Organization> {
|
|
|
199
199
|
*/
|
|
200
200
|
metadata: { [key: string]: string } = {};
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Organization Settings
|
|
204
|
+
*
|
|
205
|
+
* @generated from field: scalekit.v1.organizations.OrganizationSettings settings = 8;
|
|
206
|
+
*/
|
|
207
|
+
settings?: OrganizationSettings;
|
|
208
|
+
|
|
202
209
|
constructor(data?: PartialMessage<Organization>) {
|
|
203
210
|
super();
|
|
204
211
|
proto3.util.initPartial(data, this);
|
|
@@ -214,6 +221,7 @@ export class Organization extends Message<Organization> {
|
|
|
214
221
|
{ no: 5, name: "region_code", kind: "enum", T: proto3.getEnumType(RegionCode) },
|
|
215
222
|
{ no: 6, name: "external_id", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
|
|
216
223
|
{ no: 7, name: "metadata", kind: "map", K: 9 /* ScalarType.STRING */, V: {kind: "scalar", T: 9 /* ScalarType.STRING */} },
|
|
224
|
+
{ no: 8, name: "settings", kind: "message", T: OrganizationSettings },
|
|
217
225
|
]);
|
|
218
226
|
|
|
219
227
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Organization {
|
|
@@ -532,6 +540,11 @@ export class ListOrganizationsResponse extends Message<ListOrganizationsResponse
|
|
|
532
540
|
*/
|
|
533
541
|
organizations: Organization[] = [];
|
|
534
542
|
|
|
543
|
+
/**
|
|
544
|
+
* @generated from field: string prev_page_token = 4;
|
|
545
|
+
*/
|
|
546
|
+
prevPageToken = "";
|
|
547
|
+
|
|
535
548
|
constructor(data?: PartialMessage<ListOrganizationsResponse>) {
|
|
536
549
|
super();
|
|
537
550
|
proto3.util.initPartial(data, this);
|
|
@@ -543,6 +556,7 @@ export class ListOrganizationsResponse extends Message<ListOrganizationsResponse
|
|
|
543
556
|
{ no: 1, name: "next_page_token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
544
557
|
{ no: 2, name: "total_size", kind: "scalar", T: 13 /* ScalarType.UINT32 */ },
|
|
545
558
|
{ no: 3, name: "organizations", kind: "message", T: Organization, repeated: true },
|
|
559
|
+
{ no: 4, name: "prev_page_token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
546
560
|
]);
|
|
547
561
|
|
|
548
562
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListOrganizationsResponse {
|
|
@@ -630,6 +644,11 @@ export class SearchOrganizationsResponse extends Message<SearchOrganizationsResp
|
|
|
630
644
|
*/
|
|
631
645
|
organizations: Organization[] = [];
|
|
632
646
|
|
|
647
|
+
/**
|
|
648
|
+
* @generated from field: string prev_page_token = 4;
|
|
649
|
+
*/
|
|
650
|
+
prevPageToken = "";
|
|
651
|
+
|
|
633
652
|
constructor(data?: PartialMessage<SearchOrganizationsResponse>) {
|
|
634
653
|
super();
|
|
635
654
|
proto3.util.initPartial(data, this);
|
|
@@ -641,6 +660,7 @@ export class SearchOrganizationsResponse extends Message<SearchOrganizationsResp
|
|
|
641
660
|
{ no: 1, name: "next_page_token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
642
661
|
{ no: 2, name: "total_size", kind: "scalar", T: 13 /* ScalarType.UINT32 */ },
|
|
643
662
|
{ no: 3, name: "organizations", kind: "message", T: Organization, repeated: true },
|
|
663
|
+
{ no: 4, name: "prev_page_token", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
644
664
|
]);
|
|
645
665
|
|
|
646
666
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SearchOrganizationsResponse {
|
|
@@ -719,6 +739,16 @@ export class GeneratePortalLinkRequest extends Message<GeneratePortalLinkRequest
|
|
|
719
739
|
*/
|
|
720
740
|
id = "";
|
|
721
741
|
|
|
742
|
+
/**
|
|
743
|
+
* @generated from field: optional bool sso = 2;
|
|
744
|
+
*/
|
|
745
|
+
sso?: boolean;
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* @generated from field: optional bool directory_sync = 3;
|
|
749
|
+
*/
|
|
750
|
+
directorySync?: boolean;
|
|
751
|
+
|
|
722
752
|
constructor(data?: PartialMessage<GeneratePortalLinkRequest>) {
|
|
723
753
|
super();
|
|
724
754
|
proto3.util.initPartial(data, this);
|
|
@@ -728,6 +758,8 @@ export class GeneratePortalLinkRequest extends Message<GeneratePortalLinkRequest
|
|
|
728
758
|
static readonly typeName = "scalekit.v1.organizations.GeneratePortalLinkRequest";
|
|
729
759
|
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
730
760
|
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
761
|
+
{ no: 2, name: "sso", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true },
|
|
762
|
+
{ no: 3, name: "directory_sync", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true },
|
|
731
763
|
]);
|
|
732
764
|
|
|
733
765
|
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GeneratePortalLinkRequest {
|
|
@@ -987,3 +1019,126 @@ export class GetPortalLinksResponse extends Message<GetPortalLinksResponse> {
|
|
|
987
1019
|
}
|
|
988
1020
|
}
|
|
989
1021
|
|
|
1022
|
+
/**
|
|
1023
|
+
* @generated from message scalekit.v1.organizations.UpdateOrganizationSettingsRequest
|
|
1024
|
+
*/
|
|
1025
|
+
export class UpdateOrganizationSettingsRequest extends Message<UpdateOrganizationSettingsRequest> {
|
|
1026
|
+
/**
|
|
1027
|
+
* @generated from field: string id = 1;
|
|
1028
|
+
*/
|
|
1029
|
+
id = "";
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* @generated from field: scalekit.v1.organizations.OrganizationSettings settings = 2;
|
|
1033
|
+
*/
|
|
1034
|
+
settings?: OrganizationSettings;
|
|
1035
|
+
|
|
1036
|
+
constructor(data?: PartialMessage<UpdateOrganizationSettingsRequest>) {
|
|
1037
|
+
super();
|
|
1038
|
+
proto3.util.initPartial(data, this);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
1042
|
+
static readonly typeName = "scalekit.v1.organizations.UpdateOrganizationSettingsRequest";
|
|
1043
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
1044
|
+
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
1045
|
+
{ no: 2, name: "settings", kind: "message", T: OrganizationSettings },
|
|
1046
|
+
]);
|
|
1047
|
+
|
|
1048
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdateOrganizationSettingsRequest {
|
|
1049
|
+
return new UpdateOrganizationSettingsRequest().fromBinary(bytes, options);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdateOrganizationSettingsRequest {
|
|
1053
|
+
return new UpdateOrganizationSettingsRequest().fromJson(jsonValue, options);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdateOrganizationSettingsRequest {
|
|
1057
|
+
return new UpdateOrganizationSettingsRequest().fromJsonString(jsonString, options);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
static equals(a: UpdateOrganizationSettingsRequest | PlainMessage<UpdateOrganizationSettingsRequest> | undefined, b: UpdateOrganizationSettingsRequest | PlainMessage<UpdateOrganizationSettingsRequest> | undefined): boolean {
|
|
1061
|
+
return proto3.util.equals(UpdateOrganizationSettingsRequest, a, b);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* @generated from message scalekit.v1.organizations.OrganizationSettings
|
|
1067
|
+
*/
|
|
1068
|
+
export class OrganizationSettings extends Message<OrganizationSettings> {
|
|
1069
|
+
/**
|
|
1070
|
+
* @generated from field: repeated scalekit.v1.organizations.OrganizationSettingsFeature features = 1;
|
|
1071
|
+
*/
|
|
1072
|
+
features: OrganizationSettingsFeature[] = [];
|
|
1073
|
+
|
|
1074
|
+
constructor(data?: PartialMessage<OrganizationSettings>) {
|
|
1075
|
+
super();
|
|
1076
|
+
proto3.util.initPartial(data, this);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
1080
|
+
static readonly typeName = "scalekit.v1.organizations.OrganizationSettings";
|
|
1081
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
1082
|
+
{ no: 1, name: "features", kind: "message", T: OrganizationSettingsFeature, repeated: true },
|
|
1083
|
+
]);
|
|
1084
|
+
|
|
1085
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): OrganizationSettings {
|
|
1086
|
+
return new OrganizationSettings().fromBinary(bytes, options);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): OrganizationSettings {
|
|
1090
|
+
return new OrganizationSettings().fromJson(jsonValue, options);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): OrganizationSettings {
|
|
1094
|
+
return new OrganizationSettings().fromJsonString(jsonString, options);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
static equals(a: OrganizationSettings | PlainMessage<OrganizationSettings> | undefined, b: OrganizationSettings | PlainMessage<OrganizationSettings> | undefined): boolean {
|
|
1098
|
+
return proto3.util.equals(OrganizationSettings, a, b);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
/**
|
|
1103
|
+
* @generated from message scalekit.v1.organizations.OrganizationSettingsFeature
|
|
1104
|
+
*/
|
|
1105
|
+
export class OrganizationSettingsFeature extends Message<OrganizationSettingsFeature> {
|
|
1106
|
+
/**
|
|
1107
|
+
* @generated from field: string name = 1;
|
|
1108
|
+
*/
|
|
1109
|
+
name = "";
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* @generated from field: bool enabled = 2;
|
|
1113
|
+
*/
|
|
1114
|
+
enabled = false;
|
|
1115
|
+
|
|
1116
|
+
constructor(data?: PartialMessage<OrganizationSettingsFeature>) {
|
|
1117
|
+
super();
|
|
1118
|
+
proto3.util.initPartial(data, this);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
static readonly runtime: typeof proto3 = proto3;
|
|
1122
|
+
static readonly typeName = "scalekit.v1.organizations.OrganizationSettingsFeature";
|
|
1123
|
+
static readonly fields: FieldList = proto3.util.newFieldList(() => [
|
|
1124
|
+
{ no: 1, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
|
|
1125
|
+
{ no: 2, name: "enabled", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
|
|
1126
|
+
]);
|
|
1127
|
+
|
|
1128
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): OrganizationSettingsFeature {
|
|
1129
|
+
return new OrganizationSettingsFeature().fromBinary(bytes, options);
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): OrganizationSettingsFeature {
|
|
1133
|
+
return new OrganizationSettingsFeature().fromJson(jsonValue, options);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): OrganizationSettingsFeature {
|
|
1137
|
+
return new OrganizationSettingsFeature().fromJsonString(jsonString, options);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
static equals(a: OrganizationSettingsFeature | PlainMessage<OrganizationSettingsFeature> | undefined, b: OrganizationSettingsFeature | PlainMessage<OrganizationSettingsFeature> | undefined): boolean {
|
|
1141
|
+
return proto3.util.equals(OrganizationSettingsFeature, a, b);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
package/src/scalekit.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
1
2
|
import * as jose from 'jose';
|
|
2
3
|
import QueryString from 'qs';
|
|
3
4
|
import GrpcConnect from './connect';
|
|
4
5
|
import ConnectionClient from './connection';
|
|
5
6
|
import { IdTokenClaimToUserMap } from './constants/user';
|
|
6
7
|
import CoreClient from './core';
|
|
8
|
+
import DirectoryClient from './directory';
|
|
7
9
|
import DomainClient from './domain';
|
|
8
10
|
import OrganizationClient from './organization';
|
|
9
|
-
import { AuthorizationUrlOptions, AuthenticationOptions, GrantType, AuthenticationResponse } from './types/scalekit';
|
|
10
11
|
import { IdpInitiatedLoginClaims, IdTokenClaim, User } from './types/auth';
|
|
12
|
+
import { AuthenticationOptions, AuthenticationResponse, AuthorizationUrlOptions, GrantType } from './types/scalekit';
|
|
11
13
|
|
|
12
14
|
const authorizeEndpoint = "oauth/authorize";
|
|
15
|
+
const WEBHOOK_TOLERANCE_IN_SECONDS = 5 * 60; // 5 minutes
|
|
16
|
+
const WEBHOOK_SIGNATURE_VERSION = "v1";
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* To initiate scalekit
|
|
@@ -26,6 +30,7 @@ export default class ScalekitClient {
|
|
|
26
30
|
readonly organization: OrganizationClient;
|
|
27
31
|
readonly connection: ConnectionClient;
|
|
28
32
|
readonly domain: DomainClient;
|
|
33
|
+
readonly directory: DirectoryClient;
|
|
29
34
|
constructor(
|
|
30
35
|
envUrl: string,
|
|
31
36
|
clientId: string,
|
|
@@ -51,7 +56,11 @@ export default class ScalekitClient {
|
|
|
51
56
|
this.domain = new DomainClient(
|
|
52
57
|
this.grpcConnect,
|
|
53
58
|
this.coreClient
|
|
54
|
-
)
|
|
59
|
+
);
|
|
60
|
+
this.directory = new DirectoryClient(
|
|
61
|
+
this.grpcConnect,
|
|
62
|
+
this.coreClient
|
|
63
|
+
);
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
/**
|
|
@@ -150,7 +159,7 @@ export default class ScalekitClient {
|
|
|
150
159
|
* @returns {object} Returns the idp initiated login claims
|
|
151
160
|
*/
|
|
152
161
|
async getIdpInitiatedLoginClaims(idpInitiatedLoginToken: string): Promise<IdpInitiatedLoginClaims> {
|
|
153
|
-
return
|
|
162
|
+
return this.validateToken<IdpInitiatedLoginClaims>(idpInitiatedLoginToken);
|
|
154
163
|
}
|
|
155
164
|
|
|
156
165
|
/**
|
|
@@ -168,6 +177,39 @@ export default class ScalekitClient {
|
|
|
168
177
|
}
|
|
169
178
|
}
|
|
170
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Verifies the payload of the webhook
|
|
182
|
+
*
|
|
183
|
+
* @param {string} secret The secret
|
|
184
|
+
* @param {Record<string, string>} headers The headers
|
|
185
|
+
* @param {string} payload The payload
|
|
186
|
+
* @return {boolean} Returns true if the payload is valid.
|
|
187
|
+
*/
|
|
188
|
+
verifyWebhookPayload(secret: string, headers: Record<string, string>, payload: string): boolean {
|
|
189
|
+
const webhookId = headers['webhook-id'];
|
|
190
|
+
const webhookTimestamp = headers['webhook-timestamp'];
|
|
191
|
+
const webhookSignature = headers['webhook-signature'];
|
|
192
|
+
if (!webhookId || !webhookTimestamp || !webhookSignature) {
|
|
193
|
+
throw new Error("Missing required headers");
|
|
194
|
+
}
|
|
195
|
+
const timestamp = this.verifyTimestamp(webhookTimestamp);
|
|
196
|
+
const data = `${webhookId}.${Math.floor(timestamp.getTime() / 1000)}.${payload}`;
|
|
197
|
+
const secretBytes = Buffer.from(secret.split("_")[1], 'base64');
|
|
198
|
+
const computedSignature = this.computeSignature(secretBytes, data);
|
|
199
|
+
const receivedSignatures = webhookSignature.split(" ");
|
|
200
|
+
for (const versionedSignature of receivedSignatures) {
|
|
201
|
+
const [version, signature] = versionedSignature.split(",");
|
|
202
|
+
if (version !== WEBHOOK_SIGNATURE_VERSION) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (crypto.timingSafeEqual(Buffer.from(signature, 'base64'), Buffer.from(computedSignature, 'base64'))) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
throw new Error("Invalid Signature");
|
|
211
|
+
}
|
|
212
|
+
|
|
171
213
|
/**
|
|
172
214
|
* Validate token
|
|
173
215
|
*
|
|
@@ -186,6 +228,39 @@ export default class ScalekitClient {
|
|
|
186
228
|
throw new Error("Invalid token");
|
|
187
229
|
}
|
|
188
230
|
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Verify the timestamp
|
|
234
|
+
*
|
|
235
|
+
* @param {string} timestampStr The timestamp string
|
|
236
|
+
* @return {Date} Returns the timestamp
|
|
237
|
+
*/
|
|
238
|
+
private verifyTimestamp(timestampStr: string): Date {
|
|
239
|
+
const now = Math.floor(Date.now() / 1000);
|
|
240
|
+
const timestamp = parseInt(timestampStr, 10);
|
|
241
|
+
if (isNaN(timestamp)) {
|
|
242
|
+
throw new Error("Invalid timestamp");
|
|
243
|
+
}
|
|
244
|
+
if (now - timestamp > WEBHOOK_TOLERANCE_IN_SECONDS) {
|
|
245
|
+
throw new Error("Message timestamp too old");
|
|
246
|
+
}
|
|
247
|
+
if (timestamp > now + WEBHOOK_TOLERANCE_IN_SECONDS) {
|
|
248
|
+
throw new Error("Message timestamp too new");
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return new Date(timestamp * 1000);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Compute the signature
|
|
256
|
+
*
|
|
257
|
+
* @param {Buffer} secretBytes The secret bytes
|
|
258
|
+
* @param {string} data The data to be signed
|
|
259
|
+
* @return {string} Returns the signature
|
|
260
|
+
*/
|
|
261
|
+
private computeSignature(secretBytes: Buffer, data: string): string {
|
|
262
|
+
return crypto.createHmac('sha256', secretBytes).update(data).digest('base64');
|
|
263
|
+
}
|
|
189
264
|
}
|
|
190
265
|
|
|
191
266
|
|