@fresho/router 0.1.0 → 0.3.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,208 @@
1
+ //#region src/auth/basic.ts
2
+ /**
3
+ * Parses Basic authentication credentials from an Authorization header value.
4
+ *
5
+ * @param authHeader - The full Authorization header value (e.g., 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=')
6
+ * @returns The parsed credentials, or null if parsing fails
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const header = request.headers.get('Authorization');
11
+ * const credentials = parseBasicAuth(header);
12
+ * if (credentials) {
13
+ * // Verify credentials
14
+ * const isValid = await verifyPassword(credentials.username, credentials.password);
15
+ * }
16
+ * ```
17
+ */
18
+ function parseBasicAuth(authHeader) {
19
+ if (!authHeader?.startsWith("Basic ")) return null;
20
+ try {
21
+ const encoded = authHeader.slice(6);
22
+ const decoded = atob(encoded);
23
+ const colonIndex = decoded.indexOf(":");
24
+ if (colonIndex === -1) return null;
25
+ return {
26
+ username: decoded.substring(0, colonIndex),
27
+ password: decoded.substring(colonIndex + 1)
28
+ };
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+ /**
34
+ * Encodes credentials into a Basic authentication header value.
35
+ *
36
+ * @param username - The username
37
+ * @param password - The password
38
+ * @returns The Authorization header value (e.g., 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=')
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const authHeader = encodeBasicAuth('admin', 'secret');
43
+ * fetch('/api/endpoint', {
44
+ * headers: { Authorization: authHeader }
45
+ * });
46
+ * ```
47
+ */
48
+ function encodeBasicAuth(username, password) {
49
+ return `Basic ${btoa(`${username}:${password}`)}`;
50
+ }
51
+ /**
52
+ * Extracts the raw base64-encoded credentials from an Authorization header.
53
+ *
54
+ * @param authHeader - The full Authorization header value
55
+ * @returns The base64 string, or null if not a Basic auth header
56
+ */
57
+ function extractBasicAuthToken(authHeader) {
58
+ if (!authHeader?.startsWith("Basic ")) return null;
59
+ return authHeader.slice(6);
60
+ }
61
+
62
+ //#endregion
63
+ //#region src/auth/jwt.ts
64
+ /** Maps JWT algorithm names to Web Crypto hash names. */
65
+ const ALGORITHM_MAP = {
66
+ HS256: "SHA-256",
67
+ HS384: "SHA-384",
68
+ HS512: "SHA-512"
69
+ };
70
+ /**
71
+ * Parses a duration string (e.g., '1h', '7d', '30m') to seconds.
72
+ */
73
+ function parseDuration(duration) {
74
+ if (typeof duration === "number") return duration;
75
+ const match = duration.match(/^(\d+)\s*(s|m|h|d|w)$/i);
76
+ if (!match) throw new Error(`Invalid duration format: ${duration}. Use formats like '1h', '7d', '30m', '60s'.`);
77
+ const value = parseInt(match[1], 10);
78
+ const unit = match[2].toLowerCase();
79
+ switch (unit) {
80
+ case "s": return value;
81
+ case "m": return value * 60;
82
+ case "h": return value * 60 * 60;
83
+ case "d": return value * 60 * 60 * 24;
84
+ case "w": return value * 60 * 60 * 24 * 7;
85
+ default: throw new Error(`Unknown duration unit: ${unit}`);
86
+ }
87
+ }
88
+ /**
89
+ * Base64url encodes a string or Uint8Array.
90
+ */
91
+ function base64urlEncode(data) {
92
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
93
+ const binary = String.fromCharCode(...bytes);
94
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
95
+ }
96
+ /**
97
+ * Signs a JWT token using Web Crypto API.
98
+ *
99
+ * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
100
+ *
101
+ * @param payload - The JWT payload (custom claims)
102
+ * @param secret - The signing secret (string, ArrayBuffer, or CryptoKey)
103
+ * @param options - Optional signing options (algorithm, expiresIn, issuer, etc.)
104
+ * @returns The signed JWT token string
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * // Basic usage (HS256 by default)
109
+ * const token = await jwtSign(
110
+ * { uid: 'user-123', role: 'admin' },
111
+ * 'your-secret-key',
112
+ * { expiresIn: '1h' }
113
+ * );
114
+ *
115
+ * // With HS512 algorithm
116
+ * const token = await jwtSign(
117
+ * { uid: 'user-123' },
118
+ * process.env.JWT_SECRET,
119
+ * { algorithm: 'HS512', expiresIn: '7d' }
120
+ * );
121
+ * ```
122
+ */
123
+ async function jwtSign(payload, secret, options = {}) {
124
+ const algorithm = options.algorithm || "HS256";
125
+ const hashAlg = ALGORITHM_MAP[algorithm];
126
+ const now = options.issuedAt ? options.issuedAt instanceof Date ? Math.floor(options.issuedAt.getTime() / 1e3) : options.issuedAt : Math.floor(Date.now() / 1e3);
127
+ const finalPayload = {
128
+ ...payload,
129
+ iat: now
130
+ };
131
+ if (options.expiresIn !== void 0) finalPayload.exp = now + parseDuration(options.expiresIn);
132
+ if (options.notBefore !== void 0) finalPayload.nbf = now + parseDuration(options.notBefore);
133
+ if (options.issuer !== void 0) finalPayload.iss = options.issuer;
134
+ if (options.audience !== void 0) finalPayload.aud = options.audience;
135
+ if (options.subject !== void 0) finalPayload.sub = options.subject;
136
+ const header = {
137
+ alg: algorithm,
138
+ typ: "JWT"
139
+ };
140
+ const data = `${base64urlEncode(JSON.stringify(header))}.${base64urlEncode(JSON.stringify(finalPayload))}`;
141
+ let key;
142
+ if (secret instanceof CryptoKey) key = secret;
143
+ else {
144
+ const keyData = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
145
+ key = await crypto.subtle.importKey("raw", keyData, {
146
+ name: "HMAC",
147
+ hash: hashAlg
148
+ }, false, ["sign"]);
149
+ }
150
+ const signatureBuffer = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(data));
151
+ return `${data}.${base64urlEncode(new Uint8Array(signatureBuffer))}`;
152
+ }
153
+ /**
154
+ * Verifies a JWT token using Web Crypto API.
155
+ *
156
+ * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
157
+ *
158
+ * @param token - The JWT token string to verify
159
+ * @param secret - The secret used to sign the token (string, ArrayBuffer, or CryptoKey)
160
+ * @param options - Optional verification options
161
+ * @returns The decoded JWT payload
162
+ * @throws Error if the token is invalid, expired, or not yet valid
163
+ *
164
+ * @example
165
+ * ```typescript
166
+ * import { jwtVerify } from '@fresho/router/auth';
167
+ *
168
+ * try {
169
+ * const payload = await jwtVerify(token, 'your-secret-key');
170
+ * console.log(payload.sub); // user ID
171
+ * } catch (error) {
172
+ * console.error('Invalid token:', error.message);
173
+ * }
174
+ *
175
+ * // With specific algorithms
176
+ * const payload = await jwtVerify(token, secret, { algorithms: ['HS512'] });
177
+ * ```
178
+ */
179
+ async function jwtVerify(token, secret, options = {}) {
180
+ const algorithms = options.algorithms || ["HS256"];
181
+ const parts = token.split(".");
182
+ if (parts.length !== 3) throw new Error("Invalid JWT format");
183
+ const [headerB64, payloadB64, signatureB64] = parts;
184
+ const header = JSON.parse(atob(headerB64.replace(/-/g, "+").replace(/_/g, "/")));
185
+ if (!algorithms.includes(header.alg)) throw new Error(`Unsupported algorithm: ${header.alg}`);
186
+ const hashAlg = ALGORITHM_MAP[header.alg];
187
+ if (!hashAlg) throw new Error(`Unknown algorithm: ${header.alg}`);
188
+ const payload = JSON.parse(atob(payloadB64.replace(/-/g, "+").replace(/_/g, "/")));
189
+ const data = `${headerB64}.${payloadB64}`;
190
+ const signature = Uint8Array.from(atob(signatureB64.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0));
191
+ let key;
192
+ if (secret instanceof CryptoKey) key = secret;
193
+ else {
194
+ const keyData = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
195
+ key = await crypto.subtle.importKey("raw", keyData, {
196
+ name: "HMAC",
197
+ hash: hashAlg
198
+ }, false, ["verify"]);
199
+ }
200
+ if (!await crypto.subtle.verify("HMAC", key, signature, new TextEncoder().encode(data))) throw new Error("Invalid signature");
201
+ if (payload.exp && payload.exp < Date.now() / 1e3) throw new Error("Token expired");
202
+ if (payload.nbf && payload.nbf > Date.now() / 1e3) throw new Error("Token not yet valid");
203
+ return payload;
204
+ }
205
+
206
+ //#endregion
207
+ export { parseBasicAuth as a, extractBasicAuthToken as i, jwtVerify as n, encodeBasicAuth as r, jwtSign as t };
208
+ //# sourceMappingURL=jwt-Dab9kOC2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt-Dab9kOC2.mjs","names":["ALGORITHM_MAP: Record<JwtAlgorithm, string>","finalPayload: JwtPayload","key: CryptoKey"],"sources":["../src/auth/basic.ts","../src/auth/jwt.ts"],"sourcesContent":["/**\n * @fileoverview Basic HTTP authentication utilities.\n *\n * Provides functions for parsing and encoding Basic authentication credentials.\n *\n * @example\n * ```typescript\n * import { parseBasicAuth, encodeBasicAuth } from '@fresho/router/auth';\n *\n * // Parse credentials from Authorization header\n * const credentials = parseBasicAuth('Basic dXNlcm5hbWU6cGFzc3dvcmQ=');\n * if (credentials) {\n * console.log(credentials.username); // 'username'\n * console.log(credentials.password); // 'password'\n * }\n *\n * // Create an Authorization header value\n * const header = encodeBasicAuth('username', 'password');\n * // 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='\n * ```\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Parsed Basic authentication credentials. */\nexport interface BasicCredentials {\n /** The username from the credentials. */\n username: string;\n /** The password from the credentials. */\n password: string;\n}\n\n// =============================================================================\n// Public API\n// =============================================================================\n\n/**\n * Parses Basic authentication credentials from an Authorization header value.\n *\n * @param authHeader - The full Authorization header value (e.g., 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=')\n * @returns The parsed credentials, or null if parsing fails\n *\n * @example\n * ```typescript\n * const header = request.headers.get('Authorization');\n * const credentials = parseBasicAuth(header);\n * if (credentials) {\n * // Verify credentials\n * const isValid = await verifyPassword(credentials.username, credentials.password);\n * }\n * ```\n */\nexport function parseBasicAuth(authHeader: string | null): BasicCredentials | null {\n if (!authHeader?.startsWith('Basic ')) {\n return null;\n }\n\n try {\n const encoded = authHeader.slice(6);\n const decoded = atob(encoded);\n const colonIndex = decoded.indexOf(':');\n\n if (colonIndex === -1) {\n return null;\n }\n\n return {\n username: decoded.substring(0, colonIndex),\n password: decoded.substring(colonIndex + 1),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Encodes credentials into a Basic authentication header value.\n *\n * @param username - The username\n * @param password - The password\n * @returns The Authorization header value (e.g., 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=')\n *\n * @example\n * ```typescript\n * const authHeader = encodeBasicAuth('admin', 'secret');\n * fetch('/api/endpoint', {\n * headers: { Authorization: authHeader }\n * });\n * ```\n */\nexport function encodeBasicAuth(username: string, password: string): string {\n return `Basic ${btoa(`${username}:${password}`)}`;\n}\n\n/**\n * Extracts the raw base64-encoded credentials from an Authorization header.\n *\n * @param authHeader - The full Authorization header value\n * @returns The base64 string, or null if not a Basic auth header\n */\nexport function extractBasicAuthToken(authHeader: string | null): string | null {\n if (!authHeader?.startsWith('Basic ')) {\n return null;\n }\n return authHeader.slice(6);\n}\n","/**\n * @fileoverview JWT signing and verification utilities.\n *\n * Provides functions for creating and validating JSON Web Tokens using\n * the Web Crypto API. Compatible with Cloudflare Workers, Deno, and browsers.\n *\n * @example\n * ```typescript\n * import { jwtSign, jwtVerify } from '@fresho/router/auth';\n *\n * // Sign a token\n * const token = await jwtSign(\n * { uid: 'user-123', role: 'admin' },\n * 'your-secret-key',\n * { expiresIn: '1h' }\n * );\n *\n * // Verify a token\n * const payload = await jwtVerify(token, 'your-secret-key');\n * console.log(payload.uid); // 'user-123'\n * ```\n */\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** JWT payload type. */\nexport interface JwtPayload {\n /** Subject (user ID). */\n sub?: string;\n /** Issued at timestamp. */\n iat?: number;\n /** Expiration timestamp. */\n exp?: number;\n /** Not before timestamp. */\n nbf?: number;\n /** Issuer. */\n iss?: string;\n /** Audience. */\n aud?: string | string[];\n /** Additional claims. */\n [key: string]: unknown;\n}\n\n/** Supported HMAC algorithms for JWT signing/verification. */\nexport type JwtAlgorithm = 'HS256' | 'HS384' | 'HS512';\n\n/** JWT secret value. */\nexport type JwtSecret = string | ArrayBuffer | CryptoKey;\n\n/** Options for signing a JWT. */\nexport interface SignJwtOptions {\n /** Signing algorithm (default: 'HS256'). */\n algorithm?: JwtAlgorithm;\n /** Expiration time (e.g., '1h', '7d', '30m', or seconds as number). */\n expiresIn?: string | number;\n /** Not before time (e.g., '5m', or seconds as number). */\n notBefore?: string | number;\n /** Issuer claim. */\n issuer?: string;\n /** Audience claim. */\n audience?: string | string[];\n /** Subject claim. */\n subject?: string;\n /** Custom issued-at timestamp (defaults to now). */\n issuedAt?: number | Date;\n}\n\n/** Options for verifying a JWT. */\nexport interface VerifyJwtOptions {\n /** Allowed algorithms (default: ['HS256']). */\n algorithms?: JwtAlgorithm[];\n}\n\n// =============================================================================\n// Internal Helpers\n// =============================================================================\n\n/** Maps JWT algorithm names to Web Crypto hash names. */\nconst ALGORITHM_MAP: Record<JwtAlgorithm, string> = {\n HS256: 'SHA-256',\n HS384: 'SHA-384',\n HS512: 'SHA-512',\n};\n\n/**\n * Parses a duration string (e.g., '1h', '7d', '30m') to seconds.\n */\nfunction parseDuration(duration: string | number): number {\n if (typeof duration === 'number') return duration;\n\n const match = duration.match(/^(\\d+)\\s*(s|m|h|d|w)$/i);\n if (!match) {\n throw new Error(\n `Invalid duration format: ${duration}. Use formats like '1h', '7d', '30m', '60s'.`,\n );\n }\n\n const value = parseInt(match[1], 10);\n const unit = match[2].toLowerCase();\n\n switch (unit) {\n case 's':\n return value;\n case 'm':\n return value * 60;\n case 'h':\n return value * 60 * 60;\n case 'd':\n return value * 60 * 60 * 24;\n case 'w':\n return value * 60 * 60 * 24 * 7;\n default:\n throw new Error(`Unknown duration unit: ${unit}`);\n }\n}\n\n/**\n * Base64url encodes a string or Uint8Array.\n */\nfunction base64urlEncode(data: string | Uint8Array): string {\n const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : data;\n const binary = String.fromCharCode(...bytes);\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n// =============================================================================\n// Public API\n// =============================================================================\n\n/**\n * Signs a JWT token using Web Crypto API.\n *\n * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.\n *\n * @param payload - The JWT payload (custom claims)\n * @param secret - The signing secret (string, ArrayBuffer, or CryptoKey)\n * @param options - Optional signing options (algorithm, expiresIn, issuer, etc.)\n * @returns The signed JWT token string\n *\n * @example\n * ```typescript\n * // Basic usage (HS256 by default)\n * const token = await jwtSign(\n * { uid: 'user-123', role: 'admin' },\n * 'your-secret-key',\n * { expiresIn: '1h' }\n * );\n *\n * // With HS512 algorithm\n * const token = await jwtSign(\n * { uid: 'user-123' },\n * process.env.JWT_SECRET,\n * { algorithm: 'HS512', expiresIn: '7d' }\n * );\n * ```\n */\nexport async function jwtSign(\n payload: Record<string, unknown>,\n secret: JwtSecret,\n options: SignJwtOptions = {},\n): Promise<string> {\n const algorithm = options.algorithm || 'HS256';\n const hashAlg = ALGORITHM_MAP[algorithm];\n\n const now = options.issuedAt\n ? options.issuedAt instanceof Date\n ? Math.floor(options.issuedAt.getTime() / 1000)\n : options.issuedAt\n : Math.floor(Date.now() / 1000);\n\n // Build the final payload with registered claims.\n const finalPayload: JwtPayload = {\n ...payload,\n iat: now,\n };\n\n if (options.expiresIn !== undefined) {\n finalPayload.exp = now + parseDuration(options.expiresIn);\n }\n\n if (options.notBefore !== undefined) {\n finalPayload.nbf = now + parseDuration(options.notBefore);\n }\n\n if (options.issuer !== undefined) {\n finalPayload.iss = options.issuer;\n }\n\n if (options.audience !== undefined) {\n finalPayload.aud = options.audience;\n }\n\n if (options.subject !== undefined) {\n finalPayload.sub = options.subject;\n }\n\n // Create header.\n const header = { alg: algorithm, typ: 'JWT' };\n\n // Encode header and payload.\n const headerB64 = base64urlEncode(JSON.stringify(header));\n const payloadB64 = base64urlEncode(JSON.stringify(finalPayload));\n const data = `${headerB64}.${payloadB64}`;\n\n // Import key for signing.\n let key: CryptoKey;\n if (secret instanceof CryptoKey) {\n key = secret;\n } else {\n const keyData = typeof secret === 'string' ? new TextEncoder().encode(secret) : secret;\n key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: hashAlg }, false, [\n 'sign',\n ]);\n }\n\n // Sign the data.\n const signatureBuffer = await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(data));\n\n const signatureB64 = base64urlEncode(new Uint8Array(signatureBuffer));\n\n return `${data}.${signatureB64}`;\n}\n\n/**\n * Verifies a JWT token using Web Crypto API.\n *\n * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.\n *\n * @param token - The JWT token string to verify\n * @param secret - The secret used to sign the token (string, ArrayBuffer, or CryptoKey)\n * @param options - Optional verification options\n * @returns The decoded JWT payload\n * @throws Error if the token is invalid, expired, or not yet valid\n *\n * @example\n * ```typescript\n * import { jwtVerify } from '@fresho/router/auth';\n *\n * try {\n * const payload = await jwtVerify(token, 'your-secret-key');\n * console.log(payload.sub); // user ID\n * } catch (error) {\n * console.error('Invalid token:', error.message);\n * }\n *\n * // With specific algorithms\n * const payload = await jwtVerify(token, secret, { algorithms: ['HS512'] });\n * ```\n */\nexport async function jwtVerify(\n token: string,\n secret: JwtSecret,\n options: VerifyJwtOptions = {},\n): Promise<JwtPayload> {\n const algorithms = options.algorithms || ['HS256'];\n\n const parts = token.split('.');\n if (parts.length !== 3) {\n throw new Error('Invalid JWT format');\n }\n\n const [headerB64, payloadB64, signatureB64] = parts;\n\n // Decode header.\n const header = JSON.parse(atob(headerB64.replace(/-/g, '+').replace(/_/g, '/')));\n if (!algorithms.includes(header.alg)) {\n throw new Error(`Unsupported algorithm: ${header.alg}`);\n }\n\n // Get the hash algorithm for the JWT algorithm.\n const hashAlg = ALGORITHM_MAP[header.alg as JwtAlgorithm];\n if (!hashAlg) {\n throw new Error(`Unknown algorithm: ${header.alg}`);\n }\n\n // Decode payload.\n const payload = JSON.parse(atob(payloadB64.replace(/-/g, '+').replace(/_/g, '/')));\n\n // Verify signature using Web Crypto API.\n const data = `${headerB64}.${payloadB64}`;\n const signature = Uint8Array.from(atob(signatureB64.replace(/-/g, '+').replace(/_/g, '/')), (c) =>\n c.charCodeAt(0),\n );\n\n let key: CryptoKey;\n if (secret instanceof CryptoKey) {\n key = secret;\n } else {\n const keyData = typeof secret === 'string' ? new TextEncoder().encode(secret) : secret;\n key = await crypto.subtle.importKey('raw', keyData, { name: 'HMAC', hash: hashAlg }, false, [\n 'verify',\n ]);\n }\n\n const valid = await crypto.subtle.verify('HMAC', key, signature, new TextEncoder().encode(data));\n\n if (!valid) {\n throw new Error('Invalid signature');\n }\n\n // Check expiration.\n if (payload.exp && payload.exp < Date.now() / 1000) {\n throw new Error('Token expired');\n }\n\n // Check not before.\n if (payload.nbf && payload.nbf > Date.now() / 1000) {\n throw new Error('Token not yet valid');\n }\n\n return payload as JwtPayload;\n}\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import { i as compose, n as MiddlewareContext, t as Middleware } from "../middleware-CqtYOc6D.mjs";
1
+ import { a as VerifyJwtOptions, i as SignJwtOptions, n as JwtPayload, o as jwtSign, r as JwtSecret, s as jwtVerify, t as JwtAlgorithm } from "../jwt-DHM_nSwL.mjs";
2
+ import { i as compose, n as MiddlewareContext, t as Middleware } from "../middleware-Bxq0LHLS.mjs";
2
3
 
3
4
  //#region src/middleware/auth.d.ts
4
5
 
@@ -27,49 +28,6 @@ interface BasicAuthOptions {
27
28
  * ```
28
29
  */
29
30
  declare function basicAuth(options: BasicAuthOptions): Middleware;
30
- /** JWT payload type. */
31
- interface JwtPayload {
32
- /** Subject (user ID). */
33
- sub?: string;
34
- /** Issued at timestamp. */
35
- iat?: number;
36
- /** Expiration timestamp. */
37
- exp?: number;
38
- /** Not before timestamp. */
39
- nbf?: number;
40
- /** Issuer. */
41
- iss?: string;
42
- /** Audience. */
43
- aud?: string | string[];
44
- /** Additional claims. */
45
- [key: string]: unknown;
46
- }
47
- /** Supported HMAC algorithms for JWT signing/verification. */
48
- type JwtAlgorithm = 'HS256' | 'HS384' | 'HS512';
49
- /** Options for signing a JWT. */
50
- interface SignJwtOptions {
51
- /** Signing algorithm (default: 'HS256'). */
52
- algorithm?: JwtAlgorithm;
53
- /** Expiration time (e.g., '1h', '7d', '30m', or seconds as number). */
54
- expiresIn?: string | number;
55
- /** Not before time (e.g., '5m', or seconds as number). */
56
- notBefore?: string | number;
57
- /** Issuer claim. */
58
- issuer?: string;
59
- /** Audience claim. */
60
- audience?: string | string[];
61
- /** Subject claim. */
62
- subject?: string;
63
- /** Custom issued-at timestamp (defaults to now). */
64
- issuedAt?: number | Date;
65
- }
66
- /** JWT secret value. */
67
- type JwtSecret = string | ArrayBuffer | CryptoKey;
68
- /** Options for verifying a JWT. */
69
- interface VerifyJwtOptions {
70
- /** Allowed algorithms (default: ['HS256']). */
71
- algorithms?: JwtAlgorithm[];
72
- }
73
31
  /** JWT authentication middleware configuration. */
74
32
  interface JwtAuthOptions<Ctx = {}> {
75
33
  /** Secret key or function to get the secret from context. */
@@ -84,61 +42,6 @@ interface JwtAuthOptions<Ctx = {}> {
84
42
  /** Function to extract token from request (default: Authorization header or 'token' cookie). */
85
43
  getToken?: (request: Request) => string | null;
86
44
  }
87
- /**
88
- * Verifies a JWT token using Web Crypto API.
89
- *
90
- * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
91
- *
92
- * @param token - The JWT token string to verify
93
- * @param secret - The secret used to sign the token (string, ArrayBuffer, or CryptoKey)
94
- * @param options - Optional verification options
95
- * @returns The decoded JWT payload
96
- * @throws Error if the token is invalid, expired, or not yet valid
97
- *
98
- * @example
99
- * ```typescript
100
- * import { jwtVerify } from '@fresho/router/middleware';
101
- *
102
- * try {
103
- * const payload = await jwtVerify(token, 'your-secret-key');
104
- * console.log(payload.sub); // user ID
105
- * } catch (error) {
106
- * console.error('Invalid token:', error.message);
107
- * }
108
- *
109
- * // With specific algorithms
110
- * const payload = await jwtVerify(token, secret, { algorithms: ['HS512'] });
111
- * ```
112
- */
113
- declare function jwtVerify(token: string, secret: string | ArrayBuffer | CryptoKey, options?: VerifyJwtOptions): Promise<JwtPayload>;
114
- /**
115
- * Signs a JWT token using Web Crypto API.
116
- *
117
- * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
118
- *
119
- * @param payload - The JWT payload (custom claims)
120
- * @param secret - The signing secret (string, ArrayBuffer, or CryptoKey)
121
- * @param options - Optional signing options (algorithm, expiresIn, issuer, etc.)
122
- * @returns The signed JWT token string
123
- *
124
- * @example
125
- * ```typescript
126
- * // Basic usage (HS256 by default)
127
- * const token = await jwtSign(
128
- * { uid: 'user-123', role: 'admin' },
129
- * 'your-secret-key',
130
- * { expiresIn: '1h' }
131
- * );
132
- *
133
- * // With HS512 algorithm
134
- * const token = await jwtSign(
135
- * { uid: 'user-123' },
136
- * process.env.JWT_SECRET,
137
- * { algorithm: 'HS512', expiresIn: '7d' }
138
- * );
139
- * ```
140
- */
141
- declare function jwtSign(payload: Record<string, unknown>, secret: JwtSecret, options?: SignJwtOptions): Promise<string>;
142
45
  /**
143
46
  * Creates a JWT authentication middleware.
144
47
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/middleware/auth.ts","../../src/middleware/common.ts","../../src/middleware/cors.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/middleware/auth.ts","../../src/middleware/common.ts","../../src/middleware/cors.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,7 +1,14 @@
1
- import { t as compose } from "../middleware-BpFh0XrR.mjs";
1
+ import { t as compose } from "../middleware-XMbIevSv.mjs";
2
+ import { a as parseBasicAuth, n as jwtVerify, t as jwtSign } from "../jwt-Dab9kOC2.mjs";
2
3
 
3
4
  //#region src/middleware/auth.ts
4
5
  /**
6
+ * @fileoverview Authentication middleware for @fresho/router.
7
+ *
8
+ * Provides middleware wrappers for Basic HTTP, JWT, and Bearer token authentication.
9
+ * The underlying authentication utilities are in `@fresho/router/auth`.
10
+ */
11
+ /**
5
12
  * Creates a Basic HTTP authentication middleware.
6
13
  *
7
14
  * @example
@@ -22,18 +29,13 @@ function basicAuth(options) {
22
29
  const realm = options.realm || "Secure Area";
23
30
  return async (context, next) => {
24
31
  const { request } = context;
25
- const authHeader = request.headers.get("Authorization");
26
- if (!authHeader?.startsWith("Basic ")) return new Response("Unauthorized", {
32
+ const credentials = parseBasicAuth(request.headers.get("Authorization"));
33
+ if (!credentials) return new Response("Unauthorized", {
27
34
  status: 401,
28
35
  headers: { "WWW-Authenticate": `Basic realm="${realm}", charset="UTF-8"` }
29
36
  });
30
37
  try {
31
- const credentials = atob(authHeader.slice(6));
32
- const colonIndex = credentials.indexOf(":");
33
- if (colonIndex === -1) throw new Error("Invalid credentials format");
34
- const username = credentials.substring(0, colonIndex);
35
- const password = credentials.substring(colonIndex + 1);
36
- const claims = await options.verify(username, password, context);
38
+ const claims = await options.verify(credentials.username, credentials.password, context);
37
39
  if (claims === null) return new Response("Invalid credentials", {
38
40
  status: 401,
39
41
  headers: { "WWW-Authenticate": `Basic realm="${realm}", charset="UTF-8"` }
@@ -48,147 +50,6 @@ function basicAuth(options) {
48
50
  }
49
51
  };
50
52
  }
51
- /** Maps JWT algorithm names to Web Crypto hash names. */
52
- const ALGORITHM_MAP = {
53
- HS256: "SHA-256",
54
- HS384: "SHA-384",
55
- HS512: "SHA-512"
56
- };
57
- /**
58
- * Verifies a JWT token using Web Crypto API.
59
- *
60
- * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
61
- *
62
- * @param token - The JWT token string to verify
63
- * @param secret - The secret used to sign the token (string, ArrayBuffer, or CryptoKey)
64
- * @param options - Optional verification options
65
- * @returns The decoded JWT payload
66
- * @throws Error if the token is invalid, expired, or not yet valid
67
- *
68
- * @example
69
- * ```typescript
70
- * import { jwtVerify } from '@fresho/router/middleware';
71
- *
72
- * try {
73
- * const payload = await jwtVerify(token, 'your-secret-key');
74
- * console.log(payload.sub); // user ID
75
- * } catch (error) {
76
- * console.error('Invalid token:', error.message);
77
- * }
78
- *
79
- * // With specific algorithms
80
- * const payload = await jwtVerify(token, secret, { algorithms: ['HS512'] });
81
- * ```
82
- */
83
- async function jwtVerify(token, secret, options = {}) {
84
- const algorithms = options.algorithms || ["HS256"];
85
- const parts = token.split(".");
86
- if (parts.length !== 3) throw new Error("Invalid JWT format");
87
- const [headerB64, payloadB64, signatureB64] = parts;
88
- const header = JSON.parse(atob(headerB64.replace(/-/g, "+").replace(/_/g, "/")));
89
- if (!algorithms.includes(header.alg)) throw new Error(`Unsupported algorithm: ${header.alg}`);
90
- const hashAlg = ALGORITHM_MAP[header.alg];
91
- if (!hashAlg) throw new Error(`Unknown algorithm: ${header.alg}`);
92
- const payload = JSON.parse(atob(payloadB64.replace(/-/g, "+").replace(/_/g, "/")));
93
- const data = `${headerB64}.${payloadB64}`;
94
- const signature = Uint8Array.from(atob(signatureB64.replace(/-/g, "+").replace(/_/g, "/")), (c) => c.charCodeAt(0));
95
- let key;
96
- if (secret instanceof CryptoKey) key = secret;
97
- else {
98
- const keyData = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
99
- key = await crypto.subtle.importKey("raw", keyData, {
100
- name: "HMAC",
101
- hash: hashAlg
102
- }, false, ["verify"]);
103
- }
104
- if (!await crypto.subtle.verify("HMAC", key, signature, new TextEncoder().encode(data))) throw new Error("Invalid signature");
105
- if (payload.exp && payload.exp < Date.now() / 1e3) throw new Error("Token expired");
106
- if (payload.nbf && payload.nbf > Date.now() / 1e3) throw new Error("Token not yet valid");
107
- return payload;
108
- }
109
- /**
110
- * Parses a duration string (e.g., '1h', '7d', '30m') to seconds.
111
- */
112
- function parseDuration(duration) {
113
- if (typeof duration === "number") return duration;
114
- const match = duration.match(/^(\d+)\s*(s|m|h|d|w)$/i);
115
- if (!match) throw new Error(`Invalid duration format: ${duration}. Use formats like '1h', '7d', '30m', '60s'.`);
116
- const value = parseInt(match[1], 10);
117
- const unit = match[2].toLowerCase();
118
- switch (unit) {
119
- case "s": return value;
120
- case "m": return value * 60;
121
- case "h": return value * 60 * 60;
122
- case "d": return value * 60 * 60 * 24;
123
- case "w": return value * 60 * 60 * 24 * 7;
124
- default: throw new Error(`Unknown duration unit: ${unit}`);
125
- }
126
- }
127
- /**
128
- * Base64url encodes a string or Uint8Array.
129
- */
130
- function base64urlEncode(data) {
131
- const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
132
- const binary = String.fromCharCode(...bytes);
133
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
134
- }
135
- /**
136
- * Signs a JWT token using Web Crypto API.
137
- *
138
- * Uses only Web Crypto API, compatible with Cloudflare Workers, Deno, and browsers.
139
- *
140
- * @param payload - The JWT payload (custom claims)
141
- * @param secret - The signing secret (string, ArrayBuffer, or CryptoKey)
142
- * @param options - Optional signing options (algorithm, expiresIn, issuer, etc.)
143
- * @returns The signed JWT token string
144
- *
145
- * @example
146
- * ```typescript
147
- * // Basic usage (HS256 by default)
148
- * const token = await jwtSign(
149
- * { uid: 'user-123', role: 'admin' },
150
- * 'your-secret-key',
151
- * { expiresIn: '1h' }
152
- * );
153
- *
154
- * // With HS512 algorithm
155
- * const token = await jwtSign(
156
- * { uid: 'user-123' },
157
- * process.env.JWT_SECRET,
158
- * { algorithm: 'HS512', expiresIn: '7d' }
159
- * );
160
- * ```
161
- */
162
- async function jwtSign(payload, secret, options = {}) {
163
- const algorithm = options.algorithm || "HS256";
164
- const hashAlg = ALGORITHM_MAP[algorithm];
165
- const now = options.issuedAt ? options.issuedAt instanceof Date ? Math.floor(options.issuedAt.getTime() / 1e3) : options.issuedAt : Math.floor(Date.now() / 1e3);
166
- const finalPayload = {
167
- ...payload,
168
- iat: now
169
- };
170
- if (options.expiresIn !== void 0) finalPayload.exp = now + parseDuration(options.expiresIn);
171
- if (options.notBefore !== void 0) finalPayload.nbf = now + parseDuration(options.notBefore);
172
- if (options.issuer !== void 0) finalPayload.iss = options.issuer;
173
- if (options.audience !== void 0) finalPayload.aud = options.audience;
174
- if (options.subject !== void 0) finalPayload.sub = options.subject;
175
- const header = {
176
- alg: algorithm,
177
- typ: "JWT"
178
- };
179
- const data = `${base64urlEncode(JSON.stringify(header))}.${base64urlEncode(JSON.stringify(finalPayload))}`;
180
- let key;
181
- if (secret instanceof CryptoKey) key = secret;
182
- else {
183
- const keyData = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
184
- key = await crypto.subtle.importKey("raw", keyData, {
185
- name: "HMAC",
186
- hash: hashAlg
187
- }, false, ["sign"]);
188
- }
189
- const signatureBuffer = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(data));
190
- return `${data}.${base64urlEncode(new Uint8Array(signatureBuffer))}`;
191
- }
192
53
  /**
193
54
  * Creates a JWT authentication middleware.
194
55
  *