@mastra/auth-auth0 0.10.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.
@@ -0,0 +1 @@
1
+ export { MastraAuthAuth0 } from './_tsup-dts-rollup.cjs';
@@ -0,0 +1 @@
1
+ export { MastraAuthAuth0 } from './_tsup-dts-rollup.js';
package/dist/index.js ADDED
@@ -0,0 +1,355 @@
1
+ import { SpanKind, trace, context, propagation, SpanStatusCode } from './chunk-JLXWUSDO.js';
2
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
3
+
4
+ // ../../packages/core/dist/chunk-EWDGXKOQ.js
5
+ function hasActiveTelemetry(tracerName = "default-tracer") {
6
+ try {
7
+ return !!trace.getTracer(tracerName);
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function getBaggageValues(ctx) {
13
+ const currentBaggage = propagation.getBaggage(ctx);
14
+ const requestId = currentBaggage?.getEntry("http.request_id")?.value;
15
+ const componentName = currentBaggage?.getEntry("componentName")?.value;
16
+ const runId = currentBaggage?.getEntry("runId")?.value;
17
+ return {
18
+ requestId,
19
+ componentName,
20
+ runId
21
+ };
22
+ }
23
+ function withSpan(options) {
24
+ return function(_target, propertyKey, descriptor) {
25
+ if (!descriptor || typeof descriptor === "number") return;
26
+ const originalMethod = descriptor.value;
27
+ const methodName = String(propertyKey);
28
+ descriptor.value = function(...args) {
29
+ if (options?.skipIfNoTelemetry && !hasActiveTelemetry(options?.tracerName)) {
30
+ return originalMethod.apply(this, args);
31
+ }
32
+ const tracer = trace.getTracer(options?.tracerName ?? "default-tracer");
33
+ let spanName;
34
+ let spanKind;
35
+ if (typeof options === "string") {
36
+ spanName = options;
37
+ } else if (options) {
38
+ spanName = options.spanName || methodName;
39
+ spanKind = options.spanKind;
40
+ } else {
41
+ spanName = methodName;
42
+ }
43
+ const span = tracer.startSpan(spanName, { kind: spanKind });
44
+ let ctx = trace.setSpan(context.active(), span);
45
+ args.forEach((arg, index) => {
46
+ try {
47
+ span.setAttribute(`${spanName}.argument.${index}`, JSON.stringify(arg));
48
+ } catch {
49
+ span.setAttribute(`${spanName}.argument.${index}`, "[Not Serializable]");
50
+ }
51
+ });
52
+ const { requestId, componentName, runId } = getBaggageValues(ctx);
53
+ if (requestId) {
54
+ span.setAttribute("http.request_id", requestId);
55
+ }
56
+ if (componentName) {
57
+ span.setAttribute("componentName", componentName);
58
+ span.setAttribute("runId", runId);
59
+ } else if (this && this.name) {
60
+ span.setAttribute("componentName", this.name);
61
+ span.setAttribute("runId", this.runId);
62
+ ctx = propagation.setBaggage(
63
+ ctx,
64
+ propagation.createBaggage({
65
+ // @ts-ignore
66
+ componentName: { value: this.name },
67
+ // @ts-ignore
68
+ runId: { value: this.runId },
69
+ // @ts-ignore
70
+ "http.request_id": { value: requestId }
71
+ })
72
+ );
73
+ }
74
+ let result;
75
+ try {
76
+ result = context.with(ctx, () => originalMethod.apply(this, args));
77
+ if (result instanceof Promise) {
78
+ return result.then((resolvedValue) => {
79
+ try {
80
+ span.setAttribute(`${spanName}.result`, JSON.stringify(resolvedValue));
81
+ } catch {
82
+ span.setAttribute(`${spanName}.result`, "[Not Serializable]");
83
+ }
84
+ return resolvedValue;
85
+ }).finally(() => span.end());
86
+ }
87
+ try {
88
+ span.setAttribute(`${spanName}.result`, JSON.stringify(result));
89
+ } catch {
90
+ span.setAttribute(`${spanName}.result`, "[Not Serializable]");
91
+ }
92
+ return result;
93
+ } catch (error) {
94
+ span.setStatus({
95
+ code: SpanStatusCode.ERROR,
96
+ message: error instanceof Error ? error.message : "Unknown error"
97
+ });
98
+ if (error instanceof Error) {
99
+ span.recordException(error);
100
+ }
101
+ throw error;
102
+ } finally {
103
+ if (!(result instanceof Promise)) {
104
+ span.end();
105
+ }
106
+ }
107
+ };
108
+ return descriptor;
109
+ };
110
+ }
111
+ function InstrumentClass(options) {
112
+ return function(target) {
113
+ const methods = Object.getOwnPropertyNames(target.prototype);
114
+ methods.forEach((method) => {
115
+ if (options?.excludeMethods?.includes(method) || method === "constructor") return;
116
+ if (options?.methodFilter && !options.methodFilter(method)) return;
117
+ const descriptor = Object.getOwnPropertyDescriptor(target.prototype, method);
118
+ if (descriptor && typeof descriptor.value === "function") {
119
+ Object.defineProperty(
120
+ target.prototype,
121
+ method,
122
+ withSpan({
123
+ spanName: options?.prefix ? `${options.prefix}.${method}` : method,
124
+ skipIfNoTelemetry: true,
125
+ spanKind: options?.spanKind || SpanKind.INTERNAL,
126
+ tracerName: options?.tracerName
127
+ })(target, method, descriptor)
128
+ );
129
+ }
130
+ });
131
+ return target;
132
+ };
133
+ }
134
+
135
+ // ../../packages/core/dist/chunk-XXVGT7SJ.js
136
+ var RegisteredLogger = {
137
+ LLM: "LLM"};
138
+ var LogLevel = {
139
+ DEBUG: "debug",
140
+ INFO: "info",
141
+ WARN: "warn",
142
+ ERROR: "error"};
143
+ var MastraLogger = class {
144
+ name;
145
+ level;
146
+ transports;
147
+ constructor(options = {}) {
148
+ this.name = options.name || "Mastra";
149
+ this.level = options.level || LogLevel.ERROR;
150
+ this.transports = new Map(Object.entries(options.transports || {}));
151
+ }
152
+ getTransports() {
153
+ return this.transports;
154
+ }
155
+ async getLogs(transportId) {
156
+ if (!transportId || !this.transports.has(transportId)) {
157
+ return [];
158
+ }
159
+ return this.transports.get(transportId).getLogs() ?? [];
160
+ }
161
+ async getLogsByRunId({ transportId, runId }) {
162
+ if (!transportId || !this.transports.has(transportId) || !runId) {
163
+ return [];
164
+ }
165
+ return this.transports.get(transportId).getLogsByRunId({ runId }) ?? [];
166
+ }
167
+ };
168
+ var ConsoleLogger = class extends MastraLogger {
169
+ constructor(options = {}) {
170
+ super(options);
171
+ }
172
+ debug(message, ...args) {
173
+ if (this.level === LogLevel.DEBUG) {
174
+ console.debug(message, ...args);
175
+ }
176
+ }
177
+ info(message, ...args) {
178
+ if (this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
179
+ console.info(message, ...args);
180
+ }
181
+ }
182
+ warn(message, ...args) {
183
+ if (this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
184
+ console.warn(message, ...args);
185
+ }
186
+ }
187
+ error(message, ...args) {
188
+ if (this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
189
+ console.error(message, ...args);
190
+ }
191
+ }
192
+ async getLogs(_transportId) {
193
+ return [];
194
+ }
195
+ async getLogsByRunId(_args) {
196
+ return [];
197
+ }
198
+ };
199
+
200
+ // ../../packages/core/dist/chunk-JOCKZ2US.js
201
+ var MastraBase = class {
202
+ component = RegisteredLogger.LLM;
203
+ logger;
204
+ name;
205
+ telemetry;
206
+ constructor({ component, name }) {
207
+ this.component = component || RegisteredLogger.LLM;
208
+ this.name = name;
209
+ this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
210
+ }
211
+ /**
212
+ * Set the logger for the agent
213
+ * @param logger
214
+ */
215
+ __setLogger(logger) {
216
+ this.logger = logger;
217
+ if (this.component !== RegisteredLogger.LLM) {
218
+ this.logger.debug(`Logger updated [component=${this.component}] [name=${this.name}]`);
219
+ }
220
+ }
221
+ /**
222
+ * Set the telemetry for the
223
+ * @param telemetry
224
+ */
225
+ __setTelemetry(telemetry) {
226
+ this.telemetry = telemetry;
227
+ if (this.component !== RegisteredLogger.LLM) {
228
+ this.logger.debug(`Telemetry updated [component=${this.component}] [name=${this.telemetry.name}]`);
229
+ }
230
+ }
231
+ /**
232
+ * Get the telemetry on the vector
233
+ * @returns telemetry
234
+ */
235
+ __getTelemetry() {
236
+ return this.telemetry;
237
+ }
238
+ /*
239
+ get experimental_telemetry config
240
+ */
241
+ get experimental_telemetry() {
242
+ return this.telemetry ? {
243
+ // tracer: this.telemetry.tracer,
244
+ tracer: this.telemetry.getBaggageTracer(),
245
+ isEnabled: !!this.telemetry.tracer
246
+ } : void 0;
247
+ }
248
+ };
249
+
250
+ // ../../packages/core/dist/chunk-C6A6W6XS.js
251
+ var __create = Object.create;
252
+ var __defProp = Object.defineProperty;
253
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
254
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
255
+ var __typeError = (msg) => {
256
+ throw TypeError(msg);
257
+ };
258
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
259
+ enumerable: true,
260
+ configurable: true,
261
+ writable: true,
262
+ value
263
+ }) : obj[key] = value;
264
+ var __name = (target, value) => __defProp(target, "name", {
265
+ value,
266
+ configurable: true
267
+ });
268
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
269
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
270
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
271
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({
272
+ kind: __decoratorStrings[kind],
273
+ name,
274
+ metadata,
275
+ addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null))
276
+ });
277
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
278
+ var __runInitializers = (array, flags, self, value) => {
279
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) fns[i].call(self) ;
280
+ return value;
281
+ };
282
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
283
+ var it, done, ctx, k = flags & 7, p = false;
284
+ var j = 0;
285
+ var extraInitializers = array[j] || (array[j] = []);
286
+ var desc = k && ((target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(target , name));
287
+ __name(target, name);
288
+ for (var i = decorators.length - 1; i >= 0; i--) {
289
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
290
+ it = (0, decorators[i])(target, ctx), done._ = 1;
291
+ __expectFn(it) && (target = it);
292
+ }
293
+ return __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
294
+ };
295
+
296
+ // ../../packages/core/dist/server/index.js
297
+ var _MastraAuthProvider_decorators;
298
+ var _init;
299
+ var _a;
300
+ _MastraAuthProvider_decorators = [InstrumentClass({
301
+ prefix: "auth",
302
+ excludeMethods: ["__setTools", "__setLogger", "__setTelemetry", "#log"]
303
+ })];
304
+ var MastraAuthProvider = class extends (_a = MastraBase) {
305
+ constructor(options) {
306
+ super({
307
+ component: "AUTH",
308
+ name: options?.name
309
+ });
310
+ if (options?.authorizeUser) {
311
+ this.authorizeUser = options.authorizeUser.bind(this);
312
+ }
313
+ }
314
+ registerOptions(opts) {
315
+ if (opts?.authorizeUser) {
316
+ this.authorizeUser = opts.authorizeUser.bind(this);
317
+ }
318
+ }
319
+ };
320
+ MastraAuthProvider = /* @__PURE__ */ ((_) => {
321
+ _init = __decoratorStart(_a);
322
+ MastraAuthProvider = __decorateElement(_init, 0, "MastraAuthProvider", _MastraAuthProvider_decorators, MastraAuthProvider);
323
+ __runInitializers(_init, 1, MastraAuthProvider);
324
+ return MastraAuthProvider;
325
+ })();
326
+ var MastraAuthAuth0 = class extends MastraAuthProvider {
327
+ domain;
328
+ audience;
329
+ constructor(options) {
330
+ super({ name: options?.name ?? "auth0" });
331
+ const domain = options?.domain ?? process.env.AUTH0_DOMAIN;
332
+ const audience = options?.audience ?? process.env.AUTH0_AUDIENCE;
333
+ if (!domain || !audience) {
334
+ throw new Error(
335
+ "Auth0 domain and audience are required, please provide them in the options or set the environment variables AUTH0_DOMAIN and AUTH0_AUDIENCE"
336
+ );
337
+ }
338
+ this.domain = domain;
339
+ this.audience = audience;
340
+ this.registerOptions(options);
341
+ }
342
+ async authenticateToken(token) {
343
+ const JWKS = createRemoteJWKSet(new URL(`https://${this.domain}/.well-known/jwks.json`));
344
+ const { payload } = await jwtVerify(token, JWKS, {
345
+ issuer: `https://${this.domain}/`,
346
+ audience: this.audience
347
+ });
348
+ return payload;
349
+ }
350
+ async authorizeUser(user) {
351
+ return !!user;
352
+ }
353
+ };
354
+
355
+ export { MastraAuthAuth0 };
@@ -0,0 +1,6 @@
1
+ import { createConfig } from '@internal/lint/eslint';
2
+
3
+ const config = await createConfig();
4
+
5
+ /** @type {import("eslint").Linter.Config[]} */
6
+ export default [...config];
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@mastra/auth-auth0",
3
+ "version": "0.10.0",
4
+ "description": "Mastra Auth0 Auth integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "./package.json": "./package.json"
20
+ },
21
+ "license": "Elastic-2.0",
22
+ "dependencies": {
23
+ "jose": "^6.0.11"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^22.13.1",
27
+ "eslint": "^9.25.1",
28
+ "tsup": "^8.4.0",
29
+ "typescript": "^5.8.3",
30
+ "vitest": "^2.1.9",
31
+ "@internal/lint": "0.0.8",
32
+ "@mastra/core": "0.10.2"
33
+ },
34
+ "scripts": {
35
+ "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake",
36
+ "build:watch": "pnpm build --watch",
37
+ "test": "vitest run",
38
+ "lint": "eslint ."
39
+ }
40
+ }
@@ -0,0 +1,112 @@
1
+ import { jwtVerify, createRemoteJWKSet } from 'jose';
2
+ import { beforeEach, afterEach, describe, expect, test, vi } from 'vitest';
3
+ import { MastraAuthAuth0 } from './index';
4
+
5
+ // Mock jose library
6
+ vi.mock('jose', () => ({
7
+ createRemoteJWKSet: vi.fn(),
8
+ jwtVerify: vi.fn(),
9
+ }));
10
+
11
+ describe('MastraAuthAuth0', () => {
12
+ beforeEach(() => {
13
+ process.env.AUTH0_DOMAIN = 'test-domain.auth0.com';
14
+ process.env.AUTH0_AUDIENCE = 'test-audience';
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ afterEach(() => {
19
+ delete process.env.AUTH0_DOMAIN;
20
+ delete process.env.AUTH0_AUDIENCE;
21
+ });
22
+
23
+ describe('constructor', () => {
24
+ test('initializes with environment variables', () => {
25
+ const auth0 = new MastraAuthAuth0();
26
+ expect(auth0['domain']).toBe('test-domain.auth0.com');
27
+ expect(auth0['audience']).toBe('test-audience');
28
+ });
29
+
30
+ test('initializes with provided options', () => {
31
+ const auth0 = new MastraAuthAuth0({
32
+ domain: 'custom-domain.auth0.com',
33
+ audience: 'custom-audience',
34
+ });
35
+ expect(auth0['domain']).toBe('custom-domain.auth0.com');
36
+ expect(auth0['audience']).toBe('custom-audience');
37
+ });
38
+
39
+ test('throws error when domain is missing', () => {
40
+ delete process.env.AUTH0_DOMAIN;
41
+ expect(() => new MastraAuthAuth0()).toThrow();
42
+ });
43
+
44
+ test('throws error when audience is missing', () => {
45
+ delete process.env.AUTH0_AUDIENCE;
46
+ expect(() => new MastraAuthAuth0()).toThrow();
47
+ });
48
+ });
49
+
50
+ describe('authenticateToken', () => {
51
+ test('verifies JWT and returns payload', async () => {
52
+ const mockJWKS = vi.fn();
53
+ (createRemoteJWKSet as any).mockReturnValue(mockJWKS);
54
+ (jwtVerify as any).mockResolvedValue({
55
+ payload: { sub: 'user123', permissions: ['read'] },
56
+ });
57
+
58
+ const auth0 = new MastraAuthAuth0();
59
+ const result = await auth0.authenticateToken('test-token');
60
+
61
+ expect(createRemoteJWKSet).toHaveBeenCalledWith(new URL('https://test-domain.auth0.com/.well-known/jwks.json'));
62
+ expect(jwtVerify).toHaveBeenCalledWith('test-token', mockJWKS, {
63
+ issuer: 'https://test-domain.auth0.com/',
64
+ audience: 'test-audience',
65
+ });
66
+ expect(result).toEqual({ sub: 'user123', permissions: ['read'] });
67
+ });
68
+
69
+ test('handles JWT verification failure', async () => {
70
+ (createRemoteJWKSet as any).mockReturnValue(vi.fn());
71
+ (jwtVerify as any).mockRejectedValue(new Error('Invalid token'));
72
+
73
+ const auth0 = new MastraAuthAuth0();
74
+ await expect(auth0.authenticateToken('invalid-token')).rejects.toThrow('Invalid token');
75
+ });
76
+ });
77
+
78
+ describe('authorizeUser', () => {
79
+ test('returns true for valid user', async () => {
80
+ const auth0 = new MastraAuthAuth0();
81
+ const result = await auth0.authorizeUser({ sub: 'user123' });
82
+ expect(result).toBe(true);
83
+ });
84
+
85
+ test('returns false for null/undefined user', async () => {
86
+ const auth0 = new MastraAuthAuth0();
87
+ const result = await auth0.authorizeUser(null as any);
88
+ expect(result).toBe(false);
89
+ });
90
+
91
+ test('can be overridden with custom authorization logic', async () => {
92
+ const auth0 = new MastraAuthAuth0({
93
+ async authorizeUser(user: any): Promise<boolean> {
94
+ // Custom authorization logic that checks for specific permissions
95
+ return user?.permissions?.includes('admin') ?? false;
96
+ },
97
+ });
98
+
99
+ // Test with admin user
100
+ const adminUser = { sub: 'user123', permissions: ['admin'] };
101
+ expect(await auth0.authorizeUser(adminUser)).toBe(true);
102
+
103
+ // Test with non-admin user
104
+ const regularUser = { sub: 'user456', permissions: ['read'] };
105
+ expect(await auth0.authorizeUser(regularUser)).toBe(false);
106
+
107
+ // Test with user without permissions
108
+ const noPermissionsUser = { sub: 'user789' };
109
+ expect(await auth0.authorizeUser(noPermissionsUser)).toBe(false);
110
+ });
111
+ });
112
+ });
package/src/index.ts ADDED
@@ -0,0 +1,49 @@
1
+ import { MastraAuthProvider } from '@mastra/core/server';
2
+ import type { MastraAuthProviderOptions } from '@mastra/core/server';
3
+
4
+ import { createRemoteJWKSet, jwtVerify } from 'jose';
5
+ import type { JWTPayload } from 'jose';
6
+
7
+ type Auth0User = JWTPayload;
8
+
9
+ interface MastraAuthAuth0Options extends MastraAuthProviderOptions<Auth0User> {
10
+ domain?: string; // set this to your Auth0 domain
11
+ audience?: string; // set this to your Auth0 API identifier
12
+ }
13
+
14
+ export class MastraAuthAuth0 extends MastraAuthProvider<Auth0User> {
15
+ protected domain: string;
16
+ protected audience: string;
17
+ constructor(options?: MastraAuthAuth0Options) {
18
+ super({ name: options?.name ?? 'auth0' });
19
+
20
+ const domain = options?.domain ?? process.env.AUTH0_DOMAIN;
21
+ const audience = options?.audience ?? process.env.AUTH0_AUDIENCE;
22
+
23
+ if (!domain || !audience) {
24
+ throw new Error(
25
+ 'Auth0 domain and audience are required, please provide them in the options or set the environment variables AUTH0_DOMAIN and AUTH0_AUDIENCE',
26
+ );
27
+ }
28
+
29
+ this.domain = domain;
30
+ this.audience = audience;
31
+
32
+ this.registerOptions(options);
33
+ }
34
+
35
+ async authenticateToken(token: string): Promise<Auth0User | null> {
36
+ const JWKS = createRemoteJWKSet(new URL(`https://${this.domain}/.well-known/jwks.json`));
37
+
38
+ const { payload } = await jwtVerify(token, JWKS, {
39
+ issuer: `https://${this.domain}/`,
40
+ audience: this.audience,
41
+ });
42
+
43
+ return payload;
44
+ }
45
+
46
+ async authorizeUser(user: Auth0User) {
47
+ return !!user;
48
+ }
49
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.node.json",
3
+ "include": ["src/**/*"],
4
+ "exclude": ["node_modules", "**/*.test.ts"]
5
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ include: ['src/**/*.test.ts'],
7
+ },
8
+ });