@voltro/plugin-auth-workos 0.81.0 → 0.82.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/dist/index.d.ts CHANGED
@@ -179,6 +179,22 @@ export declare interface WorkosLoginHandoff {
179
179
  readonly codeVerifier: string;
180
180
  }
181
181
 
182
+ export declare interface WorkosLogoutOptions {
183
+ /** {@link WorkosProfile.sessionId} of the sign-in being ended. */
184
+ readonly sessionId: string;
185
+ /** Where WorkOS sends the browser afterwards. Register it as a logout
186
+ * redirect of the WorkOS application. */
187
+ readonly returnTo?: string;
188
+ readonly apiBase?: string;
189
+ }
190
+
191
+ /**
192
+ * The URL that ends a WorkOS session — redirect the browser there at
193
+ * sign-out, after clearing your own session. Every application sharing that
194
+ * WorkOS session is signed out with it; the next sign-in asks again.
195
+ */
196
+ export declare const workosLogoutUrl: (o: WorkosLogoutOptions) => string;
197
+
182
198
  export declare interface WorkosMagicAuthSendOptions {
183
199
  /** WorkOS API key (`sk_…`) — sent as a Bearer token. Server-only. */
184
200
  readonly apiKey: string;
@@ -219,11 +235,23 @@ export declare interface WorkosOrganization {
219
235
  export declare interface WorkosProfile {
220
236
  readonly workosUserId: string;
221
237
  readonly email: string;
238
+ /** Whether WorkOS has verified that the person controls `email`. An app
239
+ * that finds or links an existing account BY EMAIL must refuse when this
240
+ * is false: an identity provider that hands out unverified addresses would
241
+ * otherwise let anyone claim another person's account. Read from WorkOS's
242
+ * `email_verified`; absent counts as unverified. */
243
+ readonly emailVerified: boolean;
222
244
  readonly firstName: string | null;
223
245
  readonly lastName: string | null;
224
246
  /** The WorkOS organization the user authenticated into, when SSO/org
225
247
  * membership applies. Null for a plain AuthKit user. */
226
248
  readonly organizationId: string | null;
249
+ /** The WorkOS session this sign-in opened — the `sid` claim of the access
250
+ * token WorkOS returned. Keep it (server-side, e.g. an HttpOnly cookie) to
251
+ * end that session at sign-out with {@link workosLogoutUrl}; without it,
252
+ * signing out of your app leaves the WorkOS session — and every other app
253
+ * sharing it — signed in. Null when WorkOS returned no access token. */
254
+ readonly sessionId: string | null;
227
255
  }
228
256
 
229
257
  /**
package/dist/index.js CHANGED
@@ -51,11 +51,26 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
51
51
  return {
52
52
  workosUserId: n.id,
53
53
  email: n.email,
54
+ emailVerified: n.email_verified === !0,
54
55
  firstName: n.first_name ?? null,
55
56
  lastName: n.last_name ?? null,
56
- organizationId: t.organization_id ?? null
57
+ organizationId: t.organization_id ?? null,
58
+ sessionId: h(t.access_token)
57
59
  };
58
- }, h = async (e) => {
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) => {
59
74
  if (!e.code) throw new f(400, "workosAuthenticateWithCode: missing `code`");
60
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.");
61
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).");
@@ -71,7 +86,7 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
71
86
  code_verifier: e.codeVerifier
72
87
  })
73
88
  }));
74
- }, g = async (e) => {
89
+ }, v = async (e) => {
75
90
  if (!e.email) throw new f(400, "workosSendMagicAuthCode: missing `email`");
76
91
  let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/magic_auth`, {
77
92
  method: "POST",
@@ -85,7 +100,7 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
85
100
  let e = await t.text().catch(() => "");
86
101
  throw new f(t.status, `WorkOS magic-auth send failed (${t.status}): ${e.slice(0, 200)}`);
87
102
  }
88
- }, _ = async (e) => {
103
+ }, y = async (e) => {
89
104
  if (!e.code) throw new f(400, "workosAuthenticateWithMagicAuth: missing `code`");
90
105
  if (!e.email) throw new f(400, "workosAuthenticateWithMagicAuth: missing `email`");
91
106
  return m(await (e.fetchImpl ?? fetch)(`${e.apiBase ?? s}/user_management/authenticate`, {
@@ -99,8 +114,8 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
99
114
  email: e.email
100
115
  })
101
116
  }));
102
- }, v = "https://api.workos.com", y = async (e, t, n, r) => {
103
- let i = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? v}${n}`, {
117
+ }, b = "https://api.workos.com", x = async (e, t, n, r) => {
118
+ let i = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? b}${n}`, {
104
119
  method: t,
105
120
  headers: {
106
121
  authorization: `Bearer ${e.apiKey}`,
@@ -113,15 +128,15 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
113
128
  throw new f(i.status, `WorkOS ${t} ${n} failed (${i.status}): ${e.slice(0, 200)}`);
114
129
  }
115
130
  if (i.status !== 204) return await i.json();
116
- }, b = (e) => {
131
+ }, S = (e) => {
117
132
  if (!e.id) throw new f(502, "WorkOS organization response missing id");
118
133
  return {
119
134
  id: e.id,
120
135
  name: e.name ?? ""
121
136
  };
122
- }, x = async (e) => {
137
+ }, C = async (e) => {
123
138
  if (!e.name) throw new f(400, "workosCreateOrganization: missing `name`");
124
- let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? v}/organizations`, {
139
+ let t = await (e.fetchImpl ?? fetch)(`${e.apiBase ?? b}/organizations`, {
125
140
  method: "POST",
126
141
  headers: {
127
142
  authorization: `Bearer ${e.apiKey}`,
@@ -134,8 +149,8 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
134
149
  let e = await t.text().catch(() => "");
135
150
  throw new f(t.status, `WorkOS create organization failed (${t.status}): ${e.slice(0, 200)}`);
136
151
  }
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) => {
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) => {
139
154
  if (!e.id || !e.user_id || !e.organization_id) throw new f(502, "WorkOS membership response missing id/user_id/organization_id");
140
155
  return {
141
156
  id: e.id,
@@ -144,11 +159,11 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
144
159
  roleSlug: e.role?.slug ?? null,
145
160
  status: e.status ?? "active"
146
161
  };
147
- }, T = async (e) => w(await y(e, "POST", "/user_management/organization_memberships", {
162
+ }, D = async (e) => E(await x(e, "POST", "/user_management/organization_memberships", {
148
163
  user_id: e.userId,
149
164
  organization_id: e.organizationId,
150
165
  ...e.roleSlug ? { role_slug: e.roleSlug } : {}
151
- })), E = async (e) => {
166
+ })), O = async (e) => {
152
167
  let t = [], n;
153
168
  for (let r = 0; r < 100; r++) {
154
169
  let r = new URLSearchParams({
@@ -156,18 +171,18 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
156
171
  limit: "100"
157
172
  });
158
173
  n && r.set("after", n);
159
- let i = await y(e, "GET", `/user_management/organization_memberships?${r.toString()}`);
160
- for (let e of i.data ?? []) t.push(w(e));
174
+ let i = await x(e, "GET", `/user_management/organization_memberships?${r.toString()}`);
175
+ for (let e of i.data ?? []) t.push(E(e));
161
176
  let a = i.list_metadata?.after;
162
177
  if (!a) break;
163
178
  n = a;
164
179
  }
165
180
  return t;
166
- }, D = async (e) => {
167
- await y(e, "DELETE", `/user_management/organization_memberships/${encodeURIComponent(e.membershipId)}`);
168
- }, O = async (e) => {
181
+ }, k = async (e) => {
182
+ await x(e, "DELETE", `/user_management/organization_memberships/${encodeURIComponent(e.membershipId)}`);
183
+ }, A = async (e) => {
169
184
  if (!e.email) throw new f(400, "workosCreateInvitation: missing `email`");
170
- let t = await y(e, "POST", "/user_management/invitations", {
185
+ let t = await x(e, "POST", "/user_management/invitations", {
171
186
  email: e.email,
172
187
  organization_id: e.organizationId,
173
188
  ...e.roleSlug ? { role_slug: e.roleSlug } : {},
@@ -182,4 +197,4 @@ var i = "https://api.workos.com", a = "wos-session", o = (t) => {
182
197
  };
183
198
  };
184
199
  //#endregion
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 };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-auth-workos",
3
- "version": "0.81.0",
3
+ "version": "0.82.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.81.0"
36
+ "@voltro/protocol": "0.82.0"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "effect": "^3.22.2"