@mastra/auth-studio 1.3.3 → 1.3.4-alpha.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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # @mastra/auth-studio
2
2
 
3
+ ## 1.3.4-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed reading request headers from Express-style plain header objects so cookie-based auth providers no longer throw and fail with a misleading 401. ([#21261](https://github.com/mastra-ai/mastra/pull/21261))
8
+
9
+ Related to https://github.com/mastra-ai/mastra/issues/21253
10
+
3
11
  ## 1.3.3
4
12
 
5
13
  ### Patch Changes
@@ -10,7 +10,7 @@
10
10
  * All known API resources.
11
11
  * Derived from SERVER_ROUTES paths in @mastra/server.
12
12
  */
13
- export declare const RESOURCES: readonly ["a2a", "agent-builder", "agent-controller", "agents", "auth", "background-tasks", "channels", "datasets", "embedders", "experiments", "infrastructure", "logs", "mcp", "memory", "observability", "processor-providers", "processors", "schedules", "scores", "stored-agents", "stored-mcp-clients", "stored-prompt-blocks", "stored-scorers", "stored-skills", "stored-workspaces", "system", "tool-providers", "tools", "vector", "vectors", "workflows", "workspaces"];
13
+ export declare const RESOURCES: readonly ["a2a", "agent-builder", "agent-controller", "agents", "auth", "background-tasks", "channels", "datasets", "embedders", "experiments", "infrastructure", "logs", "mcp", "memory", "observability", "processor-providers", "processors", "schedules", "scores", "stored-agents", "stored-mcp-clients", "stored-prompt-blocks", "stored-scorers", "stored-skills", "stored-workflows", "stored-workspaces", "system", "tool-providers", "tools", "vector", "vectors", "workflows", "workspaces"];
14
14
  /**
15
15
  * Resource type union.
16
16
  */
