@scalekit-sdk/node 2.2.0-beta.1 → 2.2.1

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 (226) hide show
  1. package/README.md +5 -5
  2. package/{reference.md → REFERENCE.md} +530 -748
  3. package/lib/auth.d.ts +9 -6
  4. package/lib/auth.js +4 -20
  5. package/lib/auth.js.map +1 -1
  6. package/lib/connect.d.ts +3 -3
  7. package/lib/connect.js +1 -2
  8. package/lib/connect.js.map +1 -1
  9. package/lib/connection.d.ts +2 -2
  10. package/lib/connection.js +4 -4
  11. package/lib/connection.js.map +1 -1
  12. package/lib/core.js +2 -2
  13. package/lib/core.js.map +1 -1
  14. package/lib/directory.d.ts +2 -2
  15. package/lib/directory.js +7 -7
  16. package/lib/directory.js.map +1 -1
  17. package/lib/domain.d.ts +6 -5
  18. package/lib/domain.js +4 -5
  19. package/lib/domain.js.map +1 -1
  20. package/lib/errors/base-exception.d.ts +1 -1
  21. package/lib/errors/base-exception.js +1 -1
  22. package/lib/errors/base-exception.js.map +1 -1
  23. package/lib/organization.d.ts +10 -9
  24. package/lib/organization.js +11 -9
  25. package/lib/organization.js.map +1 -1
  26. package/lib/passwordless.d.ts +2 -2
  27. package/lib/passwordless.js +8 -7
  28. package/lib/passwordless.js.map +1 -1
  29. package/lib/permission.d.ts +6 -5
  30. package/lib/permission.js +10 -11
  31. package/lib/permission.js.map +1 -1
  32. package/lib/pkg/grpc/buf/validate/validate_pb.d.ts +7 -0
  33. package/lib/pkg/grpc/buf/validate/validate_pb.js +25 -0
  34. package/lib/pkg/grpc/buf/validate/validate_pb.js.map +1 -0
  35. package/lib/pkg/grpc/google/api/annotations_pb.d.ts +7 -0
  36. package/lib/pkg/grpc/google/api/annotations_pb.js +25 -0
  37. package/lib/pkg/grpc/google/api/annotations_pb.js.map +1 -0
  38. package/lib/pkg/grpc/google/api/field_behavior_pb.d.ts +7 -0
  39. package/lib/pkg/grpc/google/api/field_behavior_pb.js +25 -0
  40. package/lib/pkg/grpc/google/api/field_behavior_pb.js.map +1 -0
  41. package/lib/pkg/grpc/google/api/visibility_pb.d.ts +7 -0
  42. package/lib/pkg/grpc/google/api/visibility_pb.js +25 -0
  43. package/lib/pkg/grpc/google/api/visibility_pb.js.map +1 -0
  44. package/lib/pkg/grpc/protoc-gen-openapiv2/options/annotations_pb.d.ts +7 -0
  45. package/lib/pkg/grpc/protoc-gen-openapiv2/options/annotations_pb.js +25 -0
  46. package/lib/pkg/grpc/protoc-gen-openapiv2/options/annotations_pb.js.map +1 -0
  47. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_pb.d.ts +48 -42
  48. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_pb.js +27 -263
  49. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_pb.js.map +1 -1
  50. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.d.ts +371 -325
  51. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.js +132 -835
  52. package/lib/pkg/grpc/scalekit/v1/auth/auth_pb.js.map +1 -1
  53. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_pb.d.ts +113 -87
  54. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_pb.js +45 -201
  55. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_pb.js.map +1 -1
  56. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.d.ts +262 -265
  57. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.js +92 -938
  58. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_pb.js.map +1 -1
  59. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.d.ts +162 -157
  60. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js +42 -313
  61. package/lib/pkg/grpc/scalekit/v1/commons/commons_pb.js.map +1 -1
  62. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.d.ts +1488 -1459
  63. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js +353 -2362
  64. package/lib/pkg/grpc/scalekit/v1/connections/connections_pb.js.map +1 -1
  65. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.d.ts +520 -483
  66. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js +224 -1555
  67. package/lib/pkg/grpc/scalekit/v1/directories/directories_pb.js.map +1 -1
  68. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.d.ts +219 -191
  69. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js +96 -553
  70. package/lib/pkg/grpc/scalekit/v1/domains/domains_pb.js.map +1 -1
  71. package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.d.ts +76 -102
  72. package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.js +37 -393
  73. package/lib/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.js.map +1 -1
  74. package/lib/pkg/grpc/scalekit/v1/options/options_pb.d.ts +36 -26
  75. package/lib/pkg/grpc/scalekit/v1/options/options_pb.js +20 -69
  76. package/lib/pkg/grpc/scalekit/v1/options/options_pb.js.map +1 -1
  77. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.d.ts +447 -400
  78. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js +163 -1238
  79. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_pb.js.map +1 -1
  80. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.d.ts +622 -556
  81. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.js +201 -1718
  82. package/lib/pkg/grpc/scalekit/v1/roles/roles_pb.js.map +1 -1
  83. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_pb.d.ts +135 -132
  84. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_pb.js +55 -518
  85. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_pb.js.map +1 -1
  86. package/lib/pkg/grpc/scalekit/v1/users/users_pb.d.ts +445 -413
  87. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js +142 -1490
  88. package/lib/pkg/grpc/scalekit/v1/users/users_pb.js.map +1 -1
  89. package/lib/role.d.ts +8 -7
  90. package/lib/role.js +14 -14
  91. package/lib/role.js.map +1 -1
  92. package/lib/scalekit.d.ts +0 -4
  93. package/lib/scalekit.js +0 -4
  94. package/lib/scalekit.js.map +1 -1
  95. package/lib/session.js +15 -24
  96. package/lib/session.js.map +1 -1
  97. package/lib/user.d.ts +6 -5
  98. package/lib/user.js +17 -20
  99. package/lib/user.js.map +1 -1
  100. package/lib/webauthn.js +6 -5
  101. package/lib/webauthn.js.map +1 -1
  102. package/package.json +12 -10
  103. package/.github/dependabot.yml +0 -10
  104. package/.nvmrc +0 -1
  105. package/buf.gen.yaml +0 -24
  106. package/jest.config.js +0 -15
  107. package/lib/connected-accounts.d.ts +0 -119
  108. package/lib/connected-accounts.js +0 -241
  109. package/lib/connected-accounts.js.map +0 -1
  110. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_connect.d.ts +0 -19
  111. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_connect.js +0 -27
  112. package/lib/pkg/grpc/scalekit/v1/auditlogs/auditlogs_connect.js.map +0 -1
  113. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.d.ts +0 -118
  114. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.js +0 -126
  115. package/lib/pkg/grpc/scalekit/v1/auth/auth_connect.js.map +0 -1
  116. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_connect.d.ts +0 -37
  117. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_connect.js +0 -45
  118. package/lib/pkg/grpc/scalekit/v1/auth/passwordless_connect.js.map +0 -1
  119. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.d.ts +0 -82
  120. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.js +0 -90
  121. package/lib/pkg/grpc/scalekit/v1/auth/webauthn_connect.js.map +0 -1
  122. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_connect.d.ts +0 -87
  123. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_connect.js +0 -95
  124. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_connect.js.map +0 -1
  125. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb.d.ts +0 -718
  126. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb.js +0 -893
  127. package/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb.js.map +0 -1
  128. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.d.ts +0 -172
  129. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js +0 -180
  130. package/lib/pkg/grpc/scalekit/v1/connections/connections_connect.js.map +0 -1
  131. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.d.ts +0 -154
  132. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js +0 -162
  133. package/lib/pkg/grpc/scalekit/v1/directories/directories_connect.js.map +0 -1
  134. package/lib/pkg/grpc/scalekit/v1/domains/domains_connect.d.ts +0 -73
  135. package/lib/pkg/grpc/scalekit/v1/domains/domains_connect.js +0 -81
  136. package/lib/pkg/grpc/scalekit/v1/domains/domains_connect.js.map +0 -1
  137. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.d.ts +0 -171
  138. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js +0 -179
  139. package/lib/pkg/grpc/scalekit/v1/organizations/organizations_connect.js.map +0 -1
  140. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.d.ts +0 -250
  141. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.js +0 -258
  142. package/lib/pkg/grpc/scalekit/v1/roles/roles_connect.js.map +0 -1
  143. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_connect.d.ts +0 -46
  144. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_connect.js +0 -54
  145. package/lib/pkg/grpc/scalekit/v1/sessions/sessions_connect.js.map +0 -1
  146. package/lib/pkg/grpc/scalekit/v1/tools/tools_connect.d.ts +0 -75
  147. package/lib/pkg/grpc/scalekit/v1/tools/tools_connect.js +0 -83
  148. package/lib/pkg/grpc/scalekit/v1/tools/tools_connect.js.map +0 -1
  149. package/lib/pkg/grpc/scalekit/v1/tools/tools_pb.d.ts +0 -431
  150. package/lib/pkg/grpc/scalekit/v1/tools/tools_pb.js +0 -627
  151. package/lib/pkg/grpc/scalekit/v1/tools/tools_pb.js.map +0 -1
  152. package/lib/pkg/grpc/scalekit/v1/users/users_connect.d.ts +0 -173
  153. package/lib/pkg/grpc/scalekit/v1/users/users_connect.js +0 -181
  154. package/lib/pkg/grpc/scalekit/v1/users/users_connect.js.map +0 -1
  155. package/lib/tools.d.ts +0 -75
  156. package/lib/tools.js +0 -127
  157. package/lib/tools.js.map +0 -1
  158. package/src/auth.ts +0 -99
  159. package/src/connect.ts +0 -33
  160. package/src/connected-accounts.ts +0 -358
  161. package/src/connection.ts +0 -267
  162. package/src/constants/user.ts +0 -22
  163. package/src/core.ts +0 -139
  164. package/src/directory.ts +0 -431
  165. package/src/domain.ts +0 -272
  166. package/src/errors/base-exception.ts +0 -262
  167. package/src/errors/index.ts +0 -3
  168. package/src/errors/specific-exceptions.ts +0 -88
  169. package/src/index.ts +0 -10
  170. package/src/organization.ts +0 -568
  171. package/src/passwordless.ts +0 -138
  172. package/src/permission.ts +0 -310
  173. package/src/pkg/grpc/scalekit/v1/auditlogs/auditlogs_connect.ts +0 -26
  174. package/src/pkg/grpc/scalekit/v1/auditlogs/auditlogs_pb.ts +0 -342
  175. package/src/pkg/grpc/scalekit/v1/auth/auth_connect.ts +0 -125
  176. package/src/pkg/grpc/scalekit/v1/auth/auth_pb.ts +0 -1213
  177. package/src/pkg/grpc/scalekit/v1/auth/passwordless_connect.ts +0 -44
  178. package/src/pkg/grpc/scalekit/v1/auth/passwordless_pb.ts +0 -336
  179. package/src/pkg/grpc/scalekit/v1/auth/webauthn_connect.ts +0 -89
  180. package/src/pkg/grpc/scalekit/v1/auth/webauthn_pb.ts +0 -1263
  181. package/src/pkg/grpc/scalekit/v1/commons/commons_pb.ts +0 -573
  182. package/src/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_connect.ts +0 -94
  183. package/src/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb.ts +0 -1294
  184. package/src/pkg/grpc/scalekit/v1/connections/connections_connect.ts +0 -179
  185. package/src/pkg/grpc/scalekit/v1/connections/connections_pb.ts +0 -3846
  186. package/src/pkg/grpc/scalekit/v1/directories/directories_connect.ts +0 -161
  187. package/src/pkg/grpc/scalekit/v1/directories/directories_pb.ts +0 -2119
  188. package/src/pkg/grpc/scalekit/v1/domains/domains_connect.ts +0 -80
  189. package/src/pkg/grpc/scalekit/v1/domains/domains_pb.ts +0 -855
  190. package/src/pkg/grpc/scalekit/v1/errdetails/errdetails_pb.ts +0 -524
  191. package/src/pkg/grpc/scalekit/v1/options/options_pb.ts +0 -230
  192. package/src/pkg/grpc/scalekit/v1/organizations/organizations_connect.ts +0 -178
  193. package/src/pkg/grpc/scalekit/v1/organizations/organizations_pb.ts +0 -1766
  194. package/src/pkg/grpc/scalekit/v1/roles/roles_connect.ts +0 -257
  195. package/src/pkg/grpc/scalekit/v1/roles/roles_pb.ts +0 -2395
  196. package/src/pkg/grpc/scalekit/v1/sessions/sessions_connect.ts +0 -53
  197. package/src/pkg/grpc/scalekit/v1/sessions/sessions_pb.ts +0 -749
  198. package/src/pkg/grpc/scalekit/v1/tools/tools_connect.ts +0 -82
  199. package/src/pkg/grpc/scalekit/v1/tools/tools_pb.ts +0 -847
  200. package/src/pkg/grpc/scalekit/v1/users/users_connect.ts +0 -180
  201. package/src/pkg/grpc/scalekit/v1/users/users_pb.ts +0 -2151
  202. package/src/role.ts +0 -461
  203. package/src/scalekit.ts +0 -809
  204. package/src/session.ts +0 -337
  205. package/src/tools.ts +0 -166
  206. package/src/types/auth.ts +0 -73
  207. package/src/types/organization.ts +0 -12
  208. package/src/types/scalekit.ts +0 -50
  209. package/src/types/user.ts +0 -21
  210. package/src/user.ts +0 -825
  211. package/src/webauthn.ts +0 -98
  212. package/tests/README.md +0 -25
  213. package/tests/connected-accounts.test.ts +0 -472
  214. package/tests/connection.test.ts +0 -42
  215. package/tests/directory.test.ts +0 -46
  216. package/tests/domain.test.ts +0 -293
  217. package/tests/organization.test.ts +0 -81
  218. package/tests/passwordless.test.ts +0 -108
  219. package/tests/permission.test.ts +0 -399
  220. package/tests/role.test.ts +0 -323
  221. package/tests/scalekit.test.ts +0 -104
  222. package/tests/setup.ts +0 -34
  223. package/tests/tools.test.ts +0 -239
  224. package/tests/users.test.ts +0 -168
  225. package/tests/utils/test-data.ts +0 -481
  226. package/tsconfig.json +0 -19
