@vurb/jwt 3.1.31

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/README.md ADDED
@@ -0,0 +1,79 @@
1
+ <p align="center">
2
+ <h1 align="center">@vurb/jwt</h1>
3
+ <p align="center">
4
+ <strong>JWT Verification Middleware</strong> — Standards-compliant token validation for Vurb.ts servers
5
+ </p>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="https://www.npmjs.com/package/@vurb/jwt"><img src="https://img.shields.io/npm/v/@vurb/jwt?color=blue" alt="npm" /></a>
10
+ <a href="https://github.com/vinkius-labs/vurb.ts/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-green" alt="License" /></a>
11
+ <img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen" alt="Node" />
12
+ </p>
13
+
14
+ ---
15
+
16
+ > JWT verification middleware for MCP servers built with Vurb.ts. Timing-safe validation with `jose`, JWKS auto-discovery, and self-healing error responses.
17
+
18
+ ## Quick Start
19
+
20
+ ```typescript
21
+ import { initVurb } from '@vurb/core';
22
+ import { jwtGuard } from '@vurb/jwt';
23
+
24
+ const f = initVurb<AppContext>();
25
+
26
+ const withJwt = jwtGuard({
27
+ secret: process.env.JWT_SECRET!,
28
+ algorithms: ['HS256'],
29
+ });
30
+
31
+ export default f.query('billing.invoices')
32
+ .use(withJwt)
33
+ .handle(async (input, ctx) => {
34
+ // ctx.jwt contains the decoded payload
35
+ return db.invoices.findMany({ where: { tenantId: ctx.jwt.sub } });
36
+ });
37
+ ```
38
+
39
+ ## Features
40
+
41
+ | Feature | Description |
42
+ |---------|-------------|
43
+ | **Algorithms** | HS256, RS256, ES256 — all standard algorithms via `jose` |
44
+ | **JWKS** | Auto-discovery from `/.well-known/jwks.json` with key rotation |
45
+ | **Self-Healing** | Expired/invalid tokens return actionable hints to the LLM agent |
46
+ | **Timing-Safe** | Constant-time signature verification |
47
+ | **Zero Config** | Works with Auth0, Clerk, Supabase, Firebase, any OIDC provider |
48
+
49
+ ## JWKS Auto-Discovery
50
+
51
+ ```typescript
52
+ const withJwt = jwtGuard({
53
+ jwksUri: 'https://auth.example.com/.well-known/jwks.json',
54
+ issuer: 'https://auth.example.com/',
55
+ audience: 'my-mcp-server',
56
+ });
57
+ ```
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ npm install @vurb/jwt jose
63
+ ```
64
+
65
+ ### Peer Dependencies
66
+
67
+ | Package | Version |
68
+ |---------|---------|
69
+ | `vurb` | `^2.0.0` |
70
+ | `jose` | `^5.0.0` (optional) |
71
+
72
+ ## Requirements
73
+
74
+ - **Node.js** ≥ 18.0.0
75
+ - **Vurb.ts** ≥ 2.0.0 (peer dependency)
76
+
77
+ ## License
78
+
79
+ [Apache-2.0](https://github.com/vinkius-labs/vurb.ts/blob/main/LICENSE)
@@ -0,0 +1,128 @@
1
+ /**
2
+ * JWT Verifier — Standards-Compliant Token Verification
3
+ *
4
+ * Verifies JWTs using `jose` when installed, or falls back to
5
+ * native `crypto.subtle` (Web Crypto API) for HS256 verification.
6
+ *
7
+ * Supports:
8
+ * - HS256, RS256, ES256 (via jose)
9
+ * - HS256 native fallback (via crypto.subtle)
10
+ * - JWKS endpoint auto-discovery
11
+ * - Claims validation: `exp`, `nbf`, `iss`, `aud`
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { JwtVerifier } from '@vurb/jwt';
16
+ *
17
+ * // With symmetric secret (HS256)
18
+ * const verifier = new JwtVerifier({ secret: 'my-secret' });
19
+ *
20
+ * // With JWKS endpoint (RS256, ES256)
21
+ * const verifier = new JwtVerifier({ jwksUri: 'https://auth.example.com/.well-known/jwks.json' });
22
+ *
23
+ * const payload = await verifier.verify(token);
24
+ * if (payload) console.log(payload.sub); // user ID
25
+ * ```
26
+ */
27
+ export interface JwtVerifierConfig {
28
+ /** Symmetric secret for HS256. */
29
+ readonly secret?: string;
30
+ /** JWKS endpoint URL for RS256/ES256 key fetching. Requires `jose`. */
31
+ readonly jwksUri?: string;
32
+ /** PEM-encoded public key for RS256/ES256. */
33
+ readonly publicKey?: string;
34
+ /** Algorithm for public key verification (e.g. 'RS256', 'ES256', 'ES384', 'ES512'). Default: 'RS256'. */
35
+ readonly algorithm?: string;
36
+ /** Expected issuer (`iss` claim). */
37
+ readonly issuer?: string | string[];
38
+ /** Expected audience (`aud` claim). */
39
+ readonly audience?: string | string[];
40
+ /** Clock tolerance in seconds for `exp`/`nbf` checks. Default: 60 */
41
+ readonly clockTolerance?: number;
42
+ /** Required claims that must be present in the payload. */
43
+ readonly requiredClaims?: string[];
44
+ }
45
+ export interface JwtPayload {
46
+ /** Subject — typically the user ID */
47
+ readonly sub?: string;
48
+ /** Issuer */
49
+ readonly iss?: string;
50
+ /** Audience */
51
+ readonly aud?: string | string[];
52
+ /** Expiration time (Unix seconds) */
53
+ readonly exp?: number;
54
+ /** Not before (Unix seconds) */
55
+ readonly nbf?: number;
56
+ /** Issued at (Unix seconds) */
57
+ readonly iat?: number;
58
+ /** JWT ID */
59
+ readonly jti?: string;
60
+ /** Additional claims */
61
+ readonly [key: string]: unknown;
62
+ }
63
+ export interface JwtVerifyResult {
64
+ /** Whether the token is valid */
65
+ readonly valid: boolean;
66
+ /** Decoded payload (only present if valid) */
67
+ readonly payload?: JwtPayload;
68
+ /** Error reason (only present if invalid) */
69
+ readonly reason?: string;
70
+ }
71
+ export declare class JwtVerifier {
72
+ private readonly _config;
73
+ private readonly _clockTolerance;
74
+ private _joseLoaded;
75
+ private _jwtVerify;
76
+ private _createRemoteJWKSet;
77
+ private _jwks;
78
+ constructor(config: JwtVerifierConfig);
79
+ /**
80
+ * Verify a JWT and return the decoded payload.
81
+ *
82
+ * @param token - Raw JWT string (without "Bearer " prefix)
83
+ * @returns The decoded payload, or `null` if verification fails
84
+ */
85
+ verify(token: string): Promise<JwtPayload | null>;
86
+ /**
87
+ * Verify a JWT with detailed result including error reason.
88
+ *
89
+ * @param token - Raw JWT string
90
+ * @returns Detailed verification result
91
+ */
92
+ verifyDetailed(token: string): Promise<JwtVerifyResult>;
93
+ /**
94
+ * Attempt to verify using jose.
95
+ * Returns `undefined` if jose is not installed.
96
+ *
97
+ * @internal
98
+ */
99
+ private _verifyWithJose;
100
+ /**
101
+ * Load jose dynamically. Silently fails if not installed.
102
+ * @internal
103
+ */
104
+ private _loadJose;
105
+ /**
106
+ * Verify HS256 JWT using Node.js native crypto.
107
+ * @internal
108
+ */
109
+ private _verifyHS256Native;
110
+ /**
111
+ * Validate claims (exp, nbf, required) on an already signature-verified payload.
112
+ * @internal
113
+ */
114
+ private _validateClaims;
115
+ /**
116
+ * Decode a JWT payload WITHOUT verifying the signature.
117
+ * Useful for inspecting tokens in logging/debugging.
118
+ *
119
+ * ⚠️ Never trust decoded-only payloads for authorization decisions.
120
+ */
121
+ static decode(token: string): JwtPayload | null;
122
+ /**
123
+ * Check if a token is expired without verifying signature.
124
+ * Returns `true` if expired or unparseable.
125
+ */
126
+ static isExpired(token: string, clockTolerance?: number): boolean;
127
+ }
128
+ //# sourceMappingURL=JwtVerifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtVerifier.d.ts","sourceRoot":"","sources":["../src/JwtVerifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAQH,MAAM,WAAW,iBAAiB;IAC9B,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEzB,uEAAuE;IACvE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B,8CAA8C;IAC9C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,yGAAyG;IACzG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,qCAAqC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEpC,uCAAuC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEtC,qEAAqE;IACrE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAEjC,2DAA2D;IAC3D,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CACtC;AAED,MAAM,WAAW,UAAU;IACvB,sCAAsC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe;IACf,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACjC,qCAAqC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,wBAAwB;IACxB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC5B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC5B;AAMD,qBAAa,WAAW;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IAGzC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAuG;IACzH,OAAO,CAAC,mBAAmB,CAAwC;IACnE,OAAO,CAAC,KAAK,CAAiB;gBAElB,MAAM,EAAE,iBAAiB;IAUrC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAKvD;;;;;OAKG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA8B7D;;;;;OAKG;YACW,eAAe;IAkC7B;;;OAGG;YACW,SAAS;IAavB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA0C1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAgDvB;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAU/C;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,SAAK,GAAG,OAAO;CAKhE"}
@@ -0,0 +1,259 @@
1
+ /**
2
+ * JWT Verifier — Standards-Compliant Token Verification
3
+ *
4
+ * Verifies JWTs using `jose` when installed, or falls back to
5
+ * native `crypto.subtle` (Web Crypto API) for HS256 verification.
6
+ *
7
+ * Supports:
8
+ * - HS256, RS256, ES256 (via jose)
9
+ * - HS256 native fallback (via crypto.subtle)
10
+ * - JWKS endpoint auto-discovery
11
+ * - Claims validation: `exp`, `nbf`, `iss`, `aud`
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { JwtVerifier } from '@vurb/jwt';
16
+ *
17
+ * // With symmetric secret (HS256)
18
+ * const verifier = new JwtVerifier({ secret: 'my-secret' });
19
+ *
20
+ * // With JWKS endpoint (RS256, ES256)
21
+ * const verifier = new JwtVerifier({ jwksUri: 'https://auth.example.com/.well-known/jwks.json' });
22
+ *
23
+ * const payload = await verifier.verify(token);
24
+ * if (payload) console.log(payload.sub); // user ID
25
+ * ```
26
+ */
27
+ import * as crypto from 'node:crypto';
28
+ // ============================================================================
29
+ // JwtVerifier
30
+ // ============================================================================
31
+ export class JwtVerifier {
32
+ _config;
33
+ _clockTolerance;
34
+ // Lazy-loaded jose references
35
+ _joseLoaded = false;
36
+ _jwtVerify = null;
37
+ _createRemoteJWKSet = null;
38
+ _jwks = null;
39
+ constructor(config) {
40
+ if (!config.secret && !config.jwksUri && !config.publicKey) {
41
+ throw new Error('JwtVerifier requires at least one of: secret, jwksUri, publicKey');
42
+ }
43
+ this._config = config;
44
+ this._clockTolerance = config.clockTolerance ?? 60;
45
+ }
46
+ // ── Public API ───────────────────────────────────────
47
+ /**
48
+ * Verify a JWT and return the decoded payload.
49
+ *
50
+ * @param token - Raw JWT string (without "Bearer " prefix)
51
+ * @returns The decoded payload, or `null` if verification fails
52
+ */
53
+ async verify(token) {
54
+ const result = await this.verifyDetailed(token);
55
+ return result.valid ? result.payload : null;
56
+ }
57
+ /**
58
+ * Verify a JWT with detailed result including error reason.
59
+ *
60
+ * @param token - Raw JWT string
61
+ * @returns Detailed verification result
62
+ */
63
+ async verifyDetailed(token) {
64
+ if (!token || typeof token !== 'string') {
65
+ return { valid: false, reason: 'Token is empty or not a string' };
66
+ }
67
+ try {
68
+ // Try jose first (supports all algorithms)
69
+ const payload = await this._verifyWithJose(token);
70
+ if (payload !== undefined) {
71
+ return this._validateClaims(payload);
72
+ }
73
+ // Fallback: native HS256 verification (secret only)
74
+ if (this._config.secret) {
75
+ const payload = this._verifyHS256Native(token);
76
+ if (payload) {
77
+ return this._validateClaims(payload);
78
+ }
79
+ return { valid: false, reason: 'Signature verification failed' };
80
+ }
81
+ return { valid: false, reason: 'No verification method available (install jose for RS256/ES256)' };
82
+ }
83
+ catch (err) {
84
+ const message = err instanceof Error ? err.message : String(err);
85
+ return { valid: false, reason: message };
86
+ }
87
+ }
88
+ // ── Jose Integration ─────────────────────────────────
89
+ /**
90
+ * Attempt to verify using jose.
91
+ * Returns `undefined` if jose is not installed.
92
+ *
93
+ * @internal
94
+ */
95
+ async _verifyWithJose(token) {
96
+ if (!this._joseLoaded) {
97
+ await this._loadJose();
98
+ }
99
+ if (!this._jwtVerify)
100
+ return undefined;
101
+ const options = {};
102
+ if (this._config.issuer)
103
+ options['issuer'] = this._config.issuer;
104
+ if (this._config.audience)
105
+ options['audience'] = this._config.audience;
106
+ options['clockTolerance'] = this._clockTolerance;
107
+ let key;
108
+ if (this._config.jwksUri) {
109
+ if (!this._jwks && this._createRemoteJWKSet) {
110
+ this._jwks = this._createRemoteJWKSet(new URL(this._config.jwksUri));
111
+ }
112
+ key = this._jwks;
113
+ }
114
+ else if (this._config.publicKey) {
115
+ // jose importSPKI for PEM keys
116
+ const jose = await import('jose');
117
+ key = await jose.importSPKI(this._config.publicKey, this._config.algorithm ?? 'RS256');
118
+ }
119
+ else if (this._config.secret) {
120
+ const encoder = new TextEncoder();
121
+ key = encoder.encode(this._config.secret);
122
+ }
123
+ if (!key)
124
+ return undefined;
125
+ const result = await this._jwtVerify(token, key, options);
126
+ return result.payload;
127
+ }
128
+ /**
129
+ * Load jose dynamically. Silently fails if not installed.
130
+ * @internal
131
+ */
132
+ async _loadJose() {
133
+ this._joseLoaded = true;
134
+ try {
135
+ const jose = await import('jose');
136
+ this._jwtVerify = jose.jwtVerify;
137
+ this._createRemoteJWKSet = jose.createRemoteJWKSet;
138
+ }
139
+ catch {
140
+ // jose not installed — will use native fallback
141
+ }
142
+ }
143
+ // ── Native HS256 Fallback ────────────────────────────
144
+ /**
145
+ * Verify HS256 JWT using Node.js native crypto.
146
+ * @internal
147
+ */
148
+ _verifyHS256Native(token) {
149
+ const parts = token.split('.');
150
+ if (parts.length !== 3)
151
+ return null;
152
+ const headerB64 = parts[0];
153
+ const payloadB64 = parts[1];
154
+ const signatureB64 = parts[2];
155
+ // Verify header
156
+ try {
157
+ const header = JSON.parse(Buffer.from(headerB64, 'base64url').toString());
158
+ if (header.alg !== 'HS256')
159
+ return null; // Only HS256 in native mode
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ // Verify signature
165
+ const expectedSignature = crypto
166
+ .createHmac('sha256', this._config.secret)
167
+ .update(`${headerB64}.${payloadB64}`)
168
+ .digest('base64url');
169
+ // Guard against RangeError from timingSafeEqual when
170
+ // a malformed JWT carries a truncated or oversized signature.
171
+ // The length check is safe — the expected length (32 bytes for
172
+ // SHA-256) is publicly known and leaks no secret information.
173
+ const sigBuf = Buffer.from(signatureB64, 'base64url');
174
+ const expBuf = Buffer.from(expectedSignature, 'base64url');
175
+ if (sigBuf.length !== expBuf.length || !crypto.timingSafeEqual(sigBuf, expBuf)) {
176
+ return null;
177
+ }
178
+ // Decode payload
179
+ try {
180
+ return JSON.parse(Buffer.from(payloadB64, 'base64url').toString());
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
186
+ // ── Claims Validation ────────────────────────────────
187
+ /**
188
+ * Validate claims (exp, nbf, required) on an already signature-verified payload.
189
+ * @internal
190
+ */
191
+ _validateClaims(payload) {
192
+ const now = Math.floor(Date.now() / 1000);
193
+ // Check expiration
194
+ if (payload.exp !== undefined) {
195
+ if (now > payload.exp + this._clockTolerance) {
196
+ return { valid: false, reason: 'Token has expired' };
197
+ }
198
+ }
199
+ // Check not-before
200
+ if (payload.nbf !== undefined) {
201
+ if (now < payload.nbf - this._clockTolerance) {
202
+ return { valid: false, reason: 'Token is not yet valid (nbf)' };
203
+ }
204
+ }
205
+ // Check issuer (when not using jose, which validates it internally)
206
+ if (this._config.issuer && !this._jwtVerify) {
207
+ const issuers = Array.isArray(this._config.issuer) ? this._config.issuer : [this._config.issuer];
208
+ if (!payload.iss || !issuers.includes(payload.iss)) {
209
+ return { valid: false, reason: `Invalid issuer: ${payload.iss}` };
210
+ }
211
+ }
212
+ // Check audience (when not using jose)
213
+ if (this._config.audience && !this._jwtVerify) {
214
+ const audiences = Array.isArray(this._config.audience) ? this._config.audience : [this._config.audience];
215
+ const tokenAud = Array.isArray(payload.aud) ? payload.aud : payload.aud ? [payload.aud] : [];
216
+ if (!tokenAud.some(a => audiences.includes(a))) {
217
+ return { valid: false, reason: `Invalid audience: ${payload.aud}` };
218
+ }
219
+ }
220
+ // Check required claims
221
+ if (this._config.requiredClaims) {
222
+ for (const claim of this._config.requiredClaims) {
223
+ if (payload[claim] === undefined) {
224
+ return { valid: false, reason: `Missing required claim: ${claim}` };
225
+ }
226
+ }
227
+ }
228
+ return { valid: true, payload };
229
+ }
230
+ // ── Utilities ────────────────────────────────────────
231
+ /**
232
+ * Decode a JWT payload WITHOUT verifying the signature.
233
+ * Useful for inspecting tokens in logging/debugging.
234
+ *
235
+ * ⚠️ Never trust decoded-only payloads for authorization decisions.
236
+ */
237
+ static decode(token) {
238
+ try {
239
+ const parts = token.split('.');
240
+ if (parts.length !== 3)
241
+ return null;
242
+ return JSON.parse(Buffer.from(parts[1], 'base64url').toString());
243
+ }
244
+ catch {
245
+ return null;
246
+ }
247
+ }
248
+ /**
249
+ * Check if a token is expired without verifying signature.
250
+ * Returns `true` if expired or unparseable.
251
+ */
252
+ static isExpired(token, clockTolerance = 60) {
253
+ const payload = JwtVerifier.decode(token);
254
+ if (!payload?.exp)
255
+ return true;
256
+ return Math.floor(Date.now() / 1000) > payload.exp + clockTolerance;
257
+ }
258
+ }
259
+ //# sourceMappingURL=JwtVerifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtVerifier.js","sourceRoot":"","sources":["../src/JwtVerifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * JWT Auth Tool Factory — Pre-built JWT Verification Tool
3
+ *
4
+ * Creates a complete vurb tool with verify and status actions.
5
+ * Consumers only need to provide their JWT verification config.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { createJwtAuthTool } from '@vurb/jwt';
10
+ *
11
+ * const jwtTool = createJwtAuthTool({
12
+ * secret: process.env.JWT_SECRET!,
13
+ * toolName: 'jwt_auth',
14
+ * });
15
+ * ```
16
+ */
17
+ import type { JwtVerifierConfig } from './JwtVerifier.js';
18
+ export interface JwtAuthToolConfig<TContext = unknown> extends JwtVerifierConfig {
19
+ /** Tool name in MCP. Default: 'jwt_auth' */
20
+ readonly toolName?: string;
21
+ /** Tool description for the LLM. */
22
+ readonly description?: string;
23
+ /** Tags for selective tool exposure. */
24
+ readonly tags?: string[];
25
+ /**
26
+ * Extracts the JWT from the context.
27
+ * Required for the `status` action.
28
+ */
29
+ readonly extractToken?: (ctx: TContext) => string | null | undefined;
30
+ }
31
+ /**
32
+ * Creates a complete JWT auth tool with verify and status actions.
33
+ *
34
+ * Actions:
35
+ * - `verify` — Verify a JWT and return decoded claims
36
+ * - `status` — Check if JWT is present/valid/expired
37
+ */
38
+ export declare function createJwtAuthTool<TContext = unknown>(config: JwtAuthToolConfig<TContext>): import("vurb").GroupedToolBuilder<TContext, Record<string, never>, string, Record<string, never> & {
39
+ [x: `${string}.verify`]: Record<string, unknown>;
40
+ } & {
41
+ [x: `${string}.status`]: Record<string, unknown>;
42
+ }>;
43
+ //# sourceMappingURL=createJwtAuthTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createJwtAuthTool.d.ts","sourceRoot":"","sources":["../src/createJwtAuthTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAc,MAAM,kBAAkB,CAAC;AAMtE,MAAM,WAAW,iBAAiB,CAAC,QAAQ,GAAG,OAAO,CAAE,SAAQ,iBAAiB;IAC5E,4CAA4C;IAC5C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAE9B,wCAAwC;IACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACxE;AAkBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,GAAG,OAAO,EAAE,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC;;;;GAuFxF"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * JWT Auth Tool Factory — Pre-built JWT Verification Tool
3
+ *
4
+ * Creates a complete vurb tool with verify and status actions.
5
+ * Consumers only need to provide their JWT verification config.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { createJwtAuthTool } from '@vurb/jwt';
10
+ *
11
+ * const jwtTool = createJwtAuthTool({
12
+ * secret: process.env.JWT_SECRET!,
13
+ * toolName: 'jwt_auth',
14
+ * });
15
+ * ```
16
+ */
17
+ import { createTool } from 'vurb';
18
+ import { JwtVerifier } from './JwtVerifier.js';
19
+ // ============================================================================
20
+ // Response Helpers
21
+ // ============================================================================
22
+ function ok(data) {
23
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
24
+ }
25
+ function fail(data) {
26
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }], isError: true };
27
+ }
28
+ // ============================================================================
29
+ // Factory
30
+ // ============================================================================
31
+ /**
32
+ * Creates a complete JWT auth tool with verify and status actions.
33
+ *
34
+ * Actions:
35
+ * - `verify` — Verify a JWT and return decoded claims
36
+ * - `status` — Check if JWT is present/valid/expired
37
+ */
38
+ export function createJwtAuthTool(config) {
39
+ const verifier = new JwtVerifier(config);
40
+ const toolName = config.toolName ?? 'jwt_auth';
41
+ const description = config.description ?? 'JWT authentication — verify tokens and check status';
42
+ const extractToken = config.extractToken;
43
+ const tool = createTool(toolName);
44
+ if (config.tags?.length) {
45
+ tool.tags(...config.tags);
46
+ }
47
+ return tool
48
+ .action({
49
+ name: 'verify',
50
+ description: 'Verify a JWT and return decoded claims',
51
+ handler: async (_ctx, args) => {
52
+ const token = args['token'];
53
+ if (!token) {
54
+ return fail({ message: 'Token is required' });
55
+ }
56
+ const rawToken = token.startsWith('Bearer ') ? token.slice(7) : token;
57
+ const result = await verifier.verifyDetailed(rawToken);
58
+ if (!result.valid) {
59
+ return fail({
60
+ message: `Verification failed: ${result.reason}`,
61
+ valid: false,
62
+ });
63
+ }
64
+ return ok({
65
+ valid: true,
66
+ payload: result.payload,
67
+ claims: {
68
+ sub: result.payload?.sub,
69
+ iss: result.payload?.iss,
70
+ aud: result.payload?.aud,
71
+ exp: result.payload?.exp,
72
+ iat: result.payload?.iat,
73
+ },
74
+ });
75
+ },
76
+ })
77
+ .action({
78
+ name: 'status',
79
+ description: 'Check JWT authentication status from context',
80
+ handler: async (ctx) => {
81
+ if (!extractToken) {
82
+ return ok({
83
+ available: false,
84
+ reason: 'No token extractor configured',
85
+ });
86
+ }
87
+ const raw = extractToken(ctx);
88
+ if (!raw) {
89
+ return ok({
90
+ authenticated: false,
91
+ reason: 'No JWT found in context',
92
+ });
93
+ }
94
+ const token = typeof raw === 'string' && raw.startsWith('Bearer ') ? raw.slice(7) : raw;
95
+ // Decode without verification for status info
96
+ const decoded = JwtVerifier.decode(token);
97
+ const isExpired = JwtVerifier.isExpired(token, config.clockTolerance);
98
+ // Full verification
99
+ const result = await verifier.verifyDetailed(token);
100
+ return ok({
101
+ authenticated: result.valid,
102
+ expired: isExpired,
103
+ valid: result.valid,
104
+ reason: result.reason,
105
+ claims: decoded ? {
106
+ sub: decoded.sub,
107
+ iss: decoded.iss,
108
+ exp: decoded.exp ? new Date(decoded.exp * 1000).toISOString() : undefined,
109
+ iat: decoded.iat ? new Date(decoded.iat * 1000).toISOString() : undefined,
110
+ } : undefined,
111
+ });
112
+ },
113
+ });
114
+ }
115
+ //# sourceMappingURL=createJwtAuthTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createJwtAuthTool.js","sourceRoot":"","sources":["../src/createJwtAuthTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAwB/C,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,SAAS,EAAE,CAAC,IAA6B;IACrC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACzF,CAAC;AAED,SAAS,IAAI,CAAC,IAA6B;IACvC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACxG,CAAC;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAqB,MAAmC;IACrF,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,UAAU,CAAC;IAC/C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,qDAAqD,CAAC;IAChG,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;IAEzC,MAAM,IAAI,GAAG,UAAU,CAAW,QAAQ,CAAC,CAAC;IAE5C,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,IAAI;SACN,MAAM,CAAC;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,wCAAwC;QACrD,OAAO,EAAE,KAAK,EAAE,IAAc,EAAE,IAA6B,EAAyB,EAAE;YACpF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAuB,CAAC;YAClD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;YAClD,CAAC;YAED,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACtE,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YAEvD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;oBACR,OAAO,EAAE,wBAAwB,MAAM,CAAC,MAAM,EAAE;oBAChD,KAAK,EAAE,KAAK;iBACf,CAAC,CAAC;YACP,CAAC;YAED,OAAO,EAAE,CAAC;gBACN,KAAK,EAAE,IAAI;gBACX,OAAO,EAAE,MAAM,CAAC,OAAkC;gBAClD,MAAM,EAAE;oBACJ,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG;oBACxB,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG;oBACxB,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG;oBACxB,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG;oBACxB,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG;iBAC3B;aACJ,CAAC,CAAC;QACP,CAAC;KACJ,CAAC;SACD,MAAM,CAAC;QACJ,IAAI,EAAE,QAAQ;QACd,WAAW,EAAE,8CAA8C;QAC3D,OAAO,EAAE,KAAK,EAAE,GAAa,EAAyB,EAAE;YACpD,IAAI,CAAC,YAAY,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC;oBACN,SAAS,EAAE,KAAK;oBAChB,MAAM,EAAE,+BAA+B;iBAC1C,CAAC,CAAC;YACP,CAAC;YAED,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;gBACP,OAAO,EAAE,CAAC;oBACN,aAAa,EAAE,KAAK;oBACpB,MAAM,EAAE,yBAAyB;iBACpC,CAAC,CAAC;YACP,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAExF,8CAA8C;YAC9C,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;YACpD,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,KAAe,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;YAEhF,oBAAoB;YACpB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,KAAe,CAAC,CAAC;YAE9D,OAAO,EAAE,CAAC;gBACN,aAAa,EAAE,MAAM,CAAC,KAAK;gBAC3B,OAAO,EAAE,SAAS;gBAClB,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;oBACd,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,GAAG,EAAE,OAAO,CAAC,GAAG;oBAChB,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;oBACzE,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;iBAC5E,CAAC,CAAC,CAAC,SAAS;aAChB,CAAC,CAAC;QACP,CAAC;KACJ,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @vurb/jwt — JWT Verification for MCP Servers
3
+ *
4
+ * Standards-compliant JWT verification with jose integration,
5
+ * native HS256 fallback, and vurb middleware.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { JwtVerifier, requireJwt, createJwtAuthTool } from '@vurb/jwt';
10
+ *
11
+ * // Middleware
12
+ * const projects = createTool('projects')
13
+ * .use(requireJwt({ secret: 'my-secret' }))
14
+ * .action({ name: 'list', handler: async () => success([]) });
15
+ *
16
+ * // Standalone
17
+ * const verifier = new JwtVerifier({ secret: 'my-secret' });
18
+ * const payload = await verifier.verify(token);
19
+ * ```
20
+ *
21
+ * @module @vurb/jwt
22
+ * @author Vinkius Labs
23
+ * @license Apache-2.0
24
+ */
25
+ export { JwtVerifier } from './JwtVerifier.js';
26
+ export type { JwtVerifierConfig, JwtPayload, JwtVerifyResult, } from './JwtVerifier.js';
27
+ export { createJwtAuthTool } from './createJwtAuthTool.js';
28
+ export type { JwtAuthToolConfig } from './createJwtAuthTool.js';
29
+ export { requireJwt } from './middleware.js';
30
+ export type { RequireJwtOptions } from './middleware.js';
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EACR,iBAAiB,EACjB,UAAU,EACV,eAAe,GAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @vurb/jwt — JWT Verification for MCP Servers
3
+ *
4
+ * Standards-compliant JWT verification with jose integration,
5
+ * native HS256 fallback, and vurb middleware.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { JwtVerifier, requireJwt, createJwtAuthTool } from '@vurb/jwt';
10
+ *
11
+ * // Middleware
12
+ * const projects = createTool('projects')
13
+ * .use(requireJwt({ secret: 'my-secret' }))
14
+ * .action({ name: 'list', handler: async () => success([]) });
15
+ *
16
+ * // Standalone
17
+ * const verifier = new JwtVerifier({ secret: 'my-secret' });
18
+ * const payload = await verifier.verify(token);
19
+ * ```
20
+ *
21
+ * @module @vurb/jwt
22
+ * @author Vinkius Labs
23
+ * @license Apache-2.0
24
+ */
25
+ export { JwtVerifier } from './JwtVerifier.js';
26
+ export { createJwtAuthTool } from './createJwtAuthTool.js';
27
+ export { requireJwt } from './middleware.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * JWT Auth Middleware — requireJwt()
3
+ *
4
+ * vurb middleware that ensures requests carry a valid JWT.
5
+ * Extracts the token, verifies it via JwtVerifier, and rejects
6
+ * invalid/expired/missing tokens with self-healing error responses.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { requireJwt } from '@vurb/jwt';
11
+ *
12
+ * const projects = createTool('projects')
13
+ * .use(requireJwt({ secret: process.env.JWT_SECRET! }))
14
+ * .action({ name: 'list', handler: async (ctx) => { ... } });
15
+ * ```
16
+ */
17
+ import type { ToolResponse } from 'vurb';
18
+ import type { JwtVerifierConfig, JwtPayload } from './JwtVerifier.js';
19
+ export interface RequireJwtOptions extends JwtVerifierConfig {
20
+ /**
21
+ * Custom function to extract the JWT from the context.
22
+ * Default: checks `ctx.token`, `ctx.jwt`, `ctx.headers.authorization` (Bearer).
23
+ */
24
+ readonly extractToken?: (ctx: unknown) => string | null | undefined;
25
+ /**
26
+ * Callback invoked after successful verification.
27
+ * Use this to inject the decoded payload into the context.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * requireJwt({
32
+ * secret: 'my-secret',
33
+ * onVerified: (ctx, payload) => {
34
+ * (ctx as any).userId = payload.sub;
35
+ * },
36
+ * });
37
+ * ```
38
+ */
39
+ readonly onVerified?: (ctx: unknown, payload: JwtPayload) => void;
40
+ /** Error code for toolError response. Default: 'JWT_INVALID' */
41
+ readonly errorCode?: string;
42
+ /** Recovery hint for the LLM. Default: 'Provide a valid JWT in the authorization context' */
43
+ readonly recoveryHint?: string;
44
+ /** Recovery action name. Default: 'auth' */
45
+ readonly recoveryAction?: string;
46
+ }
47
+ /**
48
+ * Creates a vurb middleware that verifies JWTs.
49
+ *
50
+ * Returns `toolError('JWT_INVALID')` with self-healing hints
51
+ * when no valid JWT is found.
52
+ */
53
+ export declare function requireJwt(options: RequireJwtOptions): (ctx: unknown, _args: Record<string, unknown>, next: () => Promise<ToolResponse>) => Promise<ToolResponse>;
54
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAEzC,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMtE,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IACxD;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAEpE;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAElE,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE5B,6FAA6F;IAC7F,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE/B,4CAA4C;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CACpC;AAMD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,IAQnC,KAAK,OAAO,EAAE,OAAO,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,OAAO,CAAC,YAAY,CAAC,KAAG,OAAO,CAAC,YAAY,CAAC,CA8BxH"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * JWT Auth Middleware — requireJwt()
3
+ *
4
+ * vurb middleware that ensures requests carry a valid JWT.
5
+ * Extracts the token, verifies it via JwtVerifier, and rejects
6
+ * invalid/expired/missing tokens with self-healing error responses.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { requireJwt } from '@vurb/jwt';
11
+ *
12
+ * const projects = createTool('projects')
13
+ * .use(requireJwt({ secret: process.env.JWT_SECRET! }))
14
+ * .action({ name: 'list', handler: async (ctx) => { ... } });
15
+ * ```
16
+ */
17
+ import { toolError } from 'vurb';
18
+ import { JwtVerifier } from './JwtVerifier.js';
19
+ // ============================================================================
20
+ // Middleware Factory
21
+ // ============================================================================
22
+ /**
23
+ * Creates a vurb middleware that verifies JWTs.
24
+ *
25
+ * Returns `toolError('JWT_INVALID')` with self-healing hints
26
+ * when no valid JWT is found.
27
+ */
28
+ export function requireJwt(options) {
29
+ const verifier = new JwtVerifier(options);
30
+ const extractToken = options.extractToken ?? defaultExtractToken;
31
+ const errorCode = options.errorCode ?? 'JWT_INVALID';
32
+ const recoveryHint = options.recoveryHint ?? 'Provide a valid JWT in the authorization context';
33
+ const recoveryAction = options.recoveryAction ?? 'auth';
34
+ const onVerified = options.onVerified;
35
+ return async (ctx, _args, next) => {
36
+ const raw = extractToken(ctx);
37
+ if (!raw) {
38
+ return toolError(errorCode, {
39
+ message: 'JWT authentication required',
40
+ suggestion: recoveryHint,
41
+ availableActions: [recoveryAction],
42
+ });
43
+ }
44
+ // Strip "Bearer " prefix if present
45
+ const token = raw.startsWith('Bearer ') ? raw.slice(7) : raw;
46
+ const result = await verifier.verifyDetailed(token);
47
+ if (!result.valid) {
48
+ return toolError(errorCode, {
49
+ message: `JWT verification failed: ${result.reason}`,
50
+ suggestion: recoveryHint,
51
+ availableActions: [recoveryAction],
52
+ });
53
+ }
54
+ if (onVerified && result.payload) {
55
+ onVerified(ctx, result.payload);
56
+ }
57
+ return next();
58
+ };
59
+ }
60
+ // ============================================================================
61
+ // Default Token Extractor
62
+ // ============================================================================
63
+ /**
64
+ * Default JWT extractor — checks common patterns:
65
+ * - `ctx.token`
66
+ * - `ctx.jwt`
67
+ * - `ctx.headers.authorization` (Bearer prefix)
68
+ */
69
+ function defaultExtractToken(ctx) {
70
+ if (!ctx || typeof ctx !== 'object')
71
+ return null;
72
+ const obj = ctx;
73
+ // Direct token property
74
+ if (typeof obj['token'] === 'string' && obj['token']) {
75
+ return obj['token'];
76
+ }
77
+ // JWT property
78
+ if (typeof obj['jwt'] === 'string' && obj['jwt']) {
79
+ return obj['jwt'];
80
+ }
81
+ // Authorization header
82
+ const headers = obj['headers'];
83
+ if (headers) {
84
+ const auth = headers['authorization'];
85
+ if (typeof auth === 'string' && auth) {
86
+ return auth;
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@vurb/jwt",
3
+ "version": "3.1.31",
4
+ "description": "JWT verification middleware for MCP servers built with vurb. Standards-compliant token validation with jose, JWKS support, and self-healing error responses.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "test": "vitest run",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "vurb",
22
+ "jwt",
23
+ "json-web-token",
24
+ "authentication",
25
+ "middleware",
26
+ "ai",
27
+ "llm"
28
+ ],
29
+ "author": "Renato Marinho",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/vinkius-labs/vurb.ts.git",
33
+ "directory": "packages/jwt"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/vinkius-labs/vurb.ts/issues"
37
+ },
38
+ "homepage": "https://vurb.vinkius.com/",
39
+ "files": [
40
+ "dist",
41
+ "README.md"
42
+ ],
43
+ "engines": {
44
+ "node": ">=18.0.0"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "peerDependencies": {
50
+ "@vurb/core": "^3.0.0",
51
+ "jose": "^5.0.0"
52
+ },
53
+ "peerDependenciesMeta": {
54
+ "jose": {
55
+ "optional": true
56
+ }
57
+ },
58
+ "devDependencies": {
59
+ "@vurb/core": ">=3.0.0"
60
+ },
61
+ "license": "Apache-2.0"
62
+ }