@voltro/plugin-auth-workos 0.32.0 → 0.34.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/CHANGELOG.md +2006 -0
- package/dist/index.d.ts +88 -7
- package/dist/index.js +71 -54
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -7,24 +7,58 @@ declare interface ApiCallOptions {
|
|
|
7
7
|
readonly fetchImpl?: typeof fetch;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Exchange an authorization code for the authenticated WorkOS user — AFTER
|
|
12
|
+
* checking the CSRF `state`, and carrying the PKCE `code_verifier`.
|
|
13
|
+
*
|
|
14
|
+
* **The state check lives in here rather than beside the caller's `if (!code)`
|
|
15
|
+
* deliberately.** A generated `state` that nothing verifies is worse than no
|
|
16
|
+
* state at all: it makes a code review, a screenshot of the authorize URL and a
|
|
17
|
+
* penetration test all read as "CSRF is handled". Making the check part of the
|
|
18
|
+
* only function that can redeem a code means an integration cannot arrive at a
|
|
19
|
+
* session without having performed it — the loop is closed by the type
|
|
20
|
+
* signature, not by a note in the docs.
|
|
21
|
+
*
|
|
22
|
+
* Both values are compared in constant time. `state` is not a high-value secret,
|
|
23
|
+
* but it IS a secret compared against attacker-supplied input, and a `===` on
|
|
24
|
+
* that shape is the habit this repo does not keep.
|
|
25
|
+
*/
|
|
11
26
|
export declare const workosAuthenticateWithCode: (o: WorkosExchangeOptions) => Promise<WorkosProfile>;
|
|
12
27
|
|
|
13
28
|
/** Verify a Magic Auth one-time code → the authenticated WorkOS user. */
|
|
14
29
|
export declare const workosAuthenticateWithMagicAuth: (o: WorkosMagicAuthVerifyOptions) => Promise<WorkosProfile>;
|
|
15
30
|
|
|
16
|
-
/**
|
|
17
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Begin a WorkOS hosted-login (AuthKit) flow: mint `state` + a PKCE
|
|
33
|
+
* `code_verifier`, and build the authorize URL carrying `state` and the S256
|
|
34
|
+
* `code_challenge`.
|
|
35
|
+
*
|
|
36
|
+
* **`state` is not optional and is not caller-supplied.** It used to be both —
|
|
37
|
+
* `if (o.state) params.set('state', o.state)` — which made the CSRF defence
|
|
38
|
+
* something an integration had to know to ask for, and made "the login works"
|
|
39
|
+
* indistinguishable from "the login is forgeable". An attacker who can get a
|
|
40
|
+
* victim's browser to hit a callback with an authorization code THEY obtained
|
|
41
|
+
* logs the victim into the ATTACKER's account; `state` is the only thing that
|
|
42
|
+
* stops it, so it is minted here, always, from `randomBytes`.
|
|
43
|
+
*
|
|
44
|
+
* **PKCE (S256) rides along.** The authorization code travels through the
|
|
45
|
+
* browser's address bar and the referrer chain; without a verifier, anyone who
|
|
46
|
+
* captures it before the app redeems it can redeem it themselves. WorkOS
|
|
47
|
+
* accepts `code_challenge`/`code_challenge_method` on authorize and
|
|
48
|
+
* `code_verifier` on authenticate, so the loop closes with no extra round trip.
|
|
49
|
+
*
|
|
50
|
+
* An app that used to carry a post-login return path INSIDE `state` puts it in
|
|
51
|
+
* its own cookie next to these two instead — mixing an application payload into
|
|
52
|
+
* a CSRF nonce is what made the nonce guessable in the first place.
|
|
53
|
+
*/
|
|
54
|
+
export declare const workosBeginLogin: (o: WorkosBeginLoginOptions) => WorkosLoginHandoff;
|
|
18
55
|
|
|
19
|
-
export declare interface
|
|
56
|
+
export declare interface WorkosBeginLoginOptions {
|
|
20
57
|
/** WorkOS Client ID (`client_01…`). */
|
|
21
58
|
readonly clientId: string;
|
|
22
59
|
/** The callback URL WorkOS redirects to with `?code=…&state=…`. Must be
|
|
23
60
|
* registered in the WorkOS dashboard. */
|
|
24
61
|
readonly redirectUri: string;
|
|
25
|
-
/** Opaque state echoed back to the callback — use it for CSRF defence
|
|
26
|
-
* and to carry a post-login return path. */
|
|
27
|
-
readonly state?: string;
|
|
28
62
|
/** `'authkit'` (default) = WorkOS' hosted AuthKit UI; or a specific
|
|
29
63
|
* connection/provider id for direct SSO. */
|
|
30
64
|
readonly provider?: string;
|
|
@@ -32,6 +66,15 @@ export declare interface WorkosAuthorizationUrlOptions {
|
|
|
32
66
|
readonly loginHint?: string;
|
|
33
67
|
/** Override the API origin (tests). Default `https://api.workos.com`. */
|
|
34
68
|
readonly apiBase?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Inject the two random values instead of minting them. TESTS ONLY — a
|
|
71
|
+
* deterministic `state` is a CSRF token an attacker can also predict, and a
|
|
72
|
+
* deterministic `codeVerifier` is no PKCE at all.
|
|
73
|
+
*/
|
|
74
|
+
readonly randomness?: {
|
|
75
|
+
readonly state: string;
|
|
76
|
+
readonly codeVerifier: string;
|
|
77
|
+
};
|
|
35
78
|
}
|
|
36
79
|
|
|
37
80
|
/** Claims we expect from a WorkOS-issued AuthKit access token. The
|
|
@@ -86,6 +129,14 @@ export declare interface WorkosExchangeOptions {
|
|
|
86
129
|
readonly apiKey: string;
|
|
87
130
|
/** The `code` from the callback query string. */
|
|
88
131
|
readonly code: string;
|
|
132
|
+
/** The `state` from the callback query string — what the browser presented. */
|
|
133
|
+
readonly state: string;
|
|
134
|
+
/** The `state` {@link workosBeginLogin} minted for this browser, read back
|
|
135
|
+
* out of wherever the app stashed it. */
|
|
136
|
+
readonly expectedState: string;
|
|
137
|
+
/** The PKCE `codeVerifier` {@link workosBeginLogin} minted, read back out of
|
|
138
|
+
* wherever the app stashed it. */
|
|
139
|
+
readonly codeVerifier: string;
|
|
89
140
|
readonly apiBase?: string;
|
|
90
141
|
/** Injectable fetch for tests. */
|
|
91
142
|
readonly fetchImpl?: typeof fetch;
|
|
@@ -109,6 +160,25 @@ export declare const workosListUserMemberships: (o: ApiCallOptions & {
|
|
|
109
160
|
readonly userId: string;
|
|
110
161
|
}) => Promise<ReadonlyArray<WorkosMembership>>;
|
|
111
162
|
|
|
163
|
+
/**
|
|
164
|
+
* What a login handoff produces: the URL to send the browser to, plus the two
|
|
165
|
+
* secrets the CALLBACK has to be able to check.
|
|
166
|
+
*
|
|
167
|
+
* Both `state` and `codeVerifier` must be stashed somewhere the same browser
|
|
168
|
+
* will present back — a short-lived `HttpOnly` cookie is the usual answer — and
|
|
169
|
+
* handed to {@link workosAuthenticateWithCode}. There is no server-side store
|
|
170
|
+
* here on purpose: this package is transport-thin, and where the app keeps a
|
|
171
|
+
* 10-minute nonce is the app's decision.
|
|
172
|
+
*/
|
|
173
|
+
export declare interface WorkosLoginHandoff {
|
|
174
|
+
/** The WorkOS hosted-login URL to redirect the browser to. */
|
|
175
|
+
readonly url: string;
|
|
176
|
+
/** The CSRF nonce. Compare against the callback's `?state=` before exchanging. */
|
|
177
|
+
readonly state: string;
|
|
178
|
+
/** The PKCE verifier. Send it with the code exchange. */
|
|
179
|
+
readonly codeVerifier: string;
|
|
180
|
+
}
|
|
181
|
+
|
|
112
182
|
export declare interface WorkosMagicAuthSendOptions {
|
|
113
183
|
/** WorkOS API key (`sk_…`) — sent as a Bearer token. Server-only. */
|
|
114
184
|
readonly apiKey: string;
|
|
@@ -162,6 +232,17 @@ export declare interface WorkosProfile {
|
|
|
162
232
|
*/
|
|
163
233
|
export declare const workosSendMagicAuthCode: (o: WorkosMagicAuthSendOptions) => Promise<void>;
|
|
164
234
|
|
|
235
|
+
/**
|
|
236
|
+
* The callback's `state` did not match the one minted for this browser.
|
|
237
|
+
*
|
|
238
|
+
* A distinct class because it is a distinct event: every other
|
|
239
|
+
* `WorkosExchangeError` means WorkOS said no, this one means the request did
|
|
240
|
+
* not come from a login THIS server started. Worth alerting on separately.
|
|
241
|
+
*/
|
|
242
|
+
export declare class WorkosStateMismatchError extends WorkosExchangeError {
|
|
243
|
+
constructor(message: string);
|
|
244
|
+
}
|
|
245
|
+
|
|
165
246
|
export declare const workosStrategy: (options: WorkosStrategyOptions) => AuthStrategy;
|
|
166
247
|
|
|
167
248
|
export declare interface WorkosStrategyOptions {
|
package/dist/index.js
CHANGED
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
import { jwtBearerStrategy as e } from "@voltro/protocol/jwt";
|
|
2
|
+
import { createHash as t, randomBytes as n } from "node:crypto";
|
|
3
|
+
import { timingSafeStringEqual as r } from "@voltro/protocol/session";
|
|
2
4
|
//#region src/strategy.ts
|
|
3
|
-
var
|
|
4
|
-
if (!
|
|
5
|
-
let
|
|
5
|
+
var i = "https://api.workos.com", a = "wos-session", o = (t) => {
|
|
6
|
+
if (!t.clientId) throw Error("workosStrategy: `clientId` is required");
|
|
7
|
+
let n = t.scopesFromClaims;
|
|
6
8
|
return e({
|
|
7
9
|
id: "workos",
|
|
8
|
-
jwksUrl:
|
|
9
|
-
issuer:
|
|
10
|
-
audience:
|
|
10
|
+
jwksUrl: t.jwksUrl ?? `${i}/sso/jwks/${t.clientId}`,
|
|
11
|
+
issuer: t.issuer ?? i,
|
|
12
|
+
audience: t.clientId,
|
|
11
13
|
algorithms: ["RS256", "ES256"],
|
|
12
|
-
cookieName:
|
|
13
|
-
tenantIdFromClaims: (e) =>
|
|
14
|
-
...
|
|
14
|
+
cookieName: t.cookieName === void 0 ? a : t.cookieName,
|
|
15
|
+
tenantIdFromClaims: (e) => t.tenantIdFromClaims?.(e) ?? (typeof e.org_id == "string" ? e.org_id : void 0) ?? t.defaultTenantId ?? null,
|
|
16
|
+
...n === void 0 ? {} : { scopesFromClaims: (e) => n(e) }
|
|
15
17
|
});
|
|
16
|
-
},
|
|
17
|
-
if (!e.clientId) throw Error("
|
|
18
|
-
if (!e.redirectUri) throw Error("
|
|
19
|
-
let t = new URLSearchParams({
|
|
18
|
+
}, s = "https://api.workos.com", c = (e) => e.toString("base64url"), l = () => c(n(32)), u = (e) => c(t("sha256").update(e, "ascii").digest()), d = (e) => {
|
|
19
|
+
if (!e.clientId) throw Error("workosBeginLogin: `clientId` is required");
|
|
20
|
+
if (!e.redirectUri) throw Error("workosBeginLogin: `redirectUri` is required");
|
|
21
|
+
let t = e.randomness?.state ?? l(), n = e.randomness?.codeVerifier ?? l(), r = new URLSearchParams({
|
|
20
22
|
client_id: e.clientId,
|
|
21
23
|
redirect_uri: e.redirectUri,
|
|
22
24
|
response_type: "code",
|
|
23
|
-
provider: e.provider ?? "authkit"
|
|
25
|
+
provider: e.provider ?? "authkit",
|
|
26
|
+
state: t,
|
|
27
|
+
code_challenge: u(n),
|
|
28
|
+
code_challenge_method: "S256"
|
|
24
29
|
});
|
|
25
|
-
return e.
|
|
26
|
-
|
|
30
|
+
return e.loginHint && r.set("login_hint", e.loginHint), {
|
|
31
|
+
url: `${e.apiBase ?? s}/user_management/authorize?${r.toString()}`,
|
|
32
|
+
state: t,
|
|
33
|
+
codeVerifier: n
|
|
34
|
+
};
|
|
35
|
+
}, f = class extends Error {
|
|
27
36
|
status;
|
|
28
37
|
constructor(e, t) {
|
|
29
38
|
super(t), this.status = e, this.name = "WorkosExchangeError";
|
|
30
39
|
}
|
|
31
|
-
},
|
|
40
|
+
}, p = class extends f {
|
|
41
|
+
constructor(e) {
|
|
42
|
+
super(400, e), this.name = "WorkosStateMismatchError";
|
|
43
|
+
}
|
|
44
|
+
}, m = async (e) => {
|
|
32
45
|
if (!e.ok) {
|
|
33
46
|
let t = await e.text().catch(() => "");
|
|
34
|
-
throw new
|
|
47
|
+
throw new f(e.status, `WorkOS authenticate failed (${e.status}): ${t.slice(0, 200)}`);
|
|
35
48
|
}
|
|
36
49
|
let t = await e.json(), n = t.user;
|
|
37
|
-
if (!n?.id || !n.email) throw new
|
|
50
|
+
if (!n?.id || !n.email) throw new f(e.status, "WorkOS authenticate response missing user id/email");
|
|
38
51
|
return {
|
|
39
52
|
workosUserId: n.id,
|
|
40
53
|
email: n.email,
|
|
@@ -42,21 +55,25 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
42
55
|
lastName: n.last_name ?? null,
|
|
43
56
|
organizationId: t.organization_id ?? null
|
|
44
57
|
};
|
|
45
|
-
},
|
|
46
|
-
if (!e.code) throw new
|
|
47
|
-
|
|
58
|
+
}, h = async (e) => {
|
|
59
|
+
if (!e.code) throw new f(400, "workosAuthenticateWithCode: missing `code`");
|
|
60
|
+
if (!e.expectedState) throw new p("workosAuthenticateWithCode: no `expectedState` — the login was never started by this server, or the state cookie expired. Refusing to exchange the code.");
|
|
61
|
+
if (!e.state || !r(e.state, e.expectedState)) throw new p("workosAuthenticateWithCode: `state` does not match the value minted for this browser (possible CSRF).");
|
|
62
|
+
if (!e.codeVerifier) throw new f(400, "workosAuthenticateWithCode: missing `codeVerifier` (PKCE)");
|
|
63
|
+
return m(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/authenticate`, {
|
|
48
64
|
method: "POST",
|
|
49
65
|
headers: { "content-type": "application/json" },
|
|
50
66
|
body: JSON.stringify({
|
|
51
67
|
client_id: e.clientId,
|
|
52
68
|
client_secret: e.apiKey,
|
|
53
69
|
grant_type: "authorization_code",
|
|
54
|
-
code: e.code
|
|
70
|
+
code: e.code,
|
|
71
|
+
code_verifier: e.codeVerifier
|
|
55
72
|
})
|
|
56
73
|
}));
|
|
57
|
-
},
|
|
58
|
-
if (!e.email) throw new
|
|
59
|
-
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ??
|
|
74
|
+
}, g = async (e) => {
|
|
75
|
+
if (!e.email) throw new f(400, "workosSendMagicAuthCode: missing `email`");
|
|
76
|
+
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/magic_auth`, {
|
|
60
77
|
method: "POST",
|
|
61
78
|
headers: {
|
|
62
79
|
"content-type": "application/json",
|
|
@@ -66,12 +83,12 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
66
83
|
});
|
|
67
84
|
if (!t.ok) {
|
|
68
85
|
let e = await t.text().catch(() => "");
|
|
69
|
-
throw new
|
|
86
|
+
throw new f(t.status, `WorkOS magic-auth send failed (${t.status}): ${e.slice(0, 200)}`);
|
|
70
87
|
}
|
|
71
|
-
},
|
|
72
|
-
if (!e.code) throw new
|
|
73
|
-
if (!e.email) throw new
|
|
74
|
-
return
|
|
88
|
+
}, _ = async (e) => {
|
|
89
|
+
if (!e.code) throw new f(400, "workosAuthenticateWithMagicAuth: missing `code`");
|
|
90
|
+
if (!e.email) throw new f(400, "workosAuthenticateWithMagicAuth: missing `email`");
|
|
91
|
+
return m(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/authenticate`, {
|
|
75
92
|
method: "POST",
|
|
76
93
|
headers: { "content-type": "application/json" },
|
|
77
94
|
body: JSON.stringify({
|
|
@@ -82,8 +99,8 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
82
99
|
email: e.email
|
|
83
100
|
})
|
|
84
101
|
}));
|
|
85
|
-
},
|
|
86
|
-
let i = await (e.fetchImpl ?? fetch)(`${e.apiBase ??
|
|
102
|
+
}, v = "https://api.workos.com", y = async (e, t, n, r) => {
|
|
103
|
+
let i = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? v}${n}`, {
|
|
87
104
|
method: t,
|
|
88
105
|
headers: {
|
|
89
106
|
authorization: `Bearer ${e.apiKey}`,
|
|
@@ -93,18 +110,18 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
93
110
|
});
|
|
94
111
|
if (!i.ok) {
|
|
95
112
|
let e = await i.text().catch(() => "");
|
|
96
|
-
throw new
|
|
113
|
+
throw new f(i.status, `WorkOS ${t} ${n} failed (${i.status}): ${e.slice(0, 200)}`);
|
|
97
114
|
}
|
|
98
115
|
if (i.status !== 204) return await i.json();
|
|
99
|
-
},
|
|
100
|
-
if (!e.id) throw new
|
|
116
|
+
}, b = (e) => {
|
|
117
|
+
if (!e.id) throw new f(502, "WorkOS organization response missing id");
|
|
101
118
|
return {
|
|
102
119
|
id: e.id,
|
|
103
120
|
name: e.name ?? ""
|
|
104
121
|
};
|
|
105
|
-
},
|
|
106
|
-
if (!e.name) throw new
|
|
107
|
-
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ??
|
|
122
|
+
}, x = async (e) => {
|
|
123
|
+
if (!e.name) throw new f(400, "workosCreateOrganization: missing `name`");
|
|
124
|
+
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? v}/organizations`, {
|
|
108
125
|
method: "POST",
|
|
109
126
|
headers: {
|
|
110
127
|
authorization: `Bearer ${e.apiKey}`,
|
|
@@ -115,11 +132,11 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
115
132
|
});
|
|
116
133
|
if (!t.ok) {
|
|
117
134
|
let e = await t.text().catch(() => "");
|
|
118
|
-
throw new
|
|
135
|
+
throw new f(t.status, `WorkOS create organization failed (${t.status}): ${e.slice(0, 200)}`);
|
|
119
136
|
}
|
|
120
|
-
return
|
|
121
|
-
},
|
|
122
|
-
if (!e.id || !e.user_id || !e.organization_id) throw new
|
|
137
|
+
return b(await t.json());
|
|
138
|
+
}, S = async (e) => b(await y(e, "GET", `/organizations/${encodeURIComponent(e.organizationId)}`)), C = async (e) => b(await y(e, "PUT", `/organizations/${encodeURIComponent(e.organizationId)}`, { name: e.name })), w = (e) => {
|
|
139
|
+
if (!e.id || !e.user_id || !e.organization_id) throw new f(502, "WorkOS membership response missing id/user_id/organization_id");
|
|
123
140
|
return {
|
|
124
141
|
id: e.id,
|
|
125
142
|
userId: e.user_id,
|
|
@@ -127,11 +144,11 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
127
144
|
roleSlug: e.role?.slug ?? null,
|
|
128
145
|
status: e.status ?? "active"
|
|
129
146
|
};
|
|
130
|
-
},
|
|
147
|
+
}, T = async (e) => w(await y(e, "POST", "/user_management/organization_memberships", {
|
|
131
148
|
user_id: e.userId,
|
|
132
149
|
organization_id: e.organizationId,
|
|
133
150
|
...e.roleSlug ? { role_slug: e.roleSlug } : {}
|
|
134
|
-
})),
|
|
151
|
+
})), E = async (e) => {
|
|
135
152
|
let t = [], n;
|
|
136
153
|
for (let r = 0; r < 100; r++) {
|
|
137
154
|
let r = new URLSearchParams({
|
|
@@ -139,24 +156,24 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
139
156
|
limit: "100"
|
|
140
157
|
});
|
|
141
158
|
n && r.set("after", n);
|
|
142
|
-
let i = await
|
|
143
|
-
for (let e of i.data ?? []) t.push(
|
|
159
|
+
let i = await y(e, "GET", `/user_management/organization_memberships?${r.toString()}`);
|
|
160
|
+
for (let e of i.data ?? []) t.push(w(e));
|
|
144
161
|
let a = i.list_metadata?.after;
|
|
145
162
|
if (!a) break;
|
|
146
163
|
n = a;
|
|
147
164
|
}
|
|
148
165
|
return t;
|
|
149
|
-
},
|
|
150
|
-
await
|
|
151
|
-
},
|
|
152
|
-
if (!e.email) throw new
|
|
153
|
-
let t = await
|
|
166
|
+
}, D = async (e) => {
|
|
167
|
+
await y(e, "DELETE", `/user_management/organization_memberships/${encodeURIComponent(e.membershipId)}`);
|
|
168
|
+
}, O = async (e) => {
|
|
169
|
+
if (!e.email) throw new f(400, "workosCreateInvitation: missing `email`");
|
|
170
|
+
let t = await y(e, "POST", "/user_management/invitations", {
|
|
154
171
|
email: e.email,
|
|
155
172
|
organization_id: e.organizationId,
|
|
156
173
|
...e.roleSlug ? { role_slug: e.roleSlug } : {},
|
|
157
174
|
...e.inviterUserId ? { inviter_user_id: e.inviterUserId } : {}
|
|
158
175
|
});
|
|
159
|
-
if (!t.id || !t.email) throw new
|
|
176
|
+
if (!t.id || !t.email) throw new f(502, "WorkOS invitation response missing id/email");
|
|
160
177
|
return {
|
|
161
178
|
id: t.id,
|
|
162
179
|
email: t.email,
|
|
@@ -165,4 +182,4 @@ var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
|
165
182
|
};
|
|
166
183
|
};
|
|
167
184
|
//#endregion
|
|
168
|
-
export {
|
|
185
|
+
export { f as WorkosExchangeError, p as WorkosStateMismatchError, h as workosAuthenticateWithCode, _ as workosAuthenticateWithMagicAuth, d as workosBeginLogin, O as workosCreateInvitation, T as workosCreateMembership, x as workosCreateOrganization, D as workosDeleteMembership, S as workosGetOrganization, E as workosListUserMemberships, g as workosSendMagicAuthCode, o as workosStrategy, C as workosUpdateOrganization };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-auth-workos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "WorkOS-backed AuthStrategy for the Voltro framework. Verifies WorkOS AuthKit/SSO JWTs via JWKS and maps `org_id`→tenant. Composes via @voltro/protocol AuthStrategy alongside other IdP plugins.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"types": "./dist/index.d.ts",
|
|
23
23
|
"import": "./dist/index.js",
|
|
24
24
|
"default": "./dist/index.js"
|
|
25
|
-
}
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
26
27
|
},
|
|
27
28
|
"main": "./dist/index.js",
|
|
28
29
|
"module": "./dist/index.js",
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
"node": ">=24.0.0"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
|
-
"@voltro/protocol": "0.
|
|
36
|
+
"@voltro/protocol": "0.34.0"
|
|
36
37
|
},
|
|
37
38
|
"peerDependencies": {
|
|
38
39
|
"effect": "^3.22.0"
|