@workos-inc/node 7.31.0-beta.actions1 → 7.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -12
- package/lib/index.worker.d.ts +0 -3
- package/lib/index.worker.js +0 -6
- package/lib/user-management/interfaces/authentication-response.interface.d.ts +4 -1
- package/lib/user-management/interfaces/index.d.ts +2 -3
- package/lib/user-management/interfaces/index.js +2 -3
- package/lib/user-management/interfaces/oauth-tokens.interface.d.ts +12 -0
- package/lib/user-management/serializers/authentication-response.serializer.js +3 -2
- package/lib/user-management/serializers/oauth-tokens.serializer.d.ts +2 -0
- package/lib/user-management/serializers/oauth-tokens.serializer.js +12 -0
- package/lib/user-management/user-management.spec.js +28 -0
- package/lib/webhooks/webhooks.d.ts +9 -9
- package/lib/webhooks/webhooks.js +36 -11
- package/lib/webhooks/webhooks.spec.js +46 -23
- package/lib/workos.d.ts +0 -3
- package/lib/workos.js +1 -6
- package/lib/workos.spec.js +1 -5
- package/package.json +2 -2
- package/lib/actions/actions.d.ts +0 -19
- package/lib/actions/actions.js +0 -53
- package/lib/actions/actions.spec.d.ts +0 -1
- package/lib/actions/actions.spec.js +0 -78
- package/lib/actions/fixtures/action-context.json +0 -39
- package/lib/actions/interfaces/response-payload.d.ts +0 -23
- package/lib/common/crypto/CryptoProvider.d.ts +0 -32
- package/lib/common/crypto/CryptoProvider.js +0 -13
- package/lib/common/crypto/CryptoProvider.spec.d.ts +0 -1
- package/lib/common/crypto/CryptoProvider.spec.js +0 -57
- package/lib/common/crypto/NodeCryptoProvider.d.ts +0 -12
- package/lib/common/crypto/NodeCryptoProvider.js +0 -73
- package/lib/common/crypto/SignatureProvider.d.ts +0 -13
- package/lib/common/crypto/SignatureProvider.js +0 -53
- package/lib/common/crypto/SignatureProvider.spec.d.ts +0 -1
- package/lib/common/crypto/SignatureProvider.spec.js +0 -66
- package/lib/common/crypto/SubtleCryptoProvider.d.ts +0 -15
- package/lib/common/crypto/SubtleCryptoProvider.js +0 -75
- package/lib/common/crypto/index.d.ts +0 -4
- package/lib/common/crypto/index.js +0 -20
- package/lib/common/net/index.d.ts +0 -5
- package/lib/common/net/index.js +0 -31
- package/lib/common/utils/unreachable.d.ts +0 -10
- package/lib/common/utils/unreachable.js +0 -18
- /package/lib/{actions/interfaces/response-payload.js → user-management/interfaces/oauth-tokens.interface.js} +0 -0
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { HttpClient } from './common/net/http-client';
|
|
2
|
-
import { Actions } from './actions/actions';
|
|
3
2
|
import { Webhooks } from './webhooks/webhooks';
|
|
4
3
|
import { WorkOS } from './workos';
|
|
5
4
|
import { WorkOSOptions } from './common/interfaces';
|
|
@@ -24,8 +23,6 @@ declare class WorkOSNode extends WorkOS {
|
|
|
24
23
|
/** @override */
|
|
25
24
|
createWebhookClient(): Webhooks;
|
|
26
25
|
/** @override */
|
|
27
|
-
createActionsClient(): Actions;
|
|
28
|
-
/** @override */
|
|
29
26
|
createIronSessionProvider(): IronSessionProvider;
|
|
30
27
|
/** @override */
|
|
31
28
|
emitWarning(warning: string): void;
|
package/lib/index.js
CHANGED
|
@@ -19,7 +19,6 @@ const node_crypto_provider_1 = require("./common/crypto/node-crypto-provider");
|
|
|
19
19
|
const subtle_crypto_provider_1 = require("./common/crypto/subtle-crypto-provider");
|
|
20
20
|
const fetch_client_1 = require("./common/net/fetch-client");
|
|
21
21
|
const node_client_1 = require("./common/net/node-client");
|
|
22
|
-
const actions_1 = require("./actions/actions");
|
|
23
22
|
const webhooks_1 = require("./webhooks/webhooks");
|
|
24
23
|
const workos_1 = require("./workos");
|
|
25
24
|
const web_iron_session_provider_1 = require("./common/iron-session/web-iron-session-provider");
|
|
@@ -62,17 +61,6 @@ class WorkOSNode extends workos_1.WorkOS {
|
|
|
62
61
|
return new webhooks_1.Webhooks(cryptoProvider);
|
|
63
62
|
}
|
|
64
63
|
/** @override */
|
|
65
|
-
createActionsClient() {
|
|
66
|
-
let cryptoProvider;
|
|
67
|
-
if (typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined') {
|
|
68
|
-
cryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
cryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
|
|
72
|
-
}
|
|
73
|
-
return new actions_1.Actions(cryptoProvider);
|
|
74
|
-
}
|
|
75
|
-
/** @override */
|
|
76
64
|
createIronSessionProvider() {
|
|
77
65
|
return new web_iron_session_provider_1.WebIronSessionProvider();
|
|
78
66
|
}
|
package/lib/index.worker.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Actions } from './actions/actions';
|
|
2
1
|
import { IronSessionProvider } from './common/iron-session/iron-session-provider';
|
|
3
2
|
import { HttpClient } from './common/net/http-client';
|
|
4
3
|
import { WorkOSOptions } from './index.worker';
|
|
@@ -22,8 +21,6 @@ declare class WorkOSWorker extends WorkOS {
|
|
|
22
21
|
/** @override */
|
|
23
22
|
createWebhookClient(): Webhooks;
|
|
24
23
|
/** @override */
|
|
25
|
-
createActionsClient(): Actions;
|
|
26
|
-
/** @override */
|
|
27
24
|
createIronSessionProvider(): IronSessionProvider;
|
|
28
25
|
/** @override */
|
|
29
26
|
emitWarning(warning: string): void;
|
package/lib/index.worker.js
CHANGED
|
@@ -15,7 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.WorkOS = void 0;
|
|
18
|
-
const actions_1 = require("./actions/actions");
|
|
19
18
|
const subtle_crypto_provider_1 = require("./common/crypto/subtle-crypto-provider");
|
|
20
19
|
const edge_iron_session_provider_1 = require("./common/iron-session/edge-iron-session-provider");
|
|
21
20
|
const fetch_client_1 = require("./common/net/fetch-client");
|
|
@@ -45,11 +44,6 @@ class WorkOSWorker extends workos_1.WorkOS {
|
|
|
45
44
|
return new webhooks_1.Webhooks(cryptoProvider);
|
|
46
45
|
}
|
|
47
46
|
/** @override */
|
|
48
|
-
createActionsClient() {
|
|
49
|
-
const cryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
50
|
-
return new actions_1.Actions(cryptoProvider);
|
|
51
|
-
}
|
|
52
|
-
/** @override */
|
|
53
47
|
createIronSessionProvider() {
|
|
54
48
|
return new edge_iron_session_provider_1.EdgeIronSessionProvider();
|
|
55
49
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Impersonator, ImpersonatorResponse } from './impersonator.interface';
|
|
2
|
+
import { OauthTokens, OauthTokensResponse } from './oauth-tokens.interface';
|
|
2
3
|
import { User, UserResponse } from './user.interface';
|
|
3
|
-
type AuthenticationMethod = 'SSO' | 'Password' | 'AppleOAuth' | 'GitHubOAuth' | 'GoogleOAuth' | 'MicrosoftOAuth' | 'MagicAuth' | 'Impersonation';
|
|
4
|
+
type AuthenticationMethod = 'SSO' | 'Password' | 'Passkey' | 'AppleOAuth' | 'GitHubOAuth' | 'GoogleOAuth' | 'MicrosoftOAuth' | 'MagicAuth' | 'Impersonation';
|
|
4
5
|
export interface AuthenticationResponse {
|
|
5
6
|
user: User;
|
|
6
7
|
organizationId?: string;
|
|
@@ -9,6 +10,7 @@ export interface AuthenticationResponse {
|
|
|
9
10
|
impersonator?: Impersonator;
|
|
10
11
|
authenticationMethod?: AuthenticationMethod;
|
|
11
12
|
sealedSession?: string;
|
|
13
|
+
oauthTokens?: OauthTokens;
|
|
12
14
|
}
|
|
13
15
|
export interface AuthenticationResponseResponse {
|
|
14
16
|
user: UserResponse;
|
|
@@ -17,5 +19,6 @@ export interface AuthenticationResponseResponse {
|
|
|
17
19
|
refresh_token: string;
|
|
18
20
|
impersonator?: ImpersonatorResponse;
|
|
19
21
|
authentication_method?: AuthenticationMethod;
|
|
22
|
+
oauth_tokens?: OauthTokensResponse;
|
|
20
23
|
}
|
|
21
24
|
export {};
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export * from './authentication-event.interface';
|
|
2
|
-
export * from './authenticate-with-magic-auth-options.interface';
|
|
3
|
-
export * from './authenticate-with-password-options.interface';
|
|
4
1
|
export * from './authenticate-with-code-options.interface';
|
|
5
2
|
export * from './authenticate-with-email-verification-options.interface';
|
|
6
3
|
export * from './authenticate-with-magic-auth-options.interface';
|
|
@@ -10,6 +7,7 @@ export * from './authenticate-with-password-options.interface';
|
|
|
10
7
|
export * from './authenticate-with-refresh-token-options.interface';
|
|
11
8
|
export * from './authenticate-with-session-cookie.interface';
|
|
12
9
|
export * from './authenticate-with-totp-options.interface';
|
|
10
|
+
export * from './authentication-event.interface';
|
|
13
11
|
export * from './authentication-response.interface';
|
|
14
12
|
export * from './create-magic-auth-options.interface';
|
|
15
13
|
export * from './create-organization-membership-options.interface';
|
|
@@ -25,6 +23,7 @@ export * from './list-invitations-options.interface';
|
|
|
25
23
|
export * from './list-organization-memberships-options.interface';
|
|
26
24
|
export * from './list-users-options.interface';
|
|
27
25
|
export * from './magic-auth.interface';
|
|
26
|
+
export * from './oauth-tokens.interface';
|
|
28
27
|
export * from './organization-membership.interface';
|
|
29
28
|
export * from './password-reset.interface';
|
|
30
29
|
export * from './refresh-and-seal-session-data.interface';
|
|
@@ -14,9 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./authentication-event.interface"), exports);
|
|
18
|
-
__exportStar(require("./authenticate-with-magic-auth-options.interface"), exports);
|
|
19
|
-
__exportStar(require("./authenticate-with-password-options.interface"), exports);
|
|
20
17
|
__exportStar(require("./authenticate-with-code-options.interface"), exports);
|
|
21
18
|
__exportStar(require("./authenticate-with-email-verification-options.interface"), exports);
|
|
22
19
|
__exportStar(require("./authenticate-with-magic-auth-options.interface"), exports);
|
|
@@ -26,6 +23,7 @@ __exportStar(require("./authenticate-with-password-options.interface"), exports)
|
|
|
26
23
|
__exportStar(require("./authenticate-with-refresh-token-options.interface"), exports);
|
|
27
24
|
__exportStar(require("./authenticate-with-session-cookie.interface"), exports);
|
|
28
25
|
__exportStar(require("./authenticate-with-totp-options.interface"), exports);
|
|
26
|
+
__exportStar(require("./authentication-event.interface"), exports);
|
|
29
27
|
__exportStar(require("./authentication-response.interface"), exports);
|
|
30
28
|
__exportStar(require("./create-magic-auth-options.interface"), exports);
|
|
31
29
|
__exportStar(require("./create-organization-membership-options.interface"), exports);
|
|
@@ -41,6 +39,7 @@ __exportStar(require("./list-invitations-options.interface"), exports);
|
|
|
41
39
|
__exportStar(require("./list-organization-memberships-options.interface"), exports);
|
|
42
40
|
__exportStar(require("./list-users-options.interface"), exports);
|
|
43
41
|
__exportStar(require("./magic-auth.interface"), exports);
|
|
42
|
+
__exportStar(require("./oauth-tokens.interface"), exports);
|
|
44
43
|
__exportStar(require("./organization-membership.interface"), exports);
|
|
45
44
|
__exportStar(require("./password-reset.interface"), exports);
|
|
46
45
|
__exportStar(require("./refresh-and-seal-session-data.interface"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface OauthTokens {
|
|
2
|
+
accessToken: string;
|
|
3
|
+
refreshToken: string;
|
|
4
|
+
expiresAt: number;
|
|
5
|
+
scopes: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface OauthTokensResponse {
|
|
8
|
+
access_token: string;
|
|
9
|
+
refresh_token: string;
|
|
10
|
+
expires_at: number;
|
|
11
|
+
scopes: string[];
|
|
12
|
+
}
|
|
@@ -12,9 +12,10 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
};
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.deserializeAuthenticationResponse = void 0;
|
|
15
|
+
const oauth_tokens_serializer_1 = require("./oauth-tokens.serializer");
|
|
15
16
|
const user_serializer_1 = require("./user.serializer");
|
|
16
17
|
const deserializeAuthenticationResponse = (authenticationResponse) => {
|
|
17
|
-
const { user, organization_id, access_token, refresh_token, authentication_method, impersonator } = authenticationResponse, rest = __rest(authenticationResponse, ["user", "organization_id", "access_token", "refresh_token", "authentication_method", "impersonator"]);
|
|
18
|
-
return Object.assign({ user: (0, user_serializer_1.deserializeUser)(user), organizationId: organization_id, accessToken: access_token, refreshToken: refresh_token, impersonator, authenticationMethod: authentication_method }, rest);
|
|
18
|
+
const { user, organization_id, access_token, refresh_token, authentication_method, impersonator, oauth_tokens } = authenticationResponse, rest = __rest(authenticationResponse, ["user", "organization_id", "access_token", "refresh_token", "authentication_method", "impersonator", "oauth_tokens"]);
|
|
19
|
+
return Object.assign({ user: (0, user_serializer_1.deserializeUser)(user), organizationId: organization_id, accessToken: access_token, refreshToken: refresh_token, impersonator, authenticationMethod: authentication_method, oauthTokens: (0, oauth_tokens_serializer_1.deserializeOauthTokens)(oauth_tokens) }, rest);
|
|
19
20
|
};
|
|
20
21
|
exports.deserializeAuthenticationResponse = deserializeAuthenticationResponse;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deserializeOauthTokens = void 0;
|
|
4
|
+
const deserializeOauthTokens = (oauthTokens) => oauthTokens
|
|
5
|
+
? {
|
|
6
|
+
accessToken: oauthTokens.access_token,
|
|
7
|
+
refreshToken: oauthTokens.refresh_token,
|
|
8
|
+
expiresAt: oauthTokens.expires_at,
|
|
9
|
+
scopes: oauthTokens.scopes,
|
|
10
|
+
}
|
|
11
|
+
: undefined;
|
|
12
|
+
exports.deserializeOauthTokens = deserializeOauthTokens;
|
|
@@ -374,6 +374,34 @@ describe('UserManagement', () => {
|
|
|
374
374
|
}));
|
|
375
375
|
});
|
|
376
376
|
});
|
|
377
|
+
describe('when oauth_tokens is present', () => {
|
|
378
|
+
it('deserializes oauth_tokens', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
379
|
+
(0, test_utils_1.fetchOnce)({
|
|
380
|
+
user: user_json_1.default,
|
|
381
|
+
oauth_tokens: {
|
|
382
|
+
access_token: 'access_token',
|
|
383
|
+
refresh_token: 'refresh',
|
|
384
|
+
expires_at: 123,
|
|
385
|
+
scopes: ['read:users'],
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
const resp = yield workos.userManagement.authenticateWithCode({
|
|
389
|
+
clientId: 'proj_whatever',
|
|
390
|
+
code: 'or this',
|
|
391
|
+
});
|
|
392
|
+
expect(resp).toMatchObject({
|
|
393
|
+
user: {
|
|
394
|
+
email: 'test01@example.com',
|
|
395
|
+
},
|
|
396
|
+
oauthTokens: {
|
|
397
|
+
accessToken: 'access_token',
|
|
398
|
+
refreshToken: 'refresh',
|
|
399
|
+
expiresAt: 123,
|
|
400
|
+
scopes: ['read:users'],
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
}));
|
|
404
|
+
});
|
|
377
405
|
});
|
|
378
406
|
describe('authenticateWithRefreshToken', () => {
|
|
379
407
|
it('sends a refresh_token authentication request', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { Event } from '../common/interfaces';
|
|
2
2
|
import { CryptoProvider } from '../common/crypto/crypto-provider';
|
|
3
3
|
export declare class Webhooks {
|
|
4
|
-
private
|
|
4
|
+
private cryptoProvider;
|
|
5
5
|
constructor(cryptoProvider: CryptoProvider);
|
|
6
|
-
get verifyHeader(): ({ payload, sigHeader, secret, tolerance, }: {
|
|
7
|
-
payload: any;
|
|
8
|
-
sigHeader: string;
|
|
9
|
-
secret: string;
|
|
10
|
-
tolerance?: number | undefined;
|
|
11
|
-
}) => Promise<boolean>;
|
|
12
|
-
get computeSignature(): (timestamp: any, payload: any, secret: string) => Promise<string>;
|
|
13
|
-
get getTimestampAndSignatureHash(): (sigHeader: string) => [string, string];
|
|
14
6
|
constructEvent({ payload, sigHeader, secret, tolerance, }: {
|
|
15
7
|
payload: unknown;
|
|
16
8
|
sigHeader: string;
|
|
17
9
|
secret: string;
|
|
18
10
|
tolerance?: number;
|
|
19
11
|
}): Promise<Event>;
|
|
12
|
+
verifyHeader({ payload, sigHeader, secret, tolerance, }: {
|
|
13
|
+
payload: any;
|
|
14
|
+
sigHeader: string;
|
|
15
|
+
secret: string;
|
|
16
|
+
tolerance?: number;
|
|
17
|
+
}): Promise<boolean>;
|
|
18
|
+
getTimestampAndSignatureHash(sigHeader: string): [string, string];
|
|
19
|
+
computeSignature(timestamp: any, payload: any, secret: string): Promise<string>;
|
|
20
20
|
}
|
package/lib/webhooks/webhooks.js
CHANGED
|
@@ -10,20 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Webhooks = void 0;
|
|
13
|
+
const exceptions_1 = require("../common/exceptions");
|
|
13
14
|
const serializers_1 = require("../common/serializers");
|
|
14
|
-
const SignatureProvider_1 = require("../common/crypto/SignatureProvider");
|
|
15
15
|
class Webhooks {
|
|
16
16
|
constructor(cryptoProvider) {
|
|
17
|
-
this.
|
|
18
|
-
}
|
|
19
|
-
get verifyHeader() {
|
|
20
|
-
return this.signatureProvider.verifyHeader.bind(this.signatureProvider);
|
|
21
|
-
}
|
|
22
|
-
get computeSignature() {
|
|
23
|
-
return this.signatureProvider.computeSignature.bind(this.signatureProvider);
|
|
24
|
-
}
|
|
25
|
-
get getTimestampAndSignatureHash() {
|
|
26
|
-
return this.signatureProvider.getTimestampAndSignatureHash.bind(this.signatureProvider);
|
|
17
|
+
this.cryptoProvider = cryptoProvider;
|
|
27
18
|
}
|
|
28
19
|
constructEvent({ payload, sigHeader, secret, tolerance = 180000, }) {
|
|
29
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -33,5 +24,39 @@ class Webhooks {
|
|
|
33
24
|
return (0, serializers_1.deserializeEvent)(webhookPayload);
|
|
34
25
|
});
|
|
35
26
|
}
|
|
27
|
+
verifyHeader({ payload, sigHeader, secret, tolerance = 180000, }) {
|
|
28
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
29
|
+
const [timestamp, signatureHash] = this.getTimestampAndSignatureHash(sigHeader);
|
|
30
|
+
if (!signatureHash || Object.keys(signatureHash).length === 0) {
|
|
31
|
+
throw new exceptions_1.SignatureVerificationException('No signature hash found with expected scheme v1');
|
|
32
|
+
}
|
|
33
|
+
if (parseInt(timestamp, 10) < Date.now() - tolerance) {
|
|
34
|
+
throw new exceptions_1.SignatureVerificationException('Timestamp outside the tolerance zone');
|
|
35
|
+
}
|
|
36
|
+
const expectedSig = yield this.computeSignature(timestamp, payload, secret);
|
|
37
|
+
if ((yield this.cryptoProvider.secureCompare(expectedSig, signatureHash)) ===
|
|
38
|
+
false) {
|
|
39
|
+
throw new exceptions_1.SignatureVerificationException('Signature hash does not match the expected signature hash for payload');
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
getTimestampAndSignatureHash(sigHeader) {
|
|
45
|
+
const signature = sigHeader;
|
|
46
|
+
const [t, v1] = signature.split(',');
|
|
47
|
+
if (typeof t === 'undefined' || typeof v1 === 'undefined') {
|
|
48
|
+
throw new exceptions_1.SignatureVerificationException('Signature or timestamp missing');
|
|
49
|
+
}
|
|
50
|
+
const { 1: timestamp } = t.split('=');
|
|
51
|
+
const { 1: signatureHash } = v1.split('=');
|
|
52
|
+
return [timestamp, signatureHash];
|
|
53
|
+
}
|
|
54
|
+
computeSignature(timestamp, payload, secret) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
payload = JSON.stringify(payload);
|
|
57
|
+
const signedPayload = `${timestamp}.${payload}`;
|
|
58
|
+
return yield this.cryptoProvider.computeHMACSignatureAsync(signedPayload, secret);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
36
61
|
}
|
|
37
62
|
exports.Webhooks = Webhooks;
|
|
@@ -17,6 +17,8 @@ const workos_1 = require("../workos");
|
|
|
17
17
|
const webhook_json_1 = __importDefault(require("./fixtures/webhook.json"));
|
|
18
18
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
19
19
|
const exceptions_1 = require("../common/exceptions");
|
|
20
|
+
const node_crypto_provider_1 = require("../common/crypto/node-crypto-provider");
|
|
21
|
+
const subtle_crypto_provider_1 = require("../common/crypto/subtle-crypto-provider");
|
|
20
22
|
describe('Webhooks', () => {
|
|
21
23
|
let payload;
|
|
22
24
|
let secret;
|
|
@@ -164,34 +166,55 @@ describe('Webhooks', () => {
|
|
|
164
166
|
});
|
|
165
167
|
});
|
|
166
168
|
describe('verifyHeader', () => {
|
|
167
|
-
it('
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
workos.webhooks
|
|
171
|
-
|
|
172
|
-
payload,
|
|
173
|
-
sigHeader: `t=${timestamp}, v1=${signatureHash}`,
|
|
174
|
-
secret,
|
|
175
|
-
});
|
|
176
|
-
expect(spy).toHaveBeenCalled();
|
|
169
|
+
it('returns true when the signature is valid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
170
|
+
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
171
|
+
const options = { payload, sigHeader, secret };
|
|
172
|
+
const result = yield workos.webhooks.verifyHeader(options);
|
|
173
|
+
expect(result).toBeTruthy();
|
|
177
174
|
}));
|
|
178
175
|
});
|
|
176
|
+
describe('getTimestampAndSignatureHash', () => {
|
|
177
|
+
it('returns the timestamp and signature when the signature is valid', () => {
|
|
178
|
+
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
179
|
+
const timestampAndSignature = workos.webhooks.getTimestampAndSignatureHash(sigHeader);
|
|
180
|
+
expect(timestampAndSignature).toEqual([
|
|
181
|
+
timestamp.toString(),
|
|
182
|
+
signatureHash,
|
|
183
|
+
]);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
179
186
|
describe('computeSignature', () => {
|
|
180
|
-
it('
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
workos.webhooks['signatureProvider'], 'computeSignature');
|
|
184
|
-
yield workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
185
|
-
expect(spy).toHaveBeenCalled();
|
|
187
|
+
it('returns the computed signature', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
188
|
+
const signature = yield workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
189
|
+
expect(signature).toEqual(signatureHash);
|
|
186
190
|
}));
|
|
187
191
|
});
|
|
188
|
-
describe('
|
|
189
|
-
it('
|
|
190
|
-
const spy = jest.spyOn(
|
|
192
|
+
describe('when in an environment that supports SubtleCrypto', () => {
|
|
193
|
+
it('automatically uses the subtle crypto library', () => {
|
|
191
194
|
// tslint:disable-next-line
|
|
192
|
-
workos.webhooks['
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
195
|
+
expect(workos.webhooks['cryptoProvider']).toBeInstanceOf(subtle_crypto_provider_1.SubtleCryptoProvider);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
describe('CryptoProvider', () => {
|
|
199
|
+
describe('when computing HMAC signature', () => {
|
|
200
|
+
it('returns the same for the Node crypto and Web Crypto versions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
201
|
+
const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
|
|
202
|
+
const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
203
|
+
const stringifiedPayload = JSON.stringify(payload);
|
|
204
|
+
const payloadHMAC = `${timestamp}.${stringifiedPayload}`;
|
|
205
|
+
const nodeCompare = yield nodeCryptoProvider.computeHMACSignatureAsync(payloadHMAC, secret);
|
|
206
|
+
const subtleCompare = yield subtleCryptoProvider.computeHMACSignatureAsync(payloadHMAC, secret);
|
|
207
|
+
expect(nodeCompare).toEqual(subtleCompare);
|
|
208
|
+
}));
|
|
209
|
+
});
|
|
210
|
+
describe('when securely comparing', () => {
|
|
211
|
+
it('returns the same for the Node crypto and Web Crypto versions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
212
|
+
const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
|
|
213
|
+
const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
214
|
+
const signature = yield workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
215
|
+
expect(nodeCryptoProvider.secureCompare(signature, signatureHash)).toEqual(subtleCryptoProvider.secureCompare(signature, signatureHash));
|
|
216
|
+
expect(nodeCryptoProvider.secureCompare(signature, 'foo')).toEqual(subtleCryptoProvider.secureCompare(signature, 'foo'));
|
|
217
|
+
}));
|
|
218
|
+
});
|
|
196
219
|
});
|
|
197
220
|
});
|
package/lib/workos.d.ts
CHANGED
|
@@ -14,14 +14,12 @@ import { FGA } from './fga/fga';
|
|
|
14
14
|
import { HttpClient } from './common/net/http-client';
|
|
15
15
|
import { IronSessionProvider } from './common/iron-session/iron-session-provider';
|
|
16
16
|
import { Widgets } from './widgets/widgets';
|
|
17
|
-
import { Actions } from './actions/actions';
|
|
18
17
|
export declare class WorkOS {
|
|
19
18
|
readonly key?: string | undefined;
|
|
20
19
|
readonly options: WorkOSOptions;
|
|
21
20
|
readonly baseURL: string;
|
|
22
21
|
readonly client: HttpClient;
|
|
23
22
|
readonly clientId?: string;
|
|
24
|
-
readonly actions: Actions;
|
|
25
23
|
readonly auditLogs: AuditLogs;
|
|
26
24
|
readonly directorySync: DirectorySync;
|
|
27
25
|
readonly organizations: Organizations;
|
|
@@ -37,7 +35,6 @@ export declare class WorkOS {
|
|
|
37
35
|
readonly widgets: Widgets;
|
|
38
36
|
constructor(key?: string | undefined, options?: WorkOSOptions);
|
|
39
37
|
createWebhookClient(): Webhooks;
|
|
40
|
-
createActionsClient(): Actions;
|
|
41
38
|
createHttpClient(options: WorkOSOptions, userAgent: string): HttpClient;
|
|
42
39
|
createIronSessionProvider(): IronSessionProvider;
|
|
43
40
|
get version(): string;
|
package/lib/workos.js
CHANGED
|
@@ -28,8 +28,7 @@ const http_client_1 = require("./common/net/http-client");
|
|
|
28
28
|
const subtle_crypto_provider_1 = require("./common/crypto/subtle-crypto-provider");
|
|
29
29
|
const fetch_client_1 = require("./common/net/fetch-client");
|
|
30
30
|
const widgets_1 = require("./widgets/widgets");
|
|
31
|
-
const
|
|
32
|
-
const VERSION = '7.30.1';
|
|
31
|
+
const VERSION = '7.32.0';
|
|
33
32
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
34
33
|
const HEADER_AUTHORIZATION = 'Authorization';
|
|
35
34
|
const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
|
@@ -79,7 +78,6 @@ class WorkOS {
|
|
|
79
78
|
userAgent += ` ${name}: ${version}`;
|
|
80
79
|
}
|
|
81
80
|
this.webhooks = this.createWebhookClient();
|
|
82
|
-
this.actions = this.createActionsClient();
|
|
83
81
|
// Must initialize UserManagement after baseURL is configured
|
|
84
82
|
this.userManagement = new user_management_1.UserManagement(this, this.createIronSessionProvider());
|
|
85
83
|
this.client = this.createHttpClient(options, userAgent);
|
|
@@ -87,9 +85,6 @@ class WorkOS {
|
|
|
87
85
|
createWebhookClient() {
|
|
88
86
|
return new webhooks_1.Webhooks(new subtle_crypto_provider_1.SubtleCryptoProvider());
|
|
89
87
|
}
|
|
90
|
-
createActionsClient() {
|
|
91
|
-
return new actions_1.Actions(new subtle_crypto_provider_1.SubtleCryptoProvider());
|
|
92
|
-
}
|
|
93
88
|
createHttpClient(options, userAgent) {
|
|
94
89
|
var _a;
|
|
95
90
|
return new fetch_client_1.FetchHttpClient(this.baseURL, Object.assign(Object.assign({}, options.config), { headers: Object.assign(Object.assign({}, (_a = options.config) === null || _a === void 0 ? void 0 : _a.headers), { Authorization: `Bearer ${this.key}`, 'User-Agent': userAgent }) }));
|
package/lib/workos.spec.js
CHANGED
|
@@ -246,12 +246,8 @@ describe('WorkOS', () => {
|
|
|
246
246
|
const workos = new index_worker_1.WorkOS('sk_test_key');
|
|
247
247
|
// tslint:disable-next-line
|
|
248
248
|
expect(workos['client']).toBeInstanceOf(fetch_client_1.FetchHttpClient);
|
|
249
|
-
expect(
|
|
250
249
|
// tslint:disable-next-line
|
|
251
|
-
workos.webhooks['
|
|
252
|
-
expect(
|
|
253
|
-
// tslint:disable-next-line
|
|
254
|
-
workos.actions['signatureProvider']['cryptoProvider']).toBeInstanceOf(subtle_crypto_provider_1.SubtleCryptoProvider);
|
|
250
|
+
expect(workos.webhooks['cryptoProvider']).toBeInstanceOf(subtle_crypto_provider_1.SubtleCryptoProvider);
|
|
255
251
|
});
|
|
256
252
|
it('uses console.warn to emit warnings', () => {
|
|
257
253
|
const workos = new index_worker_1.WorkOS('sk_test_key');
|
package/package.json
CHANGED
package/lib/actions/actions.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { CryptoProvider } from '../common/crypto/crypto-provider';
|
|
2
|
-
import { AuthenticationActionResponseData, ResponsePayload, UserRegistrationActionResponseData } from './interfaces/response-payload';
|
|
3
|
-
export declare class Actions {
|
|
4
|
-
private signatureProvider;
|
|
5
|
-
constructor(cryptoProvider: CryptoProvider);
|
|
6
|
-
private get computeSignature();
|
|
7
|
-
get verifyHeader(): ({ payload, sigHeader, secret, tolerance, }: {
|
|
8
|
-
payload: any;
|
|
9
|
-
sigHeader: string;
|
|
10
|
-
secret: string;
|
|
11
|
-
tolerance?: number | undefined;
|
|
12
|
-
}) => Promise<boolean>;
|
|
13
|
-
serializeType(type: AuthenticationActionResponseData['type'] | UserRegistrationActionResponseData['type']): "authentication_action_response" | "user_registration_action_response";
|
|
14
|
-
signResponse(data: AuthenticationActionResponseData | UserRegistrationActionResponseData, secret: string): Promise<{
|
|
15
|
-
object: string;
|
|
16
|
-
payload: ResponsePayload;
|
|
17
|
-
signature: string;
|
|
18
|
-
}>;
|
|
19
|
-
}
|
package/lib/actions/actions.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.Actions = void 0;
|
|
13
|
-
const crypto_1 = require("../common/crypto");
|
|
14
|
-
const unreachable_1 = require("../common/utils/unreachable");
|
|
15
|
-
class Actions {
|
|
16
|
-
constructor(cryptoProvider) {
|
|
17
|
-
this.signatureProvider = new crypto_1.SignatureProvider(cryptoProvider);
|
|
18
|
-
}
|
|
19
|
-
get computeSignature() {
|
|
20
|
-
return this.signatureProvider.computeSignature.bind(this.signatureProvider);
|
|
21
|
-
}
|
|
22
|
-
get verifyHeader() {
|
|
23
|
-
return this.signatureProvider.verifyHeader.bind(this.signatureProvider);
|
|
24
|
-
}
|
|
25
|
-
serializeType(type) {
|
|
26
|
-
switch (type) {
|
|
27
|
-
case 'authentication':
|
|
28
|
-
return 'authentication_action_response';
|
|
29
|
-
case 'user_registration':
|
|
30
|
-
return 'user_registration_action_response';
|
|
31
|
-
default:
|
|
32
|
-
return (0, unreachable_1.unreachable)(type);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
signResponse(data, secret) {
|
|
36
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
let errorMessage;
|
|
38
|
-
const { verdict, type } = data;
|
|
39
|
-
if (verdict === 'Deny' && data.errorMessage) {
|
|
40
|
-
errorMessage = data.errorMessage;
|
|
41
|
-
}
|
|
42
|
-
const responsePayload = Object.assign({ timestamp: Date.now(), verdict }, (verdict === 'Deny' &&
|
|
43
|
-
data.errorMessage && { error_message: errorMessage }));
|
|
44
|
-
const response = {
|
|
45
|
-
object: this.serializeType(type),
|
|
46
|
-
payload: responsePayload,
|
|
47
|
-
signature: yield this.computeSignature(responsePayload.timestamp, responsePayload, secret),
|
|
48
|
-
};
|
|
49
|
-
return response;
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
exports.Actions = Actions;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|