@voltro/plugin-auth-workos 0.85.0 → 0.87.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 +5987 -0
- package/THIRD-PARTY-NOTICES.md +1122 -31
- package/dist/index.js +4 -200
- package/dist/oauth.js +105 -0
- package/dist/organizations.js +86 -0
- package/dist/strategy.js +18 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,200 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
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;
|
|
8
|
-
return e({
|
|
9
|
-
id: "workos",
|
|
10
|
-
jwksUrl: t.jwksUrl ?? `${i}/sso/jwks/${t.clientId}`,
|
|
11
|
-
issuer: t.issuer ?? i,
|
|
12
|
-
audience: t.clientId,
|
|
13
|
-
algorithms: ["RS256", "ES256"],
|
|
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) }
|
|
17
|
-
});
|
|
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({
|
|
22
|
-
client_id: e.clientId,
|
|
23
|
-
redirect_uri: e.redirectUri,
|
|
24
|
-
response_type: "code",
|
|
25
|
-
provider: e.provider ?? "authkit",
|
|
26
|
-
state: t,
|
|
27
|
-
code_challenge: u(n),
|
|
28
|
-
code_challenge_method: "S256"
|
|
29
|
-
});
|
|
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 {
|
|
36
|
-
status;
|
|
37
|
-
constructor(e, t) {
|
|
38
|
-
super(t), this.status = e, this.name = "WorkosExchangeError";
|
|
39
|
-
}
|
|
40
|
-
}, p = class extends f {
|
|
41
|
-
constructor(e) {
|
|
42
|
-
super(400, e), this.name = "WorkosStateMismatchError";
|
|
43
|
-
}
|
|
44
|
-
}, m = async (e) => {
|
|
45
|
-
if (!e.ok) {
|
|
46
|
-
let t = await e.text().catch(() => "");
|
|
47
|
-
throw new f(e.status, `WorkOS authenticate failed (${e.status}): ${t.slice(0, 200)}`);
|
|
48
|
-
}
|
|
49
|
-
let t = await e.json(), n = t.user;
|
|
50
|
-
if (!n?.id || !n.email) throw new f(e.status, "WorkOS authenticate response missing user id/email");
|
|
51
|
-
return {
|
|
52
|
-
workosUserId: n.id,
|
|
53
|
-
email: n.email,
|
|
54
|
-
emailVerified: n.email_verified === !0,
|
|
55
|
-
firstName: n.first_name ?? null,
|
|
56
|
-
lastName: n.last_name ?? null,
|
|
57
|
-
organizationId: t.organization_id ?? null,
|
|
58
|
-
sessionId: h(t.access_token)
|
|
59
|
-
};
|
|
60
|
-
}, h = (e) => {
|
|
61
|
-
let t = e?.split(".")[1];
|
|
62
|
-
if (!t) return null;
|
|
63
|
-
try {
|
|
64
|
-
let e = JSON.parse(Buffer.from(t, "base64url").toString("utf8"));
|
|
65
|
-
return typeof e.sid == "string" && e.sid !== "" ? e.sid : null;
|
|
66
|
-
} catch {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
}, g = (e) => {
|
|
70
|
-
if (!e.sessionId) throw Error("workosLogoutUrl: `sessionId` is required");
|
|
71
|
-
let t = new URLSearchParams({ session_id: e.sessionId });
|
|
72
|
-
return e.returnTo && t.set("return_to", e.returnTo), `${e.apiBase ?? s}/user_management/sessions/logout?${t.toString()}`;
|
|
73
|
-
}, _ = async (e) => {
|
|
74
|
-
if (!e.code) throw new f(400, "workosAuthenticateWithCode: missing `code`");
|
|
75
|
-
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.");
|
|
76
|
-
if (!e.state || !r(e.state, e.expectedState)) throw new p("workosAuthenticateWithCode: `state` does not match the value minted for this browser (possible CSRF).");
|
|
77
|
-
if (!e.codeVerifier) throw new f(400, "workosAuthenticateWithCode: missing `codeVerifier` (PKCE)");
|
|
78
|
-
return m(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/authenticate`, {
|
|
79
|
-
method: "POST",
|
|
80
|
-
headers: { "content-type": "application/json" },
|
|
81
|
-
body: JSON.stringify({
|
|
82
|
-
client_id: e.clientId,
|
|
83
|
-
client_secret: e.apiKey,
|
|
84
|
-
grant_type: "authorization_code",
|
|
85
|
-
code: e.code,
|
|
86
|
-
code_verifier: e.codeVerifier
|
|
87
|
-
})
|
|
88
|
-
}));
|
|
89
|
-
}, v = async (e) => {
|
|
90
|
-
if (!e.email) throw new f(400, "workosSendMagicAuthCode: missing `email`");
|
|
91
|
-
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/magic_auth`, {
|
|
92
|
-
method: "POST",
|
|
93
|
-
headers: {
|
|
94
|
-
"content-type": "application/json",
|
|
95
|
-
authorization: `Bearer ${e.apiKey}`
|
|
96
|
-
},
|
|
97
|
-
body: JSON.stringify({ email: e.email })
|
|
98
|
-
});
|
|
99
|
-
if (!t.ok) {
|
|
100
|
-
let e = await t.text().catch(() => "");
|
|
101
|
-
throw new f(t.status, `WorkOS magic-auth send failed (${t.status}): ${e.slice(0, 200)}`);
|
|
102
|
-
}
|
|
103
|
-
}, y = async (e) => {
|
|
104
|
-
if (!e.code) throw new f(400, "workosAuthenticateWithMagicAuth: missing `code`");
|
|
105
|
-
if (!e.email) throw new f(400, "workosAuthenticateWithMagicAuth: missing `email`");
|
|
106
|
-
return m(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/authenticate`, {
|
|
107
|
-
method: "POST",
|
|
108
|
-
headers: { "content-type": "application/json" },
|
|
109
|
-
body: JSON.stringify({
|
|
110
|
-
client_id: e.clientId,
|
|
111
|
-
client_secret: e.apiKey,
|
|
112
|
-
grant_type: "urn:workos:oauth:grant-type:magic-auth:code",
|
|
113
|
-
code: e.code,
|
|
114
|
-
email: e.email
|
|
115
|
-
})
|
|
116
|
-
}));
|
|
117
|
-
}, b = "https://api.workos.com", x = async (e, t, n, r) => {
|
|
118
|
-
let i = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? b}${n}`, {
|
|
119
|
-
method: t,
|
|
120
|
-
headers: {
|
|
121
|
-
authorization: `Bearer ${e.apiKey}`,
|
|
122
|
-
...r === void 0 ? {} : { "content-type": "application/json" }
|
|
123
|
-
},
|
|
124
|
-
...r === void 0 ? {} : { body: JSON.stringify(r) }
|
|
125
|
-
});
|
|
126
|
-
if (!i.ok) {
|
|
127
|
-
let e = await i.text().catch(() => "");
|
|
128
|
-
throw new f(i.status, `WorkOS ${t} ${n} failed (${i.status}): ${e.slice(0, 200)}`);
|
|
129
|
-
}
|
|
130
|
-
if (i.status !== 204) return await i.json();
|
|
131
|
-
}, S = (e) => {
|
|
132
|
-
if (!e.id) throw new f(502, "WorkOS organization response missing id");
|
|
133
|
-
return {
|
|
134
|
-
id: e.id,
|
|
135
|
-
name: e.name ?? ""
|
|
136
|
-
};
|
|
137
|
-
}, C = async (e) => {
|
|
138
|
-
if (!e.name) throw new f(400, "workosCreateOrganization: missing `name`");
|
|
139
|
-
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? b}/organizations`, {
|
|
140
|
-
method: "POST",
|
|
141
|
-
headers: {
|
|
142
|
-
authorization: `Bearer ${e.apiKey}`,
|
|
143
|
-
"content-type": "application/json",
|
|
144
|
-
...e.idempotencyKey ? { "idempotency-key": e.idempotencyKey } : {}
|
|
145
|
-
},
|
|
146
|
-
body: JSON.stringify({ name: e.name })
|
|
147
|
-
});
|
|
148
|
-
if (!t.ok) {
|
|
149
|
-
let e = await t.text().catch(() => "");
|
|
150
|
-
throw new f(t.status, `WorkOS create organization failed (${t.status}): ${e.slice(0, 200)}`);
|
|
151
|
-
}
|
|
152
|
-
return S(await t.json());
|
|
153
|
-
}, w = async (e) => S(await x(e, "GET", `/organizations/${encodeURIComponent(e.organizationId)}`)), T = async (e) => S(await x(e, "PUT", `/organizations/${encodeURIComponent(e.organizationId)}`, { name: e.name })), E = (e) => {
|
|
154
|
-
if (!e.id || !e.user_id || !e.organization_id) throw new f(502, "WorkOS membership response missing id/user_id/organization_id");
|
|
155
|
-
return {
|
|
156
|
-
id: e.id,
|
|
157
|
-
userId: e.user_id,
|
|
158
|
-
organizationId: e.organization_id,
|
|
159
|
-
roleSlug: e.role?.slug ?? null,
|
|
160
|
-
status: e.status ?? "active"
|
|
161
|
-
};
|
|
162
|
-
}, D = async (e) => E(await x(e, "POST", "/user_management/organization_memberships", {
|
|
163
|
-
user_id: e.userId,
|
|
164
|
-
organization_id: e.organizationId,
|
|
165
|
-
...e.roleSlug ? { role_slug: e.roleSlug } : {}
|
|
166
|
-
})), O = async (e) => {
|
|
167
|
-
let t = [], n;
|
|
168
|
-
for (let r = 0; r < 100; r++) {
|
|
169
|
-
let r = new URLSearchParams({
|
|
170
|
-
user_id: e.userId,
|
|
171
|
-
limit: "100"
|
|
172
|
-
});
|
|
173
|
-
n && r.set("after", n);
|
|
174
|
-
let i = await x(e, "GET", `/user_management/organization_memberships?${r.toString()}`);
|
|
175
|
-
for (let e of i.data ?? []) t.push(E(e));
|
|
176
|
-
let a = i.list_metadata?.after;
|
|
177
|
-
if (!a) break;
|
|
178
|
-
n = a;
|
|
179
|
-
}
|
|
180
|
-
return t;
|
|
181
|
-
}, k = async (e) => {
|
|
182
|
-
await x(e, "DELETE", `/user_management/organization_memberships/${encodeURIComponent(e.membershipId)}`);
|
|
183
|
-
}, A = async (e) => {
|
|
184
|
-
if (!e.email) throw new f(400, "workosCreateInvitation: missing `email`");
|
|
185
|
-
let t = await x(e, "POST", "/user_management/invitations", {
|
|
186
|
-
email: e.email,
|
|
187
|
-
organization_id: e.organizationId,
|
|
188
|
-
...e.roleSlug ? { role_slug: e.roleSlug } : {},
|
|
189
|
-
...e.inviterUserId ? { inviter_user_id: e.inviterUserId } : {}
|
|
190
|
-
});
|
|
191
|
-
if (!t.id || !t.email) throw new f(502, "WorkOS invitation response missing id/email");
|
|
192
|
-
return {
|
|
193
|
-
id: t.id,
|
|
194
|
-
email: t.email,
|
|
195
|
-
organizationId: t.organization_id ?? null,
|
|
196
|
-
state: t.state ?? "pending"
|
|
197
|
-
};
|
|
198
|
-
};
|
|
199
|
-
//#endregion
|
|
200
|
-
export { f as WorkosExchangeError, p as WorkosStateMismatchError, _ as workosAuthenticateWithCode, y as workosAuthenticateWithMagicAuth, d as workosBeginLogin, A as workosCreateInvitation, D as workosCreateMembership, C as workosCreateOrganization, k as workosDeleteMembership, w as workosGetOrganization, O as workosListUserMemberships, g as workosLogoutUrl, v as workosSendMagicAuthCode, o as workosStrategy, T as workosUpdateOrganization };
|
|
1
|
+
import { workosStrategy as e } from "./strategy.js";
|
|
2
|
+
import { WorkosExchangeError as t, WorkosStateMismatchError as n, workosAuthenticateWithCode as r, workosAuthenticateWithMagicAuth as i, workosBeginLogin as a, workosLogoutUrl as o, workosSendMagicAuthCode as s } from "./oauth.js";
|
|
3
|
+
import { workosCreateInvitation as c, workosCreateMembership as l, workosCreateOrganization as u, workosDeleteMembership as d, workosGetOrganization as f, workosListUserMemberships as p, workosUpdateOrganization as m } from "./organizations.js";
|
|
4
|
+
export { t as WorkosExchangeError, n as WorkosStateMismatchError, r as workosAuthenticateWithCode, i as workosAuthenticateWithMagicAuth, a as workosBeginLogin, c as workosCreateInvitation, l as workosCreateMembership, u as workosCreateOrganization, d as workosDeleteMembership, f as workosGetOrganization, p as workosListUserMemberships, o as workosLogoutUrl, s as workosSendMagicAuthCode, e as workosStrategy, m as workosUpdateOrganization };
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createHash as e, randomBytes as t } from "node:crypto";
|
|
2
|
+
import { timingSafeStringEqual as n } from "@voltro/protocol/session";
|
|
3
|
+
//#region src/oauth.ts
|
|
4
|
+
var r = "https://api.workos.com", i = (e) => e.toString("base64url"), a = () => i(t(32)), o = (t) => i(e("sha256").update(t, "ascii").digest()), s = (e) => {
|
|
5
|
+
if (!e.clientId) throw Error("workosBeginLogin: `clientId` is required");
|
|
6
|
+
if (!e.redirectUri) throw Error("workosBeginLogin: `redirectUri` is required");
|
|
7
|
+
let t = e.randomness?.state ?? a(), n = e.randomness?.codeVerifier ?? a(), i = new URLSearchParams({
|
|
8
|
+
client_id: e.clientId,
|
|
9
|
+
redirect_uri: e.redirectUri,
|
|
10
|
+
response_type: "code",
|
|
11
|
+
provider: e.provider ?? "authkit",
|
|
12
|
+
state: t,
|
|
13
|
+
code_challenge: o(n),
|
|
14
|
+
code_challenge_method: "S256"
|
|
15
|
+
});
|
|
16
|
+
return e.loginHint && i.set("login_hint", e.loginHint), {
|
|
17
|
+
url: `${e.apiBase ?? r}/user_management/authorize?${i.toString()}`,
|
|
18
|
+
state: t,
|
|
19
|
+
codeVerifier: n
|
|
20
|
+
};
|
|
21
|
+
}, c = class extends Error {
|
|
22
|
+
status;
|
|
23
|
+
constructor(e, t) {
|
|
24
|
+
super(t), this.status = e, this.name = "WorkosExchangeError";
|
|
25
|
+
}
|
|
26
|
+
}, l = class extends c {
|
|
27
|
+
constructor(e) {
|
|
28
|
+
super(400, e), this.name = "WorkosStateMismatchError";
|
|
29
|
+
}
|
|
30
|
+
}, u = async (e) => {
|
|
31
|
+
if (!e.ok) {
|
|
32
|
+
let t = await e.text().catch(() => "");
|
|
33
|
+
throw new c(e.status, `WorkOS authenticate failed (${e.status}): ${t.slice(0, 200)}`);
|
|
34
|
+
}
|
|
35
|
+
let t = await e.json(), n = t.user;
|
|
36
|
+
if (!n?.id || !n.email) throw new c(e.status, "WorkOS authenticate response missing user id/email");
|
|
37
|
+
return {
|
|
38
|
+
workosUserId: n.id,
|
|
39
|
+
email: n.email,
|
|
40
|
+
emailVerified: n.email_verified === !0,
|
|
41
|
+
firstName: n.first_name ?? null,
|
|
42
|
+
lastName: n.last_name ?? null,
|
|
43
|
+
organizationId: t.organization_id ?? null,
|
|
44
|
+
sessionId: d(t.access_token)
|
|
45
|
+
};
|
|
46
|
+
}, d = (e) => {
|
|
47
|
+
let t = e?.split(".")[1];
|
|
48
|
+
if (!t) return null;
|
|
49
|
+
try {
|
|
50
|
+
let e = JSON.parse(Buffer.from(t, "base64url").toString("utf8"));
|
|
51
|
+
return typeof e.sid == "string" && e.sid !== "" ? e.sid : null;
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}, f = (e) => {
|
|
56
|
+
if (!e.sessionId) throw Error("workosLogoutUrl: `sessionId` is required");
|
|
57
|
+
let t = new URLSearchParams({ session_id: e.sessionId });
|
|
58
|
+
return e.returnTo && t.set("return_to", e.returnTo), `${e.apiBase ?? r}/user_management/sessions/logout?${t.toString()}`;
|
|
59
|
+
}, p = async (e) => {
|
|
60
|
+
if (!e.code) throw new c(400, "workosAuthenticateWithCode: missing `code`");
|
|
61
|
+
if (!e.expectedState) throw new l("workosAuthenticateWithCode: no `expectedState` — the login was never started by this server, or the state cookie expired. Refusing to exchange the code.");
|
|
62
|
+
if (!e.state || !n(e.state, e.expectedState)) throw new l("workosAuthenticateWithCode: `state` does not match the value minted for this browser (possible CSRF).");
|
|
63
|
+
if (!e.codeVerifier) throw new c(400, "workosAuthenticateWithCode: missing `codeVerifier` (PKCE)");
|
|
64
|
+
return u(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? r}/user_management/authenticate`, {
|
|
65
|
+
method: "POST",
|
|
66
|
+
headers: { "content-type": "application/json" },
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
client_id: e.clientId,
|
|
69
|
+
client_secret: e.apiKey,
|
|
70
|
+
grant_type: "authorization_code",
|
|
71
|
+
code: e.code,
|
|
72
|
+
code_verifier: e.codeVerifier
|
|
73
|
+
})
|
|
74
|
+
}));
|
|
75
|
+
}, m = async (e) => {
|
|
76
|
+
if (!e.email) throw new c(400, "workosSendMagicAuthCode: missing `email`");
|
|
77
|
+
let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? r}/user_management/magic_auth`, {
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: {
|
|
80
|
+
"content-type": "application/json",
|
|
81
|
+
authorization: `Bearer ${e.apiKey}`
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify({ email: e.email })
|
|
84
|
+
});
|
|
85
|
+
if (!t.ok) {
|
|
86
|
+
let e = await t.text().catch(() => "");
|
|
87
|
+
throw new c(t.status, `WorkOS magic-auth send failed (${t.status}): ${e.slice(0, 200)}`);
|
|
88
|
+
}
|
|
89
|
+
}, h = async (e) => {
|
|
90
|
+
if (!e.code) throw new c(400, "workosAuthenticateWithMagicAuth: missing `code`");
|
|
91
|
+
if (!e.email) throw new c(400, "workosAuthenticateWithMagicAuth: missing `email`");
|
|
92
|
+
return u(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? r}/user_management/authenticate`, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: { "content-type": "application/json" },
|
|
95
|
+
body: JSON.stringify({
|
|
96
|
+
client_id: e.clientId,
|
|
97
|
+
client_secret: e.apiKey,
|
|
98
|
+
grant_type: "urn:workos:oauth:grant-type:magic-auth:code",
|
|
99
|
+
code: e.code,
|
|
100
|
+
email: e.email
|
|
101
|
+
})
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
104
|
+
//#endregion
|
|
105
|
+
export { c as WorkosExchangeError, l as WorkosStateMismatchError, p as workosAuthenticateWithCode, h as workosAuthenticateWithMagicAuth, s as workosBeginLogin, f as workosLogoutUrl, m as workosSendMagicAuthCode };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { WorkosExchangeError as e } from "./oauth.js";
|
|
2
|
+
//#region src/organizations.ts
|
|
3
|
+
var t = "https://api.workos.com", n = async (n, r, i, a) => {
|
|
4
|
+
let o = await (n.fetchImpl ?? fetch)(`${n.apiBase ?? t}${i}`, {
|
|
5
|
+
method: r,
|
|
6
|
+
headers: {
|
|
7
|
+
authorization: `Bearer ${n.apiKey}`,
|
|
8
|
+
...a === void 0 ? {} : { "content-type": "application/json" }
|
|
9
|
+
},
|
|
10
|
+
...a === void 0 ? {} : { body: JSON.stringify(a) }
|
|
11
|
+
});
|
|
12
|
+
if (!o.ok) {
|
|
13
|
+
let t = await o.text().catch(() => "");
|
|
14
|
+
throw new e(o.status, `WorkOS ${r} ${i} failed (${o.status}): ${t.slice(0, 200)}`);
|
|
15
|
+
}
|
|
16
|
+
if (o.status !== 204) return await o.json();
|
|
17
|
+
}, r = (t) => {
|
|
18
|
+
if (!t.id) throw new e(502, "WorkOS organization response missing id");
|
|
19
|
+
return {
|
|
20
|
+
id: t.id,
|
|
21
|
+
name: t.name ?? ""
|
|
22
|
+
};
|
|
23
|
+
}, i = async (n) => {
|
|
24
|
+
if (!n.name) throw new e(400, "workosCreateOrganization: missing `name`");
|
|
25
|
+
let i = await (n.fetchImpl ?? fetch)(`${n.apiBase ?? t}/organizations`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
authorization: `Bearer ${n.apiKey}`,
|
|
29
|
+
"content-type": "application/json",
|
|
30
|
+
...n.idempotencyKey ? { "idempotency-key": n.idempotencyKey } : {}
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify({ name: n.name })
|
|
33
|
+
});
|
|
34
|
+
if (!i.ok) {
|
|
35
|
+
let t = await i.text().catch(() => "");
|
|
36
|
+
throw new e(i.status, `WorkOS create organization failed (${i.status}): ${t.slice(0, 200)}`);
|
|
37
|
+
}
|
|
38
|
+
return r(await i.json());
|
|
39
|
+
}, a = async (e) => r(await n(e, "GET", `/organizations/${encodeURIComponent(e.organizationId)}`)), o = async (e) => r(await n(e, "PUT", `/organizations/${encodeURIComponent(e.organizationId)}`, { name: e.name })), s = (t) => {
|
|
40
|
+
if (!t.id || !t.user_id || !t.organization_id) throw new e(502, "WorkOS membership response missing id/user_id/organization_id");
|
|
41
|
+
return {
|
|
42
|
+
id: t.id,
|
|
43
|
+
userId: t.user_id,
|
|
44
|
+
organizationId: t.organization_id,
|
|
45
|
+
roleSlug: t.role?.slug ?? null,
|
|
46
|
+
status: t.status ?? "active"
|
|
47
|
+
};
|
|
48
|
+
}, c = async (e) => s(await n(e, "POST", "/user_management/organization_memberships", {
|
|
49
|
+
user_id: e.userId,
|
|
50
|
+
organization_id: e.organizationId,
|
|
51
|
+
...e.roleSlug ? { role_slug: e.roleSlug } : {}
|
|
52
|
+
})), l = async (e) => {
|
|
53
|
+
let t = [], r;
|
|
54
|
+
for (let i = 0; i < 100; i++) {
|
|
55
|
+
let i = new URLSearchParams({
|
|
56
|
+
user_id: e.userId,
|
|
57
|
+
limit: "100"
|
|
58
|
+
});
|
|
59
|
+
r && i.set("after", r);
|
|
60
|
+
let a = await n(e, "GET", `/user_management/organization_memberships?${i.toString()}`);
|
|
61
|
+
for (let e of a.data ?? []) t.push(s(e));
|
|
62
|
+
let o = a.list_metadata?.after;
|
|
63
|
+
if (!o) break;
|
|
64
|
+
r = o;
|
|
65
|
+
}
|
|
66
|
+
return t;
|
|
67
|
+
}, u = async (e) => {
|
|
68
|
+
await n(e, "DELETE", `/user_management/organization_memberships/${encodeURIComponent(e.membershipId)}`);
|
|
69
|
+
}, d = async (t) => {
|
|
70
|
+
if (!t.email) throw new e(400, "workosCreateInvitation: missing `email`");
|
|
71
|
+
let r = await n(t, "POST", "/user_management/invitations", {
|
|
72
|
+
email: t.email,
|
|
73
|
+
organization_id: t.organizationId,
|
|
74
|
+
...t.roleSlug ? { role_slug: t.roleSlug } : {},
|
|
75
|
+
...t.inviterUserId ? { inviter_user_id: t.inviterUserId } : {}
|
|
76
|
+
});
|
|
77
|
+
if (!r.id || !r.email) throw new e(502, "WorkOS invitation response missing id/email");
|
|
78
|
+
return {
|
|
79
|
+
id: r.id,
|
|
80
|
+
email: r.email,
|
|
81
|
+
organizationId: r.organization_id ?? null,
|
|
82
|
+
state: r.state ?? "pending"
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
export { d as workosCreateInvitation, c as workosCreateMembership, i as workosCreateOrganization, u as workosDeleteMembership, a as workosGetOrganization, l as workosListUserMemberships, o as workosUpdateOrganization };
|
package/dist/strategy.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jwtBearerStrategy as e } from "@voltro/protocol/jwt";
|
|
2
|
+
//#region src/strategy.ts
|
|
3
|
+
var t = "https://api.workos.com", n = "wos-session", r = (r) => {
|
|
4
|
+
if (!r.clientId) throw Error("workosStrategy: `clientId` is required");
|
|
5
|
+
let i = r.scopesFromClaims;
|
|
6
|
+
return e({
|
|
7
|
+
id: "workos",
|
|
8
|
+
jwksUrl: r.jwksUrl ?? `${t}/sso/jwks/${r.clientId}`,
|
|
9
|
+
issuer: r.issuer ?? t,
|
|
10
|
+
audience: r.clientId,
|
|
11
|
+
algorithms: ["RS256", "ES256"],
|
|
12
|
+
cookieName: r.cookieName === void 0 ? n : r.cookieName,
|
|
13
|
+
tenantIdFromClaims: (e) => r.tenantIdFromClaims?.(e) ?? (typeof e.org_id == "string" ? e.org_id : void 0) ?? r.defaultTenantId ?? null,
|
|
14
|
+
...i === void 0 ? {} : { scopesFromClaims: (e) => i(e) }
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
//#endregion
|
|
18
|
+
export { r as workosStrategy };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/plugin-auth-workos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"node": ">=24.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@voltro/protocol": "0.
|
|
36
|
+
"@voltro/protocol": "0.87.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"effect": "4.0.1"
|