package/src/scalekit.ts DELETED
@@ -1,809 +0,0 @@
1
- import crypto from 'crypto';
2
- import * as jose from 'jose';
3
- import QueryString from 'qs';
4
- import GrpcConnect from './connect';
5
- import ConnectionClient from './connection';
6
- import { IdTokenClaimToUserMap } from './constants/user';
7
- import CoreClient from './core';
8
- import ToolsClient from './tools';
9
- import ConnectedAccountsClient from './connected-accounts';
10
- import DirectoryClient from './directory';
11
- import DomainClient from './domain';
12
- import AuthClient from './auth';
13
- import OrganizationClient from './organization';
14
- import PasswordlessClient from './passwordless';
15
- import UserClient from './user';
16
- import SessionClient from './session';
17
- import RoleClient from './role';
18
- import PermissionClient from './permission';
19
- import WebAuthnClient from './webauthn';
20
- import { IdpInitiatedLoginClaims, IdTokenClaim, User } from './types/auth';
21
- import { AuthenticationOptions, AuthenticationResponse, AuthorizationUrlOptions, GrantType, LogoutUrlOptions, RefreshTokenResponse ,TokenValidationOptions } from './types/scalekit';
22
- import { WebhookVerificationError, ScalekitValidateTokenFailureException } from './errors/base-exception';
23
-
24
- const authorizeEndpoint = "oauth/authorize";
25
- const logoutEndpoint = "oidc/logout";
26
- const WEBHOOK_TOLERANCE_IN_SECONDS = 5 * 60; // 5 minutes
27
- const WEBHOOK_SIGNATURE_VERSION = "v1";
28
-
29
- /**
30
- * Main Scalekit SDK client for interacting with all Scalekit API endpoints.
31
- *
32
- * TIP: You can use it as a singleton object - that is you can initialize it just once and use the same client variable wherever required.
33
- *
34
- * This is the primary entry point for interacting with Scalekit's authentication services,
35
- * including SSO, SCIM, user management, roles, permissions, and passwordless authentication.
36
- *
37
- * You can find the Environment URL, Client ID and Client Secret in Scalekit Dashboard -> Developers (Settings) -> API Credentials
38
- *
39
- * @param {string} envUrl - The Scalekit environment URL (e.g., "https://yourorg.scalekit.com" or your configured custom domain like "https://auth.yourapp.ai")
40
- * @param {string} clientId - Your Scalekit client ID from the Scalekit Dashboard
41
- * @param {string} clientSecret - Your Scalekit client secret from the Scalekit Dashboard
42
- *
43
- * @example
44
- * // Initialize the Scalekit client
45
- * import { ScalekitClient } from '@scalekit-sdk/node';
46
- *
47
- * const scalekitClient = new ScalekitClient(
48
- * process.env.SCALEKIT_ENV_URL,
49
- * process.env.SCALEKIT_CLIENT_ID,
50
- * process.env.SCALEKIT_CLIENT_SECRET
51
- * );
52
- *
53
- * // Access various client modules
54
- * const organizations = await scalekitClient.organization.listOrganization();
55
- * const users = await scalekitClient.user.listUsers();
56
- *
57
- * @see {@link https://docs.scalekit.com/apis/ | Scalekit API Documentation}
58
- */
59
- export default class ScalekitClient {
60
- private readonly coreClient: CoreClient;
61
- private readonly grpcConnect: GrpcConnect;
62
- readonly organization: OrganizationClient;
63
- readonly connection: ConnectionClient;
64
- readonly domain: DomainClient;
65
- readonly tools: ToolsClient;
66
- readonly connectedAccounts: ConnectedAccountsClient;
67
- readonly directory: DirectoryClient;
68
- readonly passwordless: PasswordlessClient;
69
- readonly user: UserClient;
70
- readonly session: SessionClient;
71
- readonly role: RoleClient;
72
- readonly permission: PermissionClient;
73
- readonly auth: AuthClient;
74
- readonly webauthn: WebAuthnClient;
75
- constructor(
76
- envUrl: string,
77
- clientId: string,
78
- clientSecret: string
79
- ) {
80
- this.coreClient = new CoreClient(
81
- envUrl,
82
- clientId,
83
- clientSecret
84
- );
85
- this.grpcConnect = new GrpcConnect(
86
- this.coreClient
87
- );
88
-
89
- this.organization = new OrganizationClient(
90
- this.grpcConnect,
91
- this.coreClient
92
- );
93
- this.connection = new ConnectionClient(this.grpcConnect, this.coreClient);
94
- this.domain = new DomainClient(this.grpcConnect, this.coreClient);
95
- this.tools = new ToolsClient(this.grpcConnect, this.coreClient);
96
- this.connectedAccounts = new ConnectedAccountsClient(
97
- this.grpcConnect,
98
- this.coreClient
99
- );
100
- this.directory = new DirectoryClient(this.grpcConnect, this.coreClient);
101
- this.passwordless = new PasswordlessClient(
102
- this.grpcConnect,
103
- this.coreClient
104
- );
105
- this.user = new UserClient(
106
- this.grpcConnect,
107
- this.coreClient
108
- );
109
- this.session = new SessionClient(
110
- this.grpcConnect,
111
- this.coreClient
112
- );
113
- this.role = new RoleClient(
114
- this.grpcConnect,
115
- this.coreClient
116
- );
117
- this.permission = new PermissionClient(
118
- this.grpcConnect,
119
- this.coreClient
120
- );
121
- this.auth = new AuthClient(
122
- this.grpcConnect,
123
- this.coreClient
124
- );
125
- this.webauthn = new WebAuthnClient(
126
- this.grpcConnect,
127
- this.coreClient
128
- );
129
- }
130
-
131
- /**
132
- * Utility method to generate the OAuth 2.0 authorization URL to initiate the SSO authentication flow.
133
- *
134
- * This method doesn't make any network calls but instead generates a fully formed Authorization URL
135
- * as a string that you can redirect your users to initiate authentication.
136
- *
137
- * @param {string} redirectUri - The URL where users will be redirected after authentication.
138
- * Must match one of the redirect URIs configured in your Scalekit dashboard.
139
- * @param {AuthorizationUrlOptions} [options] - Optional configuration for the authorization request
140
- * @param {string[]} [options.scopes=['openid', 'profile', 'email']] - OAuth scopes to request. Default includes openid, profile, and email.
141
- * @param {string} [options.state] - Opaque value to maintain state between request and callback. Used to prevent CSRF attacks.
142
- * @param {string} [options.nonce] - String value used to associate a client session with an ID Token.
143
- * @param {string} [options.loginHint] - Hint to the authorization server about the login identifier the user might use (e.g., email address).
144
- * @param {string} [options.domainHint] - Domain hint to identify which organization's IdP to use for authentication.
145
- * @param {string} [options.connectionId] - Specific SSO connection ID to use for authentication.
146
- * @param {string} [options.organizationId] - Organization ID to authenticate against.
147
- * @param {string} [options.provider] - Social login provider (e.g., 'google', 'github', 'microsoft').
148
- * @param {string} [options.codeChallenge] - PKCE code challenge for enhanced security in public clients.
149
- * @param {string} [options.codeChallengeMethod] - Method used to generate the code challenge (we support only 'S256').
150
- * @param {string} [options.prompt] - Controls the authorization server's authentication behavior (e.g., 'login', 'consent', 'create').
151
- *
152
- * @returns {string} The complete authorization URL to redirect the user to
153
- *
154
- * @example
155
- * // Initiate Enterprise SSO authentication for a given org_id
156
- * const authUrl = scalekitClient.getAuthorizationUrl(
157
- * 'https://yourapp.com/auth/callback',
158
- * {
159
- * state: 'random-state-value',
160
- * organizationId: 'org_123456'
161
- * }
162
- * );
163
- * // Redirect user to authUrl
164
- *
165
- * @example
166
- * // Initiate Enterprise SSO authentication for a specific connection id
167
- * // optionally, pass the loginhint to the 3rd party identity provider.
168
- * const authUrl = scalekitClient.getAuthorizationUrl(
169
- * 'https://yourapp.com/auth/callback',
170
- * {
171
- * connectionId: 'conn_abc123',
172
- * loginHint: 'user@company.com'
173
- * }
174
- * );
175
- *
176
- * @example
177
- * // Social login
178
- * const authUrl = scalekitClient.getAuthorizationUrl(
179
- * 'https://yourapp.com/auth/callback',
180
- * {
181
- * provider: 'google',
182
- * state: 'random-state'
183
- * }
184
- * );
185
- *
186
- * @example
187
- * // PKCE flow for public clients
188
- * const authUrl = scalekitClient.getAuthorizationUrl(
189
- * 'https://yourapp.com/auth/callback',
190
- * {
191
- * codeChallenge: 'your-code-challenge',
192
- * codeChallengeMethod: 'S256',
193
- * organizationId: 'org_123456'
194
- * }
195
- * );
196
- *
197
- * @see {@link https://docs.scalekit.com/apis/#tag/api%20auth | Authentication API Documentation}
198
- * @see {@link authenticateWithCode} - Use this method to exchange the authorization code for tokens
199
- */
200
- getAuthorizationUrl(
201
- redirectUri: string,
202
- options?: AuthorizationUrlOptions
203
- ): string {
204
- const defaultOptions: AuthorizationUrlOptions = {
205
- scopes: ["openid", "profile", "email"],
206
- };
207
- options = {
208
- ...defaultOptions,
209
- ...options,
210
- };
211
- const qs = QueryString.stringify({
212
- response_type: "code",
213
- client_id: this.coreClient.clientId,
214
- redirect_uri: redirectUri,
215
- scope: options.scopes?.join(" "),
216
- ...(options.state && { state: options.state }),
217
- ...(options.nonce && { nonce: options.nonce }),
218
- ...(options.loginHint && { login_hint: options.loginHint }),
219
- ...(options.domainHint && { domain_hint: options.domainHint }),
220
- ...(options.domainHint && { domain: options.domainHint }),
221
- ...(options.connectionId && { connection_id: options.connectionId }),
222
- ...(options.organizationId && {
223
- organization_id: options.organizationId,
224
- }),
225
- ...(options.codeChallenge && { code_challenge: options.codeChallenge }),
226
- ...(options.codeChallengeMethod && {
227
- code_challenge_method: options.codeChallengeMethod,
228
- }),
229
- ...(options.provider && { provider: options.provider }),
230
- ...(options.prompt && { prompt: options.prompt }),
231
- });
232
-
233
- return `${this.coreClient.envUrl}/${authorizeEndpoint}?${qs}`;
234
- }
235
-
236
- /**
237
- * Exchanges an authorization code for access tokens and user information.
238
- *
239
- * This method completes the OAuth 2.0 authorization code flow by exchanging the code
240
- * received in the callback for access tokens, ID tokens, and user profile information.
241
- * Call this method in your redirect URI handler after receiving the authorization code.
242
- *
243
- * @param {string} code - The authorization code received in the callback URL after user authentication
244
- * @param {string} redirectUri - The same redirect URI used in getAuthorizationUrl(). Must match exactly.
245
- * @param {AuthenticationOptions} [options] - Optional authentication configuration
246
- * @param {string} [options.codeVerifier] - PKCE code verifier to validate the code challenge (required if PKCE was used)
247
- *
248
- * @returns {Promise<AuthenticationResponse>} Authentication response containing:
249
- * - user: User profile information (email, name, organization, etc.)
250
- * - idToken: JWT ID token containing user claims
251
- * - accessToken: Access token for API authorization
252
- * - expiresIn: Token expiration time in seconds
253
- * - refreshToken: Refresh token for obtaining new access tokens
254
- *
255
- * @throws {Error} When the authorization code is invalid, expired, or already used
256
- * @throws {Error} When the redirect URI doesn't match the one used in authorization
257
- * @throws {Error} When PKCE code verifier is invalid or missing
258
- *
259
- * @example
260
- * // Basic code exchange (server-side flow)
261
- * app.get('/auth/callback', async (req, res) => {
262
- * const { code } = req.query;
263
- *
264
- * try {
265
- * const result = await scalekitClient.authenticateWithCode(
266
- * code,
267
- * 'https://yourapp.com/auth/callback'
268
- * );
269
- *
270
- * // Store tokens securely
271
- * req.session.accessToken = result.accessToken;
272
- * req.session.user = result.user;
273
- *
274
- * res.redirect('/dashboard');
275
- * } catch (error) {
276
- * console.error('Authentication failed:', error);
277
- * res.redirect('/login?error=auth_failed');
278
- * }
279
- * });
280
- *
281
- * @example
282
- * // PKCE flow (for public clients)
283
- * app.get('/auth/callback', async (req, res) => {
284
- * const { code } = req.query;
285
- * const codeVerifier = req.session.codeVerifier; // Stored during authorization
286
- *
287
- * const result = await scalekitClient.authenticateWithCode(
288
- * code,
289
- * 'https://yourapp.com/auth/callback',
290
- * { codeVerifier }
291
- * );
292
- *
293
- * // Use result.user, result.accessToken, etc.
294
- * });
295
- *
296
- * @see {@link getAuthorizationUrl} - Generate the authorization URL first
297
- * @see {@link validateAccessToken} - Validate tokens in subsequent requests
298
- */
299
- async authenticateWithCode(
300
- code: string,
301
- redirectUri: string,
302
- options?: AuthenticationOptions
303
- ): Promise<AuthenticationResponse> {
304
- const res = await this.coreClient.authenticate(
305
- QueryString.stringify({
306
- code: code,
307
- redirect_uri: redirectUri,
308
- grant_type: GrantType.AuthorizationCode,
309
- client_id: this.coreClient.clientId,
310
- client_secret: this.coreClient.clientSecret,
311
- ...(options?.codeVerifier && { code_verifier: options.codeVerifier }),
312
- })
313
- );
314
- const { id_token, access_token, expires_in, refresh_token } = res.data;
315
- const claims = jose.decodeJwt<IdTokenClaim>(id_token);
316
- const user = <User>{};
317
- for (const [k, v] of Object.entries(claims)) {
318
- if (IdTokenClaimToUserMap[k]) {
319
- user[IdTokenClaimToUserMap[k]] = v;
320
- }
321
- }
322
-
323
- return {
324
- user,
325
- idToken: id_token,
326
- accessToken: access_token,
327
- expiresIn: expires_in,
328
- refreshToken: refresh_token,
329
- };
330
- }
331
-
332
- /**
333
- * Extracts and validates claims from an IdP-initiated login token.
334
- *
335
- * Use this method when handling IdP-initiated SSO flows, where the authentication is
336
- * initiated from the identity provider's portal rather than your application. This validates
337
- * the token and returns the necessary information to initiate a new SP Initiated SSO workflow.
338
- *
339
- * @param {string} idpInitiatedLoginToken - The token received in the 'idp_initiated_login' query parameter
340
- * @param {TokenValidationOptions} [options] - Optional token validation configuration
341
- * @param {string} [options.issuer] - Expected token issuer for validation
342
- * @param {string} [options.audience] - Expected token audience for validation
343
- *
344
- * @returns {Promise<IdpInitiatedLoginClaims>} Claims containing:
345
- * - connection_id: The SSO connection identifier
346
- * - organization_id: The organization identifier
347
- * - login_hint: User's email or login identifier
348
- * - relay_state: Optional state parameter from the IdP
349
- *
350
- * @throws {ScalekitValidateTokenFailureException} When token validation fails
351
- *
352
- * @example
353
- * // Handle IdP-initiated login
354
- * app.get('/auth/callback', async (req, res) => {
355
- * const { idp_initiated_login } = req.query;
356
- *
357
- * if (idp_initiated_login) {
358
- * try {
359
- * const claims = await scalekitClient.getIdpInitiatedLoginClaims(idp_initiated_login);
360
- *
361
- * // Redirect to authorization URL with the claims
362
- * const authUrl = scalekitClient.getAuthorizationUrl(
363
- * 'https://yourapp.com/auth/callback',
364
- * {
365
- * connectionId: claims.connection_id,
366
- * organizationId: claims.organization_id,
367
- * loginHint: claims.login_hint,
368
- * ...(claims.relay_state && { state: claims.relay_state })
369
- * }
370
- * );
371
- *
372
- * return res.redirect(authUrl);
373
- * } catch (error) {
374
- * console.error('IdP-initiated login failed:', error);
375
- * return res.redirect('/login?error=idp_login_failed');
376
- * }
377
- * }
378
- * // Handle normal callback flow...
379
- * });
380
- *
381
- * @see {@link https://docs.scalekit.com/sso/guides/idp-init-sso/ | IdP-Initiated SSO Documentation}
382
- * @see {@link getAuthorizationUrl} - Use the claims to construct the authorization URL
383
- */
384
- async getIdpInitiatedLoginClaims(
385
- idpInitiatedLoginToken: string,
386
- options?: TokenValidationOptions
387
- ): Promise<IdpInitiatedLoginClaims> {
388
- return this.validateToken<IdpInitiatedLoginClaims>(
389
- idpInitiatedLoginToken,
390
- options
391
- );
392
- }
393
-
394
- /**
395
- * Validates the access token and returns a boolean result.
396
- *
397
- * @param {string} token The token to be validated.
398
- * @param {TokenValidationOptions} options Optional validation options for issuer, audience, and scopes
399
- * @return {Promise<boolean>} Returns true if the token is valid, false otherwise.
400
- */
401
- async validateAccessToken(
402
- token: string,
403
- options?: TokenValidationOptions
404
- ): Promise<boolean> {
405
- try {
406
- await this.validateToken(token, options);
407
- return true;
408
- } catch (_) {
409
- return false;
410
- }
411
- }
412
-
413
- /**
414
- * Returns the logout URL that can be used to log out the user.
415
- * @param {LogoutUrlOptions} options Logout URL options
416
- * @param {string} options.idTokenHint The ID Token previously issued to the client
417
- * @param {string} options.postLogoutRedirectUri URL to redirect after logout
418
- * @param {string} options.state Opaque value to maintain state between request and callback
419
- * @returns {string} The logout URL
420
- *
421
- * @example
422
- * const scalekit = new Scalekit(envUrl, clientId, clientSecret);
423
- * const logoutUrl = scalekit.getLogoutUrl({
424
- * postLogoutRedirectUri: 'https://example.com',
425
- * state: 'some-state'
426
- * });
427
- */
428
- getLogoutUrl(options?: LogoutUrlOptions): string {
429
- const qs = QueryString.stringify({
430
- ...(options?.idTokenHint && { id_token_hint: options.idTokenHint }),
431
- ...(options?.postLogoutRedirectUri && {
432
- post_logout_redirect_uri: options.postLogoutRedirectUri,
433
- }),
434
- ...(options?.state && { state: options.state }),
435
- });
436
-
437
- return `${this.coreClient.envUrl}/${logoutEndpoint}${qs ? `?${qs}` : ""}`;
438
- }
439
-
440
- /**
441
- * Verifies the authenticity and integrity of webhook payloads from Scalekit.
442
- *
443
- * Use this method to validate webhook requests from Scalekit by verifying the HMAC signature.
444
- * This ensures the webhook was sent by Scalekit and hasn't been tampered with. The method
445
- * checks the signature and timestamp to prevent replay attacks (5-minute tolerance window).
446
- *
447
- * @param {string} secret - Your webhook signing secret from the Scalekit dashboard (format: 'whsec_...')
448
- * @param {Record<string, string>} headers - The HTTP headers from the webhook request
449
- * @param {string} payload - The raw webhook request body as a string
450
- *
451
- * @returns {boolean} Returns true if the webhook signature is valid
452
- *
453
- * @throws {WebhookVerificationError} When required headers are missing
454
- * @throws {WebhookVerificationError} When the secret format is invalid
455
- * @throws {WebhookVerificationError} When the signature doesn't match
456
- * @throws {WebhookVerificationError} When the timestamp is too old (>5 minutes) or in the future
457
- *
458
- * @example
459
- * // Express.js webhook handler
460
- * app.post('/webhooks/scalekit', express.raw({ type: 'application/json' }), (req, res) => {
461
- * const secret = process.env.SCALEKIT_WEBHOOK_SECRET;
462
- * const headers = req.headers;
463
- * const payload = req.body.toString();
464
- *
465
- * try {
466
- * const isValid = scalekitClient.verifyWebhookPayload(secret, headers, payload);
467
- *
468
- * if (isValid) {
469
- * const event = JSON.parse(payload);
470
- *
471
- * // Process the webhook event
472
- * switch (event.type) {
473
- * case 'user.created':
474
- * console.log('New user created:', event.data);
475
- * break;
476
- * case 'connection.enabled':
477
- * console.log('Connection enabled:', event.data);
478
- * break;
479
- * }
480
- *
481
- * res.status(200).send('Webhook received');
482
- * }
483
- * } catch (error) {
484
- * console.error('Webhook verification failed:', error);
485
- * res.status(400).send('Invalid webhook signature');
486
- * }
487
- * });
488
- *
489
- * @see {@link https://docs.scalekit.com/reference/webhooks/overview/ | Webhook Documentation}
490
- * @see {@link verifyInterceptorPayload} - Similar method for interceptor payloads
491
- */
492
- verifyWebhookPayload(
493
- secret: string,
494
- headers: Record<string, string>,
495
- payload: string
496
- ): boolean {
497
- const webhookId = headers["webhook-id"];
498
- const webhookTimestamp = headers["webhook-timestamp"];
499
- const webhookSignature = headers["webhook-signature"];
500
-
501
- return this.verifyPayloadSignature(
502
- secret,
503
- webhookId,
504
- webhookTimestamp,
505
- webhookSignature,
506
- payload
507
- );
508
- }
509
-
510
- /**
511
- * Verifies the authenticity and integrity of interceptor payloads from Scalekit.
512
- *
513
- * Use this method to validate HTTP interceptor requests from Scalekit by verifying the HMAC signature.
514
- * This ensures the interceptor payload was sent by Scalekit and hasn't been tampered with. The method
515
- * checks the signature and timestamp to prevent replay attacks (5-minute tolerance window)
516
- *
517
- * @param {string} secret Your interceptor signing secret that you can copy from Scalekit Dashboard
518
- * @param {Record<string, string>} headers The HTTP headers from the interceptor request
519
- * @param {string} payload The raw interceptor request body as a string
520
- * @return {boolean} Returns true if the interceptor payload is valid.
521
- */
522
- verifyInterceptorPayload(
523
- secret: string,
524
- headers: Record<string, string>,
525
- payload: string
526
- ): boolean {
527
- const interceptorId = headers["interceptor-id"];
528
- const interceptorTimestamp = headers["interceptor-timestamp"];
529
- const interceptorSignature = headers["interceptor-signature"];
530
-
531
- return this.verifyPayloadSignature(
532
- secret,
533
- interceptorId,
534
- interceptorTimestamp,
535
- interceptorSignature,
536
- payload
537
- );
538
- }
539
-
540
- /**
541
- * Common payload signature verification logic
542
- *
543
- * @param {string} secret The secret
544
- * @param {string} id The webhook/interceptor id
545
- * @param {string} timestamp The timestamp
546
- * @param {string} signature The signature
547
- * @param {string} payload The payload
548
- * @return {boolean} Returns true if the payload signature is valid.
549
- */
550
- private verifyPayloadSignature(
551
- secret: string,
552
- id: string,
553
- timestamp: string,
554
- signature: string,
555
- payload: string
556
- ): boolean {
557
- if (!id || !timestamp || !signature) {
558
- throw new WebhookVerificationError("Missing required headers");
559
- }
560
-
561
- const secretParts = secret.split("_");
562
- if (secretParts.length < 2) {
563
- throw new WebhookVerificationError("Invalid secret");
564
- }
565
-
566
- try {
567
- const timestampDate = this.verifyTimestamp(timestamp);
568
- const data = `${id}.${Math.floor(
569
- timestampDate.getTime() / 1000
570
- )}.${payload}`;
571
- const secretBytes = Buffer.from(secretParts[1], "base64");
572
- const computedSignature = this.computeSignature(secretBytes, data);
573
- const receivedSignatures = signature.split(" ");
574
-
575
- for (const versionedSignature of receivedSignatures) {
576
- const [version, receivedSignature] = versionedSignature.split(",");
577
- if (version !== WEBHOOK_SIGNATURE_VERSION) {
578
- continue;
579
- }
580
- if (
581
- crypto.timingSafeEqual(
582
- Buffer.from(receivedSignature, "base64"),
583
- Buffer.from(computedSignature, "base64")
584
- )
585
- ) {
586
- return true;
587
- }
588
- }
589
-
590
- throw new WebhookVerificationError("Invalid Signature");
591
- } catch (error) {
592
- if (error instanceof WebhookVerificationError) {
593
- throw error;
594
- }
595
- throw new WebhookVerificationError("Invalid Signature");
596
- }
597
- }
598
-
599
- /**
600
- * Validates a token and returns the claims as json payload if valid.
601
- * Supports issuer, audience, and scope validation.
602
- *
603
- * @param {string} token The token to be validated
604
- * @param {TokenValidationOptions} options Optional validation options for issuer, audience, and scopes
605
- * @return {Promise<T>} Returns the token payload if valid
606
- * @throws {ScalekitValidateTokenFailureException} If token is invalid or missing required scopes
607
- */
608
- async validateToken<T>(
609
- token: string,
610
- options?: TokenValidationOptions
611
- ): Promise<T> {
612
- await this.coreClient.getJwks();
613
- const jwks = jose.createLocalJWKSet({
614
- keys: this.coreClient.keys,
615
- });
616
- try {
617
- const { payload } = await jose.jwtVerify<T>(token, jwks, {
618
- ...(options?.issuer && { issuer: options.issuer }),
619
- ...(options?.audience && { audience: options.audience }),
620
- });
621
-
622
- if (options?.requiredScopes && options.requiredScopes.length > 0) {
623
- this.verifyScopes(token, options.requiredScopes);
624
- }
625
-
626
- return payload;
627
- } catch (error) {
628
- throw new ScalekitValidateTokenFailureException(error);
629
- }
630
- }
631
-
632
- /**
633
- * Verify that the token contains the required scopes
634
- *
635
- * @param {string} token The token to verify
636
- * @param {string[]} requiredScopes The scopes that must be present in the token
637
- * @return {boolean} Returns true if all required scopes are present
638
- * @throws {ScalekitValidateTokenFailureException} If required scopes are missing, with details about which scopes are missing
639
- */
640
- verifyScopes(token: string, requiredScopes: string[]): boolean {
641
- const payload = jose.decodeJwt(token);
642
- const scopes = this.extractScopesFromPayload(payload);
643
-
644
- const missingScopes = requiredScopes.filter(
645
- (scope) => !scopes.includes(scope)
646
- );
647
-
648
- if (missingScopes.length > 0) {
649
- throw new ScalekitValidateTokenFailureException(
650
- `Token missing required scopes: ${missingScopes.join(", ")}`
651
- );
652
- }
653
-
654
- return true;
655
- }
656
-
657
- /**
658
- * Extract scopes from token payload
659
- *
660
- * @param {any} payload The token payload
661
- * @return {string[]} Array of scopes found in the token
662
- */
663
- private extractScopesFromPayload(payload: Record<string, any>): string[] {
664
- const scopes = payload.scopes;
665
- return Array.isArray(scopes)
666
- ? scopes.filter((scope) => !!scope.trim?.())
667
- : [];
668
- }
669
-
670
- /**
671
- * Verify the timestamp
672
- *
673
- * @param {string} timestampStr The timestamp string
674
- * @return {Date} Returns the timestamp
675
- */
676
- private verifyTimestamp(timestampStr: string): Date {
677
- const now = Math.floor(Date.now() / 1000);
678
- const timestamp = parseInt(timestampStr, 10);
679
- if (isNaN(timestamp)) {
680
- throw new WebhookVerificationError("Invalid Signature Headers");
681
- }
682
- if (now - timestamp > WEBHOOK_TOLERANCE_IN_SECONDS) {
683
- throw new WebhookVerificationError("Message timestamp too old");
684
- }
685
- if (timestamp > now + WEBHOOK_TOLERANCE_IN_SECONDS) {
686
- throw new WebhookVerificationError("Message timestamp too new");
687
- }
688
-
689
- return new Date(timestamp * 1000);
690
- }
691
-
692
- /**
693
- * Compute the signature
694
- *
695
- * @param {Buffer} secretBytes The secret bytes
696
- * @param {string} data The data to be signed
697
- * @return {string} Returns the signature
698
- */
699
- private computeSignature(secretBytes: Buffer, data: string): string {
700
- return crypto
701
- .createHmac("sha256", secretBytes)
702
- .update(data)
703
- .digest("base64");
704
- }
705
-
706
- /**
707
- * Obtains a new access token using a refresh token.
708
- *
709
- * Use this method to get a new access token when the current one expires, without requiring
710
- * the user to re-authenticate. This implements the OAuth 2.0 refresh token grant type.
711
- * The method returns both a new access token and a new refresh token (token rotation).
712
- *
713
- * @param {string} refreshToken - The refresh token obtained from a previous authentication
714
- *
715
- * @returns {Promise<RefreshTokenResponse>} Response containing:
716
- * - accessToken: New access token for API authorization
717
- * - refreshToken: New refresh token (the old one is invalidated)
718
- *
719
- * @throws {Error} When the refresh token is missing
720
- * @throws {Error} When the refresh token is invalid, expired, or revoked
721
- * @throws {Error} When the authentication server response is invalid
722
- *
723
- * @example
724
- * // Refresh tokens before they expire
725
- * async function refreshUserToken(userId) {
726
- * try {
727
- * const oldRefreshToken = await getStoredRefreshToken(userId);
728
- *
729
- * const result = await scalekitClient.refreshAccessToken(oldRefreshToken);
730
- *
731
- * // Store the new tokens (old refresh token is now invalid)
732
- * await storeTokens(userId, {
733
- * accessToken: result.accessToken,
734
- * refreshToken: result.refreshToken
735
- * });
736
- *
737
- * return result.accessToken;
738
- * } catch (error) {
739
- * console.error('Token refresh failed:', error);
740
- * // Redirect user to login
741
- * throw new Error('Please log in again');
742
- * }
743
- * }
744
- *
745
- * @example
746
- * // Automatic token refresh middleware
747
- * app.use(async (req, res, next) => {
748
- * const accessToken = req.session.accessToken;
749
- * const refreshToken = req.session.refreshToken;
750
- *
751
- * // Check if access token is expired (decode JWT and check exp claim)
752
- * if (isTokenExpired(accessToken) && refreshToken) {
753
- * try {
754
- * const result = await scalekitClient.refreshAccessToken(refreshToken);
755
- * req.session.accessToken = result.accessToken;
756
- * req.session.refreshToken = result.refreshToken;
757
- * } catch (error) {
758
- * return res.redirect('/login');
759
- * }
760
- * }
761
- * next();
762
- * });
763
- *
764
- */
765
- async refreshAccessToken(
766
- refreshToken: string
767
- ): Promise<RefreshTokenResponse> {
768
- if (!refreshToken) {
769
- throw new Error("Refresh token is required");
770
- }
771
-
772
- let res;
773
- try {
774
- res = await this.coreClient.authenticate(
775
- QueryString.stringify({
776
- grant_type: GrantType.RefreshToken,
777
- client_id: this.coreClient.clientId,
778
- client_secret: this.coreClient.clientSecret,
779
- refresh_token: refreshToken,
780
- })
781
- );
782
- } catch (error) {
783
- throw new Error(
784
- `Failed to refresh token: ${
785
- error instanceof Error ? error.message : "Unknown error"
786
- }`
787
- );
788
- }
789
-
790
- if (!res || !res.data) {
791
- throw new Error("Invalid response from authentication server");
792
- }
793
-
794
- const { access_token, refresh_token } = res.data;
795
-
796
- // Validate that all required properties exist
797
- if (!access_token) {
798
- throw new Error("Missing access_token in authentication response");
799
- }
800
- if (!refresh_token) {
801
- throw new Error("Missing refresh_token in authentication response");
802
- }
803
-
804
- return {
805
- accessToken: access_token,
806
- refreshToken: refresh_token,
807
- };
808
- }
809
- }