@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.
Files changed (36) hide show
  1. package/buf.gen.yaml +2 -1
  2. package/lib/core.js +1 -1
  3. package/lib/directory.d.ts +78 -0
  4. package/lib/directory.js +126 -0
  5. package/lib/directory.js.map +1 -0
  6. package/lib/organization.d.ts +8 -0
  7. package/lib/organization.js +20 -0
  8. package/lib/organization.js.map +1 -1
  9. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.d.ts +118 -0
  10. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js +126 -0
  11. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js.map +1 -0
  12. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.d.ts +960 -0
  13. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js +1429 -0
  14. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js.map +1 -0
  15. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.d.ts +10 -1
  16. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js +9 -0
  17. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js.map +1 -1
  18. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.d.ts +81 -0
  19. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js +113 -1
  20. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js.map +1 -1
  21. package/lib/scalekit.d.ts +27 -1
  22. package/lib/scalekit.js +67 -1
  23. package/lib/scalekit.js.map +1 -1
  24. package/lib/types/organization.d.ts +7 -0
  25. package/lib/types/organization.js +3 -0
  26. package/lib/types/organization.js.map +1 -0
  27. package/package.json +1 -1
  28. package/src/core.ts +1 -1
  29. package/src/directory.ts +173 -0
  30. package/src/organization.ts +24 -1
  31. package/src/pkg/grpc/scalekit/v1/directories/directories_connect.ts +125 -0
  32. package/src/pkg/grpc/scalekit/v1/directories/directories_pb.ts +1838 -0
  33. package/src/pkg/grpc/scalekit/v1/organizations/organizations_connect.ts +10 -1
  34. package/src/pkg/grpc/scalekit/v1/organizations/organizations_pb.ts +155 -0
  35. package/src/scalekit.ts +78 -3
  36. 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 await this.validateToken<IdpInitiatedLoginClaims>(idpInitiatedLoginToken);
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
 
@@ -0,0 +1,8 @@
1
+ export type OrganizationSettings = {
2
+ features: Feature[];
3
+ }
4
+
5
+ export type Feature = {
6
+ name: string;
7
+ enabled: boolean;
8
+ }