### Quick Start: Setup JWT Middleware and Endpoints in Farrow Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This TypeScript example shows how to set up JWT authentication middleware in a Farrow application. It defines a user type, creates a JWT context, configures access and refresh tokens, applies the middleware, and demonstrates login, protected, and refresh endpoints. ```typescript import { Http, Response } from 'farrow-http' import { createJWTMiddleware, createJwtDataCtx } from 'farrow-auth-jwt' // Define your user type interface User { id: number username: string role: 'admin' | 'user' } // Create JWT context const userContext = createJwtDataCtx() // Create middleware const jwtMiddleware = createJWTMiddleware({ access: { secret: 'your-access-secret', signOptions: { expiresIn: '15m' } }, refresh: { secret: 'your-refresh-secret', signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: ['/login', '/register', '/refresh'] }) // Apply middleware const app = Http() app.use(jwtMiddleware) // Login endpoint app.post('/login').use((request) => { const { username, password } = request.body // Validate credentials... const user: User = { id: 1, username, role: 'user' } // Sign tokens return userContext.sign(user) }) // Protected endpoint app.get('/profile').use(() => { const user = userContext.get() // Note: Without passNoToken: true, requests without token won't reach here // The middleware will return 401 directly, so user is guaranteed to exist return Response.json(user) }) // Refresh endpoint app.post('/refresh').use(async () => { return await userContext.refresh() }) app.listen(3000) ``` -------------------------------- ### Install farrow-auth-jwt using npm, yarn, or pnpm Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md These commands demonstrate how to install the farrow-auth-jwt package using different package managers. This is the first step to integrate JWT authentication into your Farrow application. ```bash npm install farrow-auth-jwt # or yarn add farrow-auth-jwt # or pnpm add farrow-auth-jwt ``` -------------------------------- ### JWT Token Refresh Flow Configuration Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This comprehensive example details the setup and usage of a token refresh flow using JWT. It covers configuring JWT middleware with separate secrets and expiration times for access and refresh tokens, returning both tokens upon login, defining a protected refresh endpoint, and client-side usage for obtaining new tokens. ```typescript // 1. Configure refresh tokens const jwtMiddleware = createJWTMiddleware({ access: { secret: ACCESS_SECRET, signOptions: { expiresIn: '15m' } // Short-lived }, refresh: { secret: REFRESH_SECRET, signOptions: { expiresIn: '7d' } // Long-lived }, jwtDataCtx: userContext, whitelist: ['/auth/refresh'] // Important: Add refresh endpoint to whitelist }) // 2. Login returns both tokens app.post('/auth/login').use((request) => { const user = validateCredentials(request.body) return userContext.sign(user) // Returns: { token: "...", refreshToken: "..." } }) // 3. Refresh endpoint (must be in whitelist) app.post('/auth/refresh').use(async (request) => { // Only refresh token is validated, no access token needed return await userContext.refresh() // Returns: { token: "new...", refreshToken: "new..." } }) // 4. Client usage // When access token expires, use refresh token to get new tokens fetch('/auth/refresh', { method: 'POST', body: JSON.stringify({ refreshToken: savedRefreshToken }) }) ``` -------------------------------- ### Advanced Whitelist Rules using path-to-regexp syntax Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This TypeScript array demonstrates how to define whitelist rules for JWT authentication using path-to-regexp syntax. It shows examples of simple paths, paths with parameters (including optional ones), wildcard matching, and restricting rules to specific HTTP methods. ```typescript const whitelist: WhitelistRule[] = [ // Simple path '/public', // Path parameters '/users/:id', // matches /users/123 '/api/users/:id?', // optional parameter, matches /api/users and /api/users/123 // Wildcard (Note: v8 uses {*} syntax) '/public/{*path}', // matches all paths under /public/ // With method restriction { path: '/auth/login', methods: ['POST'] }, { path: '/api/upload', methods: ['POST', 'PUT'] } ] ``` -------------------------------- ### Complete Authentication System with Farrow Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt A comprehensive example of an authentication system using `farrow-http` and `farrow-auth-jwt`. It includes user registration, login with password hashing (bcrypt), JWT access and refresh token generation, and protected routes with role-based authorization. The `createJWTMiddleware` handles token validation and injection of user data into context, while whitelisting ensures unauthenticated access to specific endpoints. ```typescript import { Http, Response } from 'farrow-http' import { createJWTMiddleware, createJwtDataCtx, JWTErrorContext } from 'farrow-auth-jwt' import * as bcrypt from 'bcrypt' interface User { id: number username: string email: string role: 'admin' | 'user' } // Create user context const userContext = createJwtDataCtx() // Mock database const users: Map = new Map() // Configure JWT middleware const jwtMiddleware = createJWTMiddleware({ access: { secret: process.env.JWT_ACCESS_SECRET!, signOptions: { expiresIn: '15m' } }, refresh: { secret: process.env.JWT_REFRESH_SECRET!, signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: [ '/auth/register', '/auth/login', '/auth/refresh', '/public/{*path}', { path: '/api/docs', methods: ['GET'] } ] }) // Create app const app = Http() // Apply middleware app.use(jwtMiddleware) // Registration endpoint app.post('/auth/register').use(async (request) => { const { username, email, password } = request.body if (users.has(username)) { return Response.status(400).json({ error: 'Username already exists' }) } const passwordHash = await bcrypt.hash(password, 10) const user = { id: users.size + 1, username, email, passwordHash, role: 'user' as const } users.set(username, user) return Response.status(201).json({ message: 'User registered successfully', userId: user.id }) }) // Login endpoint app.post('/auth/login').use(async (request) => { const { username, password } = request.body const user = users.get(username) if (!user) { return Response.status(401).json({ error: 'Invalid credentials' }) } const isValid = await bcrypt.compare(password, user.passwordHash) if (!isValid) { return Response.status(401).json({ error: 'Invalid credentials' }) } // Sign and return tokens return userContext.sign({ id: user.id, username: user.username, email: user.email, role: user.role }) }) // Refresh token endpoint app.post('/auth/refresh').use(async () => { return await userContext.refresh() }) // Protected profile endpoint app.get('/auth/profile').use(() => { const user = userContext.get() return Response.json({ user }) }) // Admin-only endpoint app.get('/admin/users').use(() => { const user = userContext.get() if (user?.role !== 'admin') { return Response.status(403).json({ error: 'Admin access required' }) } return Response.json({ users: Array.from(users.values()).map(u => ({ id: u.id, username: u.username, email: u.email, role: u.role })) }) }) // Public endpoint app.get('/public/info').use(() => { return Response.json({ name: 'My API', version: '1.0.0', endpoints: ['/auth/login', '/auth/register', '/auth/profile'] }) }) app.listen(3000, () => { console.log('Server running on http://localhost:3000') }) ``` -------------------------------- ### JWT Context Methods: Get, Sign, and Refresh Tokens Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This TypeScript snippet illustrates the core methods provided by the JWT context in farrow-auth-jwt. `get()` retrieves the current user's data, `sign()` creates new access and refresh tokens, and `refresh()` handles the token refresh process. ```typescript const userContext = createJwtDataCtx() // Get current user const user = userContext.get() // Sign new tokens const response = userContext.sign(userData) // Refresh tokens const response = await userContext.refresh() ``` -------------------------------- ### Implement Custom Token Parser with Farrow Auth JWT Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This example shows how to customize token extraction and response formatting using the `parser` option in `createJWTMiddleware`. It defines a `customParser` object with `getToken` to extract tokens from non-standard headers and request bodies, and `setToken` to format the response according to specific requirements. Client usage with custom headers is also illustrated. ```typescript import { RequestInfo, Response } from 'farrow-http' import { createJWTMiddleware } from 'farrow-auth-jwt' const customParser = { getToken: (request: RequestInfo) => { // Extract from custom headers const accessToken = request.headers?.['x-access-token'] || request.headers?.['x-api-key'] || null const refreshToken = request.headers?.['x-refresh-token'] || request.body?.refresh || null return { accessToken, refreshToken } }, setToken: (token: string, refreshToken?: string) => { // Return custom response format return Response.json({ success: true, data: { accessToken: token, refreshToken, expiresIn: 900, tokenType: 'Bearer' } }) } } const jwtMiddleware = createJWTMiddleware({ access: { secret: 'your-secret', signOptions: { expiresIn: '15m' } }, jwtDataCtx: userContext, parser: customParser }) // Client usage with custom headers: // fetch('/api/protected', { // headers: { // 'X-Access-Token': 'your_jwt_token', // 'X-Refresh-Token': 'your_refresh_token' // } // }) ``` -------------------------------- ### Token Revocation Implementation Example Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This TypeScript code snippet shows how to implement token revocation in farrow-auth-jwt. It demonstrates checking if a user is banned or if a token exists in a revoked tokens set, which can be used for blacklisting tokens. ```typescript const revokedTokens = new Set() const jwtMiddleware = createJWTMiddleware({ // ... other options isRevoked: async (payload: User) => { // Check if user is banned const user = await db.users.findById(payload.id) return user.status === 'banned' // Or check token blacklist // return revokedTokens.has(payload.jti) } }) ``` -------------------------------- ### Mixed Authentication (Public + Protected) with JWT Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This example shows how to configure JWT middleware to allow both authenticated and anonymous access. By setting `passNoToken: true`, requests without a token are not rejected, enabling conditional logic to serve different responses based on user authentication status. ```typescript const jwtMiddleware = createJWTMiddleware({ // ... other options passNoToken: true // Don't reject requests without token }) app.get('/posts').use(() => { const user = userContext.get() if (user) { // Return all posts for authenticated users return Response.json({ posts: getAllPosts(), user }) } else { // Return only public posts for anonymous users return Response.json({ posts: getPublicPosts() }) } }) ``` -------------------------------- ### API Reference - Utility Functions and Types Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Reference for utility functions and type definitions provided by the farrow-auth-jwt library. ```APIDOC ## API Reference - Utility Functions and Types ### `extractBearerToken(authHeader)` - **Description**: Extracts a JWT token from a standard 'Authorization: Bearer ' HTTP header string. - **Parameters**: - `authHeader` (`string` | `undefined`) - The value of the 'Authorization' header. - **Returns**: `string` | `null` - The extracted token string, or null if the header is missing or malformed. ### `JWTErrorContext` - **Description**: A context object that holds the state of the most recent JWT error encountered during request processing. It allows access to error details within your application logic. ### Types #### `JWTError` - **Description**: Represents the possible errors that can occur during JWT processing. - **Possible Values**: - `{ type: 'TOKEN_EXPIRED'; expiredAt?: Date }` - The token has expired. - `{ type: 'INVALID_TOKEN'; message: string }` - The token is invalid (e.g., malformed signature, incorrect claims). - `{ type: 'NO_TOKEN' }` - No token was provided in the request. - `{ type: 'TOKEN_REVOKED' }` - The token has been explicitly revoked. #### `WhitelistRule` - **Description**: Defines rules for whitelisting specific endpoints or HTTP methods, allowing them to bypass JWT authentication middleware. - **Possible Values**: - `string` - A path pattern (e.g., `/public/*`). - `object` - A more specific rule: - `path` (`string`): The path pattern for the rule. - `methods` (`string[]`, optional): An array of HTTP methods (e.g., `['GET', 'POST']`) to apply this rule to. If omitted, the rule applies to all methods. ``` -------------------------------- ### API Reference - Core Functions Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Reference for the core functions provided by the farrow-auth-jwt library. ```APIDOC ## API Reference - Core Functions ### `createJwtDataCtx()` - **Description**: Creates a JSON Web Token (JWT) context with a specified type `D` for holding user data. - **Type Parameter**: `D` - The type of the data to be stored within the JWT context. ### `createJWTMiddleware(options)` - **Description**: Generates and returns the JWT authentication middleware. This middleware can be integrated into your application to protect routes and manage token validation. - **Type Parameter**: `D` - The expected type of the decoded JWT payload. - **Parameters**: `options` - An object containing configuration settings for the middleware (e.g., secrets, token validation options, whitelist). ### `verifyToken(token, secret, options?)` - **Description**: Manually verifies a given JWT token against a specified secret. Useful for custom token handling scenarios outside the standard middleware flow. - **Type Parameter**: `D` - The expected type of the decoded JWT payload. - **Parameters**: - `token` (`string`) - The JWT token string to verify. - `secret` (`string` | `Buffer`) - The secret key used for signing the token. - `options` (`object`, optional) - Verification options (e.g., algorithms, audience). - **Returns**: `Result` - A result object containing either the decoded payload (`D`) on success or a `JWTError` on failure. ``` -------------------------------- ### Configure JWT Middleware with createJWTMiddleware Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Sets up the JWT authentication middleware for Farrow HTTP, including access and refresh token configurations, a JWT data context, and whitelisted paths. This middleware handles token validation and protection of routes. ```typescript import { Http, Response } from 'farrow-http' import { createJWTMiddleware, createJwtDataCtx } from 'farrow-auth-jwt' interface User { id: number username: string role: 'admin' | 'user' } const userContext = createJwtDataCtx() const jwtMiddleware = createJWTMiddleware({ access: { secret: 'your-access-secret-key', signOptions: { expiresIn: '15m' } }, refresh: { secret: 'your-refresh-secret-key', signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: ['/login', '/register', '/public/{*path}'] }) const app = Http() app.use(jwtMiddleware) app.post('/login').use((request) => { const { username, password } = request.body // Validate credentials (pseudo-code) if (username === 'admin' && password === 'secret') { return userContext.sign({ id: 1, username, role: 'admin' }) } return Response.status(401).json({ error: 'Invalid credentials' }) }) app.get('/profile').use(() => { const user = userContext.get() return Response.json({ user }) }) app.listen(3000) ``` -------------------------------- ### JWT Middleware Configuration Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Creates and configures the JWT authentication middleware with support for both access and refresh tokens. This middleware handles token validation and integrates with a provided JWT data context. ```APIDOC ## createJWTMiddleware ### Description Creates and configures the JWT authentication middleware with access and refresh token support. ### Method Function ### Endpoint N/A (Server-side middleware setup) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **options** (object) - Required - Configuration options for the JWT middleware. - **access** (object) - Required - Configuration for access tokens. - **secret** (string) - Required - The secret key for signing and verifying access tokens. - **signOptions** (object) - Optional - Options for signing access tokens (e.g., `expiresIn`). - **refresh** (object) - Required - Configuration for refresh tokens. - **secret** (string) - Required - The secret key for signing and verifying refresh tokens. - **signOptions** (object) - Optional - Options for signing refresh tokens (e.g., `expiresIn`). - **jwtDataCtx** (object) - Required - The JWT data context created by `createJwtDataCtx`. - **whitelist** (array) - Optional - An array of paths or path patterns that should not require authentication. ### Request Example ```typescript import { Http, Response } from 'farrow-http' import { createJWTMiddleware, createJwtDataCtx } from 'farrow-auth-jwt' interface User { id: number username: string role: 'admin' | 'user' } const userContext = createJwtDataCtx() const jwtMiddleware = createJWTMiddleware({ access: { secret: 'your-access-secret-key', signOptions: { expiresIn: '15m' } }, refresh: { secret: 'your-refresh-secret-key', signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: ['/login', '/register', '/public/{*path}'] }) const app = Http() app.use(jwtMiddleware) app.post('/login').use((request) => { const { username, password } = request.body // Validate credentials (pseudo-code) if (username === 'admin' && password === 'secret') { return userContext.sign({ id: 1, username, role: 'admin' }) } return Response.status(401).json({ error: 'Invalid credentials' }) }) app.get('/profile').use(() => { const user = userContext.get() return Response.json({ user }) }) app.listen(3000) ``` ### Response #### Success Response (N/A) Returns an Express-compatible middleware function. #### Response Example ```json { "middleware": "function" } ``` ``` -------------------------------- ### farrow-auth-jwt Middleware Options Configuration Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This TypeScript interface defines the configuration options for the `createJWTMiddleware` function. It covers settings for access and refresh tokens (secrets, sign/verify options), the JWT data context, token revocation checks, whitelisting paths, custom token parsing, and handling requests without tokens. ```typescript interface JWTMiddlewareOptions { // Access token configuration access: { secret: string | Buffer signOptions?: jwt.SignOptions verifyOptions?: jwt.VerifyOptions } // Optional refresh token configuration refresh?: { secret: string | Buffer signOptions?: jwt.SignOptions verifyOptions?: jwt.VerifyOptions } // JWT data context jwtDataCtx: JwtDataCtx // Optional token revocation checker isRevoked?: (payload: D) => boolean | Promise // Whitelist paths that don't require authentication whitelist?: WhitelistRule[] // Custom token parser parser?: { getToken: (request: RequestInfo) => { accessToken: string | null refreshToken: string | null } setToken: (token: string, refreshToken?: string) => Response } // Allow requests without token to continue passNoToken?: boolean } ``` -------------------------------- ### Whitelist Rules Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Defines rules for whitelisting public endpoints that do not require authentication. Supports various path matching patterns and method restrictions. ```APIDOC ## Whitelist Rules ### Description Configure public endpoints that don't require authentication using path-to-regexp patterns and HTTP method restrictions. ### Method N/A (Configuration array) ### Endpoint N/A (Used within `createJWTMiddleware` options) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **whitelist** (array) - An array of `WhitelistRule` objects or strings. - **WhitelistRule** (object) - Optional. Defines a specific path and allowed methods. - **path** (string) - Required - The path pattern (supports `path-to-regexp` syntax). - **methods** (array) - Optional - An array of HTTP methods (e.g., 'GET', 'POST') that are allowed for this path. If not provided, all methods are allowed. ### Request Example ```typescript import { createJWTMiddleware, WhitelistRule } from 'farrow-auth-jwt' const whitelist: WhitelistRule[] = [ // Simple path '/public', // Path with parameters '/users/:id', // Optional parameters '/api/users/:id?', // Wildcard paths (v8 syntax) '/public/{*path}', '/assets/{*file}', // Method-specific rules { path: '/auth/login', methods: ['POST'] }, { path: '/auth/register', methods: ['POST'] }, { path: '/api/docs', methods: ['GET', 'HEAD'] } ] const jwtMiddleware = createJWTMiddleware({ access: { secret: process.env.JWT_SECRET!, signOptions: { expiresIn: '1h' } }, jwtDataCtx: userContext, whitelist }) const app = Http() app.use(jwtMiddleware) // POST /auth/login is whitelisted - no token required app.post('/auth/login').use(() => { return Response.json({ message: 'Login endpoint' }) }) // GET /auth/login is NOT whitelisted - token required app.get('/auth/login').use(() => { return Response.json({ message: 'Protected' }) }) app.listen(3000) ``` ### Response #### Success Response (N/A) N/A (This is a configuration structure used within `createJWTMiddleware`) #### Response Example ```json [ "/public", "/users/:id", { "path": "/auth/login", "methods": ["POST"] } ] ``` ``` -------------------------------- ### Create Typed JWT Context with createJwtDataCtx Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Initializes a type-safe context for managing JWT data, such as user information, within Farrow HTTP requests. It enables operations like retrieving authenticated user data and signing/refreshing JWTs. ```typescript import { createJwtDataCtx } from 'farrow-auth-jwt' interface User { id: number username: string role: 'admin' | 'user' } const userContext = createJwtDataCtx() // Usage in route handlers: // Get authenticated user data const user = userContext.get() // Sign new tokens with user data const response = userContext.sign({ id: 1, username: 'john', role: 'user' }) // Refresh tokens using existing refresh token const refreshResponse = await userContext.refresh() ``` -------------------------------- ### JWT Data Context Creation Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Creates a typed JWT context for managing user authentication state throughout the request lifecycle. This context allows for retrieving authenticated user data and signing/refreshing JWTs. ```APIDOC ## createJwtDataCtx ### Description Creates a typed JWT context for managing user authentication state throughout the request lifecycle. ### Method Function ### Endpoint N/A (Client-side function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **User Type** (Type): The type representing the user data to be stored in the JWT. ### Request Example ```typescript import { createJwtDataCtx } from 'farrow-auth-jwt' interface User { id: number username: string role: 'admin' | 'user' } const userContext = createJwtDataCtx() // Usage in route handlers: // Get authenticated user data const user = userContext.get() // Sign new tokens with user data const response = userContext.sign({ id: 1, username: 'john', role: 'user' }) // Refresh tokens using existing refresh token const refreshResponse = await userContext.refresh() ``` ### Response #### Success Response (N/A) Returns a JWT context object with `get`, `sign`, and `refresh` methods. #### Response Example ```json { "get": "function", "sign": "function", "refresh": "function" } ``` ``` -------------------------------- ### Custom Token Parser Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This section explains how to customize the token extraction and response format to support non-standard authentication schemes. ```APIDOC ## POST /api/protected (Example) ### Description An example protected endpoint demonstrating client-side usage with custom token headers. ### Method GET or POST (depending on the original request) ### Endpoint /api/protected ### Parameters #### Request Headers - **X-Access-Token** (string) - Required - The custom access token. - **X-Refresh-Token** (string) - Optional - The custom refresh token. ### Request Example ```javascript fetch('/api/protected', { headers: { 'X-Access-Token': 'your_jwt_token', 'X-Refresh-Token': 'your_refresh_token' } }) ``` ### Response #### Success Response (200) - The response from the protected endpoint. #### Response Example (Varies based on the endpoint) ```json { "data": "Protected resource" } ``` ``` -------------------------------- ### Custom Token Parser Configuration Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Customize how JWT tokens are extracted from requests and formatted in responses. ```APIDOC ## Custom Token Parser Configuration ### Description Allows developers to define custom logic for extracting JWT access and refresh tokens from incoming requests and for formatting the tokens in responses. ### Method ```typescript const customParser = { getToken: (request: RequestInfo) => { ... }, setToken: (token: string, refreshToken?: string) => { ... } } ``` ### Parameters #### `getToken` function - **request** (`RequestInfo`) - The incoming request object. - **Returns** (`{ accessToken: string | null, refreshToken: string | null }`) - An object containing the extracted access and refresh tokens. #### `setToken` function - **token** (`string`) - The access token. - **refreshToken** (`string`, optional) - The refresh token. - **Returns** (`Response`) - A response object containing the tokens in a custom format. ``` -------------------------------- ### Implement Token Refresh Flow with Farrow Auth JWT Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This snippet demonstrates how to set up a token refresh mechanism to obtain new access tokens without requiring users to re-authenticate. It configures JWT middleware for both access and refresh tokens, defines a login endpoint that issues both tokens, and a refresh endpoint that validates the refresh token and issues new ones. Client-side error handling for expired access tokens is also illustrated. ```typescript import { Http, Response } from 'farrow-http' import { createJWTMiddleware, createJwtDataCtx } from 'farrow-auth-jwt' interface User { id: number username: string } const userContext = createJwtDataCtx() const jwtMiddleware = createJWTMiddleware({ access: { secret: 'access-secret', signOptions: { expiresIn: '15m' } }, refresh: { secret: 'refresh-secret', signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: ['/auth/login', '/auth/refresh'] }) const app = Http() app.use(jwtMiddleware) // Login returns both tokens app.post('/auth/login').use((request) => { const { username, password } = request.body // Validate credentials... const user = { id: 1, username } return userContext.sign(user) // Returns: { token: "access_jwt", refreshToken: "refresh_jwt" } }) // Refresh endpoint validates refresh token and issues new tokens app.post('/auth/refresh').use(async () => { return await userContext.refresh() // Returns: { token: "new_access_jwt", refreshToken: "new_refresh_jwt" } }) app.listen(3000) // Client-side usage example: // fetch('/api/protected', { // headers: { 'Authorization': `Bearer ${accessToken}` } // }).catch(async (error) => { // if (error.status === 401) { // const response = await fetch('/auth/refresh', { // method: 'POST', // body: JSON.stringify({ refreshToken }) // }) // const { token, refreshToken: newRefresh } = await response.json() // // Retry original request with new token // } // }) ``` -------------------------------- ### Custom Token Parser for JWT Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This snippet demonstrates how to create a custom token parser object. It defines `getToken` to extract access and refresh tokens from custom headers ('x-access-token' and 'x-refresh-token') and `setToken` to format tokens for the response in a specific structure. ```typescript const customParser = { getToken: (request: RequestInfo) => { // Extract from custom header const accessToken = request.headers?.['x-access-token'] || null const refreshToken = request.headers?.['x-refresh-token'] || null return { accessToken, refreshToken } }, setToken: (token: string, refreshToken?: string) => { // Return tokens in custom format return Response.json({ auth: { accessToken: token, refreshToken }, expiresIn: 900 }) } } ``` -------------------------------- ### JWT Whitelist Rule Definition Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Specifies the structure for defining whitelist rules for JWT middleware. Rules can be simple path strings or objects that include a path and an optional array of HTTP methods to whitelist. ```typescript type WhitelistRule = | string // Path pattern | { path: string methods?: string[] // HTTP methods } ``` -------------------------------- ### Token Refresh Flow Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This section details the implementation of a token refresh mechanism, allowing clients to obtain new access tokens using a refresh token without requiring full re-authentication. ```APIDOC ## POST /auth/login ### Description Logs in a user and returns both an access token and a refresh token. ### Method POST ### Endpoint /auth/login ### Parameters #### Request Body - **username** (string) - Required - The user's username. - **password** (string) - Required - The user's password. ### Request Example ```json { "username": "user", "password": "password" } ``` ### Response #### Success Response (200) - **token** (string) - The access JWT. - **refreshToken** (string) - The refresh JWT. #### Response Example ```json { "token": "access_jwt", "refreshToken": "refresh_jwt" } ``` --- ## POST /auth/refresh ### Description Refreshes an access token using a valid refresh token and issues new access and refresh tokens. ### Method POST ### Endpoint /auth/refresh ### Parameters #### Request Body - **refreshToken** (string) - Required - The refresh token obtained during login. ### Request Example ```json { "refreshToken": "refresh_jwt" } ``` ### Response #### Success Response (200) - **token** (string) - The new access JWT. - **refreshToken** (string) - The new refresh JWT. #### Response Example ```json { "token": "new_access_jwt", "refreshToken": "new_refresh_jwt" } ``` ``` -------------------------------- ### Token Revocation Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This section covers implementing token revocation, including blacklisting tokens and checking user status to invalidate tokens. ```APIDOC ## POST /auth/logout ### Description Logs out the current user by revoking their active token and adding it to a blacklist. ### Method POST ### Endpoint /auth/logout ### Parameters None ### Request Example ```json { "message": "Logged out successfully" } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating successful logout. #### Response Example ```json { "message": "Logged out successfully" } ``` ``` -------------------------------- ### Configure Whitelist Rules for Public Endpoints Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Defines public endpoints that bypass JWT authentication using path-to-regexp patterns and optional HTTP method restrictions. This allows specific routes, like login or public APIs, to be accessed without a token. ```typescript import { createJWTMiddleware, WhitelistRule } from 'farrow-auth-jwt' const whitelist: WhitelistRule[] = [ // Simple path '/public', // Path with parameters '/users/:id', // Optional parameters '/api/users/:id?', // Wildcard paths (v8 syntax) '/public/{*path}', '/assets/{*file}', // Method-specific rules { path: '/auth/login', methods: ['POST'] }, { path: '/auth/register', methods: ['POST'] }, { path: '/api/docs', methods: ['GET', 'HEAD'] } ] const jwtMiddleware = createJWTMiddleware({ access: { secret: process.env.JWT_SECRET!, signOptions: { expiresIn: '1h' } }, jwtDataCtx: userContext, whitelist }) const app = Http() app.use(jwtMiddleware) // POST /auth/login is whitelisted - no token required app.post('/auth/login').use(() => { return Response.json({ message: 'Login endpoint' }) }) // GET /auth/login is NOT whitelisted - token required app.get('/auth/login').use(() => { return Response.json({ message: 'Protected' }) }) app.listen(3000) ``` -------------------------------- ### JWT Error Handling with Context Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md This snippet illustrates how to access and handle JWT errors using `JWTErrorContext`. It demonstrates logging errors and returning custom HTTP responses based on the error type, such as 'TOKEN_EXPIRED' or 'INVALID_TOKEN'. ```typescript import { JWTErrorContext } from 'farrow-auth-jwt' app.use((request, next) => { const response = next(request) const error = JWTErrorContext.get() if (error) { // Log authentication errors console.log('JWT Error:', error) // Custom error response switch (error.type) { case 'TOKEN_EXPIRED': return Response.status(401).json({ error: 'Session expired', code: 'AUTH_EXPIRED' }) case 'INVALID_TOKEN': return Response.status(403).json({ error: 'Invalid credentials', code: 'AUTH_INVALID' }) // ... handle other errors } } return response }) ``` -------------------------------- ### JWT Error Handling Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Access and handle JWT-related errors within your application context for custom error responses and logging. ```APIDOC ## JWT Error Handling ### Description Provides a mechanism to intercept and manage JWT errors, allowing for custom logging and standardized error responses to the client. ### Usage ```typescript import { JWTErrorContext } from 'farrow-auth-jwt' app.use((request, next) => { const response = next(request) const error = JWTErrorContext.get() if (error) { // Handle specific error types switch (error.type) { case 'TOKEN_EXPIRED': return Response.status(401).json({ error: 'Session expired', code: 'AUTH_EXPIRED' }) case 'INVALID_TOKEN': return Response.status(403).json({ error: 'Invalid credentials', code: 'AUTH_INVALID' }) // ... other error types } } return response }) ``` ### `JWTErrorContext` - A context object used to retrieve the current JWT error state within the request lifecycle. ``` -------------------------------- ### Implement Token Revocation with Farrow Auth JWT Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt This snippet details how to implement token revocation, including blacklisting tokens and performing user-based revocation checks. It uses an in-memory set for revoked tokens (suggesting Redis for production) and defines an `isRevoked` function to check user status or token presence in the blacklist. A logout endpoint is provided to add tokens to the revoked list. ```typescript import { createJWTMiddleware } from 'farrow-auth-jwt' interface User { id: number username: string status: 'active' | 'banned' } // In-memory blacklist (use Redis in production) const revokedTokens = new Set() const jwtMiddleware = createJWTMiddleware({ access: { secret: 'your-secret', signOptions: { expiresIn: '1h' } }, jwtDataCtx: userContext, isRevoked: async (payload: User) => { // Method 1: Check user status in database const user = await database.users.findById(payload.id) if (user.status === 'banned') { return true } // Method 2: Check token ID against blacklist if (payload.jti && revokedTokens.has(payload.jti)) { return true } return false } }) // Revoke token endpoint app.post('/auth/logout').use(() => { const user = userContext.get() if (user && user.jti) { revokedTokens.add(user.jti) } return Response.json({ message: 'Logged out successfully' }) }) ``` -------------------------------- ### Manual JWT Token Verification with Farrow Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Manually verify JWT tokens using the `verifyToken` function from `farrow-auth-jwt` outside of the middleware. This allows for custom logic in middleware or directly within route handlers to validate tokens, check their validity, and extract user data. It returns a `Result` type indicating success or failure. ```typescript import { verifyToken } from 'farrow-auth-jwt' interface User { id: number username: string } // Verify a token manually const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' const result = verifyToken(token, 'your-secret', { algorithms: ['HS256'], audience: 'your-app' }) if (result.kind === 'Ok') { const user = result.value console.log('Valid token:', user) // { id: 1, username: 'john' } } else { const error = result.value console.error('Invalid token:', error) // { type: 'TOKEN_EXPIRED', expiredAt: Date } or // { type: 'INVALID_TOKEN', message: 'jwt malformed' } } // Use in custom middleware const customAuthMiddleware = (request, next) => { const authHeader = request.headers?.authorization if (!authHeader) { return Response.status(401).json({ error: 'No auth header' }) } const token = authHeader.replace('Bearer ', '') const result = verifyToken(token, process.env.JWT_SECRET!) if (result.kind === 'Err') { return Response.status(401).json({ error: result.value }) } // Attach user to request context return next(request) } ``` -------------------------------- ### Token Refresh Flow Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Implement a secure token refresh mechanism allowing clients to obtain new access tokens using long-lived refresh tokens. ```APIDOC ## Token Refresh Flow ### Description This flow enables users to maintain authenticated sessions by obtaining new, short-lived access tokens using persistent refresh tokens, enhancing user experience without frequent re-logins. ### Setup 1. **Configure Refresh Tokens**: Initialize the JWT middleware with separate secrets and expiration times for access and refresh tokens. Ensure the refresh endpoint is whitelisted. ```typescript const jwtMiddleware = createJWTMiddleware({ access: { secret: ACCESS_SECRET, signOptions: { expiresIn: '15m' } }, refresh: { secret: REFRESH_SECRET, signOptions: { expiresIn: '7d' } }, jwtDataCtx: userContext, whitelist: ['/auth/refresh'] }) ``` 2. **Login Endpoint**: Upon successful login, return both the access token and the refresh token. ```typescript app.post('/auth/login').use((request) => { const user = validateCredentials(request.body) return userContext.sign(user) // Returns { token: '...', refreshToken: '...' } }) ``` 3. **Refresh Endpoint**: Create an endpoint (e.g., `/auth/refresh`) that handles the refresh token validation and issues new tokens. This endpoint must be included in the middleware's whitelist. ```typescript app.post('/auth/refresh').use(async (request) => { return await userContext.refresh() // Returns: { token: 'new_access_token', refreshToken: 'new_refresh_token' } }) ``` 4. **Client Usage**: When the access token expires, the client should use the stored refresh token to request new tokens from the refresh endpoint. ```javascript fetch('/auth/refresh', { method: 'POST', body: JSON.stringify({ refreshToken: savedRefreshToken }) }) ``` ### Key Components - **`access`**: Configuration for the short-lived access token. - **`refresh`**: Configuration for the long-lived refresh token. - **`whitelist`**: An array of paths or path/method combinations that bypass JWT validation. ``` -------------------------------- ### Mixed Authentication (Public + Protected Endpoints) Source: https://github.com/aisonsu/farrow-auth-jwt/blob/main/README.md Configure the JWT middleware to allow both authenticated and anonymous access to different endpoints. ```APIDOC ## Mixed Authentication (Public + Protected Endpoints) ### Description Enables a flexible authentication strategy where some API routes can be accessed without a token, while others require a valid JWT. ### Method ```typescript const jwtMiddleware = createJWTMiddleware({ passNoToken: true // Allows requests without a token }) app.get('/posts').use(() => { ... }) ``` ### Configuration - **`passNoToken`** (`boolean`) - If set to `true`, requests without a token will not be rejected by the middleware, allowing for anonymous access to the route. ``` -------------------------------- ### Extract Bearer Token from Authorization Header Source: https://context7.com/aisonsu/farrow-auth-jwt/llms.txt Demonstrates how to use the `extractBearerToken` function from `farrow-auth-jwt` to parse JWT tokens from an Authorization header. It handles valid Bearer tokens and returns `null` for invalid formats or undefined inputs. This function is useful for custom logic to retrieve tokens from various request sources. ```typescript import { extractBearerToken } from 'farrow-auth-jwt' // Extract token from Authorization header const authHeader = 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' const token = extractBearerToken(authHeader) console.log(token) // 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' // Returns null for invalid formats const invalid1 = extractBearerToken('Basic dXNlcjpwYXNz') console.log(invalid1) // null const invalid2 = extractBearerToken(undefined) console.log(invalid2) // null // Usage in custom logic const customGetToken = (request: RequestInfo) => { const authHeader = request.headers?.authorization const headerToken = extractBearerToken(authHeader) // Fallback to other sources return headerToken || request.cookies?.jwt_token || request.query?.access_token || null } ```