@@ -98,6 +98,8 @@ export declare const PERMISSION_PATTERNS: {
98
98
  readonly 'stored-scorers:*': "stored-scorers:*";
99
99
  /** Full access to stored skills */
100
100
  readonly 'stored-skills:*': "stored-skills:*";
101
+ /** Full access to stored workflows */
102
+ readonly 'stored-workflows:*': "stored-workflows:*";
101
103
  /** Full access to stored workspaces */
102
104
  readonly 'stored-workspaces:*': "stored-workspaces:*";
103
105
  /** Full access to system info */
@@ -238,6 +240,10 @@ export declare const PERMISSION_PATTERNS: {
238
240
  readonly 'stored-skills:read': "stored-skills:read";
239
241
  /** Create and modify stored skills */
240
242
  readonly 'stored-skills:write': "stored-skills:write";
243
+ /** View stored workflows */
244
+ readonly 'stored-workflows:read': "stored-workflows:read";
245
+ /** Create and modify stored workflows */
246
+ readonly 'stored-workflows:write': "stored-workflows:write";
241
247
  /** Delete stored workspaces */
242
248
  readonly 'stored-workspaces:delete': "stored-workspaces:delete";
243
249
  /** View stored workspaces */
@@ -305,7 +311,7 @@ export type PermissionPattern = keyof typeof PERMISSION_PATTERNS;
305
311
  /**
306
312
  * All valid resource:action permission combinations (excludes wildcards).
307
313
  */
308
- export declare const PERMISSIONS: readonly ["a2a:read", "a2a:write", "agent-builder:execute", "agent-builder:read", "agent-builder:write", "agent-controller:execute", "agent-controller:read", "agents:create", "agents:delete", "agents:execute", "agents:read", "agents:write", "auth:read", "background-tasks:read", "channels:read", "channels:write", "datasets:delete", "datasets:execute", "datasets:read", "datasets:write", "embedders:read", "experiments:read", "infrastructure:read", "logs:read", "mcp:execute", "mcp:read", "mcp:write", "memory:delete", "memory:execute", "memory:read", "memory:write", "observability:read", "observability:write", "processor-providers:read", "processors:execute", "processors:read", "schedules:delete", "schedules:execute", "schedules:read", "schedules:write", "scores:read", "scores:write", "stored-agents:delete", "stored-agents:publish", "stored-agents:read", "stored-agents:write", "stored-mcp-clients:delete", "stored-mcp-clients:publish", "stored-mcp-clients:read", "stored-mcp-clients:write", "stored-prompt-blocks:delete", "stored-prompt-blocks:publish", "stored-prompt-blocks:read", "stored-prompt-blocks:write", "stored-scorers:delete", "stored-scorers:publish", "stored-scorers:read", "stored-scorers:write", "stored-skills:delete", "stored-skills:publish", "stored-skills:read", "stored-skills:write", "stored-workspaces:delete", "stored-workspaces:read", "stored-workspaces:write", "system:read", "tool-providers:delete", "tool-providers:read", "tool-providers:write", "tools:execute", "tools:read", "vector:delete", "vector:execute", "vector:read", "vector:write", "vectors:read", "workflows:delete", "workflows:execute", "workflows:read", "workflows:write", "workspaces:delete", "workspaces:read", "workspaces:write"];
314
+ export declare const PERMISSIONS: readonly ["a2a:read", "a2a:write", "agent-builder:execute", "agent-builder:read", "agent-builder:write", "agent-controller:execute", "agent-controller:read", "agents:create", "agents:delete", "agents:execute", "agents:read", "agents:write", "auth:read", "background-tasks:read", "channels:read", "channels:write", "datasets:delete", "datasets:execute", "datasets:read", "datasets:write", "embedders:read", "experiments:read", "infrastructure:read", "logs:read", "mcp:execute", "mcp:read", "mcp:write", "memory:delete", "memory:execute", "memory:read", "memory:write", "observability:read", "observability:write", "processor-providers:read", "processors:execute", "processors:read", "schedules:delete", "schedules:execute", "schedules:read", "schedules:write", "scores:read", "scores:write", "stored-agents:delete", "stored-agents:publish", "stored-agents:read", "stored-agents:write", "stored-mcp-clients:delete", "stored-mcp-clients:publish", "stored-mcp-clients:read", "stored-mcp-clients:write", "stored-prompt-blocks:delete", "stored-prompt-blocks:publish", "stored-prompt-blocks:read", "stored-prompt-blocks:write", "stored-scorers:delete", "stored-scorers:publish", "stored-scorers:read", "stored-scorers:write", "stored-skills:delete", "stored-skills:publish", "stored-skills:read", "stored-skills:write", "stored-workflows:read", "stored-workflows:write", "stored-workspaces:delete", "stored-workspaces:read", "stored-workspaces:write", "system:read", "tool-providers:delete", "tool-providers:read", "tool-providers:write", "tools:execute", "tools:read", "vector:delete", "vector:execute", "vector:read", "vector:write", "vectors:read", "workflows:delete", "workflows:execute", "workflows:read", "workflows:write", "workspaces:delete", "workspaces:read", "workspaces:write"];
309
315
  /**
310
316
  * Specific permission type (e.g., 'agents:read', 'workflows:execute').
311
317
  */
@@ -441,6 +447,10 @@ export declare const MastraFGAPermissions: {
441
447
  readonly STORED_SKILLS_READ: "stored-skills:read";
442
448
  /** Create and modify stored skills */
443
449
  readonly STORED_SKILLS_WRITE: "stored-skills:write";
450
+ /** View stored workflows */
451
+ readonly STORED_WORKFLOWS_READ: "stored-workflows:read";
452
+ /** Create and modify stored workflows */
453
+ readonly STORED_WORKFLOWS_WRITE: "stored-workflows:write";
444
454
  /** Delete stored workspaces */
445
455
  readonly STORED_WORKSPACES_DELETE: "stored-workspaces:delete";
446
456
  /** View stored workspaces */
@@ -1,7 +1,7 @@
1
1
  export interface HonoRequestLike {
2
2
  raw?: Request;
3
- headers?: Headers;
4
- header(name: string): string | undefined;
3
+ headers?: Headers | Record<string, string | string[] | undefined>;
4
+ header?(name: string): string | undefined;
5
5
  }
6
6
  export type MastraAuthRequest = Request | HonoRequestLike;
7
7
  export type AuthenticateTokenFn<TUser, TResult = Promise<TUser | null>> = {
@@ -10,6 +10,10 @@ export type AuthenticateTokenFn<TUser, TResult = Promise<TUser | null>> = {
10
10
  export type AuthorizeUserFn<TUser, TResult = Promise<boolean> | boolean> = {
11
11
  bivarianceHack(user: TUser, request: MastraAuthRequest): TResult;
12
12
  }['bivarianceHack'];
13
+ /**
14
+ * Read a request header across fetch, Hono, and Express-style request shapes.
15
+ * Must not throw when `headers` is a plain object (Express `IncomingHttpHeaders`).
16
+ */
13
17
  export declare function getRequestHeader(request: MastraAuthRequest, name: string): string | null;
14
18
  export declare function getWebRequest(request: MastraAuthRequest): Request | undefined;
15
19
  export type Methods = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'ALL';
package/dist/index.cjs CHANGED
@@ -1,113 +1,25 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let crypto$1 = require("crypto");
3
- //#region ../../packages/_internals/auth/dist/ee-C8o0LZ3r.js
4
- /**
5
- * FGA enforcement utility for checking fine-grained authorization.
6
- *
7
- * @license Mastra Enterprise License - see ee/LICENSE
8
- */
9
- /**
10
- * Compound resource keys that expand to a set of per-family resources.
11
- * A granted `stored:<action>` is treated as matching any `stored-<family>:<action>`
12
- * (and `stored:*` matches any `stored-<family>:*`).
13
- */
14
- const RESOURCE_EXPANSIONS = { stored: [
15
- "stored-agents",
16
- "stored-mcp-clients",
17
- "stored-prompt-blocks",
18
- "stored-scorers",
19
- "stored-skills",
20
- "stored-workspaces"
21
- ] };
22
- /**
23
- * Check if a permission matches (including wildcard support).
24
- *
25
- * Permission format: `{resource}:{action}[:{resource-id}]`
26
- *
27
- * Examples:
28
- * - `*` matches everything
29
- * - `agents:*` matches `agents:read`, `agents:read:my-agent`
30
- * - `*:read` matches `agents:read`, `workflows:read` (action across all resources)
31
- * - `agents:read` matches `agents:read`, `agents:read:my-agent`
32
- * - `agents:read:my-agent` matches only `agents:read:my-agent`
33
- * - `agents:*:my-agent` matches `agents:read:my-agent`, `agents:write:my-agent`
34
- *
35
- * @param userPermission - Permission the user has
36
- * @param requiredPermission - Permission being checked
37
- * @returns True if permission matches
38
- */
39
- function matchesPermission(userPermission, requiredPermission) {
40
- if (userPermission === "*") return true;
41
- const grantedParts = userPermission.split(":");
42
- const requiredParts = requiredPermission.split(":");
43
- const expandedFamilies = RESOURCE_EXPANSIONS[grantedParts[0] ?? ""];
44
- if (expandedFamilies && expandedFamilies.includes(requiredParts[0] ?? "")) return matchesPermission([requiredParts[0], ...grantedParts.slice(1)].join(":"), requiredPermission);
45
- if (grantedParts.length < 2 || requiredParts.length < 2) return userPermission === requiredPermission;
46
- const [grantedResource, grantedAction, grantedId] = grantedParts;
47
- const [requiredResource, requiredAction, requiredId] = requiredParts;
48
- if (grantedResource === "*") {
49
- if (grantedAction === "*") {
50
- if (grantedId === void 0) return true;
51
- return grantedId === requiredId;
52
- }
53
- if (grantedAction !== requiredAction) return false;
54
- if (grantedId === void 0) return true;
55
- return grantedId === requiredId;
56
- }
57
- if (grantedResource !== requiredResource) return false;
58
- if (grantedAction === "*") {
59
- if (grantedId === void 0) return true;
60
- return grantedId === requiredId;
61
- }
62
- if (grantedAction !== requiredAction) return false;
63
- if (grantedId === void 0) return true;
64
- return grantedId === requiredId;
3
+ //#region ../../packages/_internals/auth/dist/types/index.js
4
+ function headerFromPlainObject(headers, name) {
5
+ const normalizedName = name.toLowerCase();
6
+ const matchingKey = Object.keys(headers).find((key) => key.toLowerCase() === normalizedName);
7
+ const value = matchingKey === void 0 ? void 0 : headers[matchingKey];
8
+ return Array.isArray(value) ? value[0] ?? null : value ?? null;
65
9
  }
66
10
  /**
67
- * Resolve permissions from user roles using a role mapping.
68
- *
69
- * This function translates provider-defined roles (from WorkOS, Okta, etc.)
70
- * to Mastra permissions using a configurable mapping.
71
- *
72
- * @example
73
- * ```typescript
74
- * const roleMapping = {
75
- * "Engineering": ["agents:*", "workflows:*"],
76
- * "Product": ["agents:read"],
77
- * "_default": [],
78
- * };
79
- *
80
- * // User has "Engineering" and "QA" roles
81
- * const permissions = resolvePermissionsFromMapping(
82
- * ["Engineering", "QA"],
83
- * roleMapping
84
- * );
85
- * // Result: ["agents:*", "workflows:*"] (QA is unmapped, gets _default)
86
- * ```
87
- *
88
- * @param roles - User's roles from the identity provider
89
- * @param mapping - Role to permission mapping
90
- * @returns Array of resolved permissions
11
+ * Read a request header across fetch, Hono, and Express-style request shapes.
12
+ * Must not throw when `headers` is a plain object (Express `IncomingHttpHeaders`).
91
13
  */
92
- function resolvePermissionsFromMapping(roles, mapping) {
93
- const permissions = /* @__PURE__ */ new Set();
94
- const defaultPerms = mapping["_default"] ?? [];
95
- for (const role of roles) {
96
- const rolePerms = mapping[role];
97
- if (rolePerms) for (const perm of rolePerms) permissions.add(perm);
98
- else for (const perm of defaultPerms) permissions.add(perm);
99
- }
100
- return Array.from(permissions);
14
+ function getRequestHeader(request, name) {
15
+ if (request instanceof Request) return request.headers.get(name);
16
+ if (request.raw instanceof Request) return request.raw.headers.get(name);
17
+ const headers = request.headers;
18
+ if (headers instanceof Headers) return headers.get(name);
19
+ if (typeof request.header === "function") return request.header(name) ?? null;
20
+ if (headers && typeof headers === "object") return headerFromPlainObject(headers, name);
21
+ return null;
101
22
  }
102
- /**
103
- * @mastra/core/auth/ee
104
- *
105
- * Enterprise authentication capabilities for Mastra.
106
- * This code is licensed under the Mastra Enterprise License - see ee/LICENSE.
107
- *
108
- * @license Mastra Enterprise License - see ee/LICENSE
109
- * @packageDocumentation
110
- */
111
23
  //#endregion
112
24
  //#region ../../packages/_internal-core/dist/logger/index.js
113
25
  const RegisteredLogger = {
@@ -316,11 +228,116 @@ var MastraAuthProvider = class extends MastraBase {
316
228
  }
317
229
  };
318
230
  //#endregion
319
- //#region src/index.ts
320
- function getRequestHeader(request, name) {
321
- if (request instanceof Request) return request.headers.get(name);
322
- return request.raw?.headers.get(name) ?? request.headers?.get(name) ?? request.header(name) ?? null;
231
+ //#region ../../packages/_internals/auth/dist/ee-DXvSoTl7.js
232
+ /**
233
+ * FGA enforcement utility for checking fine-grained authorization.
234
+ *
235
+ * @license Mastra Enterprise License - see ee/LICENSE
236
+ */
237
+ /**
238
+ * Compound resource keys that expand to a set of per-family resources.
239
+ * A granted `stored:<action>` is treated as matching any `stored-<family>:<action>`
240
+ * (and `stored:*` matches any `stored-<family>:*`).
241
+ */
242
+ const RESOURCE_EXPANSIONS = { stored: [
243
+ "stored-agents",
244
+ "stored-mcp-clients",
245
+ "stored-prompt-blocks",
246
+ "stored-scorers",
247
+ "stored-skills",
248
+ "stored-workspaces"
249
+ ] };
250
+ /**
251
+ * Check if a permission matches (including wildcard support).
252
+ *
253
+ * Permission format: `{resource}:{action}[:{resource-id}]`
254
+ *
255
+ * Examples:
256
+ * - `*` matches everything
257
+ * - `agents:*` matches `agents:read`, `agents:read:my-agent`
258
+ * - `*:read` matches `agents:read`, `workflows:read` (action across all resources)
259
+ * - `agents:read` matches `agents:read`, `agents:read:my-agent`
260
+ * - `agents:read:my-agent` matches only `agents:read:my-agent`
261
+ * - `agents:*:my-agent` matches `agents:read:my-agent`, `agents:write:my-agent`
262
+ *
263
+ * @param userPermission - Permission the user has
264
+ * @param requiredPermission - Permission being checked
265
+ * @returns True if permission matches
266
+ */
267
+ function matchesPermission(userPermission, requiredPermission) {
268
+ if (userPermission === "*") return true;
269
+ const grantedParts = userPermission.split(":");
270
+ const requiredParts = requiredPermission.split(":");
271
+ const expandedFamilies = RESOURCE_EXPANSIONS[grantedParts[0] ?? ""];
272
+ if (expandedFamilies && expandedFamilies.includes(requiredParts[0] ?? "")) return matchesPermission([requiredParts[0], ...grantedParts.slice(1)].join(":"), requiredPermission);
273
+ if (grantedParts.length < 2 || requiredParts.length < 2) return userPermission === requiredPermission;
274
+ const [grantedResource, grantedAction, grantedId] = grantedParts;
275
+ const [requiredResource, requiredAction, requiredId] = requiredParts;
276
+ if (grantedResource === "*") {
277
+ if (grantedAction === "*") {
278
+ if (grantedId === void 0) return true;
279
+ return grantedId === requiredId;
280
+ }
281
+ if (grantedAction !== requiredAction) return false;
282
+ if (grantedId === void 0) return true;
283
+ return grantedId === requiredId;
284
+ }
285
+ if (grantedResource !== requiredResource) return false;
286
+ if (grantedAction === "*") {
287
+ if (grantedId === void 0) return true;
288
+ return grantedId === requiredId;
289
+ }
290
+ if (grantedAction !== requiredAction) return false;
291
+ if (grantedId === void 0) return true;
292
+ return grantedId === requiredId;
293
+ }
294
+ /**
295
+ * Resolve permissions from user roles using a role mapping.
296
+ *
297
+ * This function translates provider-defined roles (from WorkOS, Okta, etc.)
298
+ * to Mastra permissions using a configurable mapping.
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const roleMapping = {
303
+ * "Engineering": ["agents:*", "workflows:*"],
304
+ * "Product": ["agents:read"],
305
+ * "_default": [],
306
+ * };
307
+ *
308
+ * // User has "Engineering" and "QA" roles
309
+ * const permissions = resolvePermissionsFromMapping(
310
+ * ["Engineering", "QA"],
311
+ * roleMapping
312
+ * );
313
+ * // Result: ["agents:*", "workflows:*"] (QA is unmapped, gets _default)
314
+ * ```
315
+ *
316
+ * @param roles - User's roles from the identity provider
317
+ * @param mapping - Role to permission mapping
318
+ * @returns Array of resolved permissions
319
+ */
320
+ function resolvePermissionsFromMapping(roles, mapping) {
321
+ const permissions = /* @__PURE__ */ new Set();
322
+ const defaultPerms = mapping["_default"] ?? [];
323
+ for (const role of roles) {
324
+ const rolePerms = mapping[role];
325
+ if (rolePerms) for (const perm of rolePerms) permissions.add(perm);
326
+ else for (const perm of defaultPerms) permissions.add(perm);
327
+ }
328
+ return Array.from(permissions);
323
329
  }
330
+ /**
331
+ * @mastra/core/auth/ee
332
+ *
333
+ * Enterprise authentication capabilities for Mastra.
334
+ * This code is licensed under the Mastra Enterprise License - see ee/LICENSE.
335
+ *
336
+ * @license Mastra Enterprise License - see ee/LICENSE
337
+ * @packageDocumentation
338
+ */
339
+ //#endregion
340
+ //#region src/index.ts
324
341
  const COOKIE_NAME = "wos-session";
325
342
  /**
326
343
  * Upper bound for shared-API verification fetches. Matches the platform API