or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdcaching.mdextensions.mdindex.mdplugin-system.mdrequest-processing.mdresponse-management.mdrouting.mdserver-management.mdvalidation.md
tile.json

authentication.mddocs/

Authentication

Pluggable authentication system supporting multiple schemes and strategies with built-in session management in @hapi/hapi.

Capabilities

Authentication API

The authentication interface provides methods to register schemes, strategies, and manage authentication.

interface AuthAPI {
    /** Register authentication scheme */
    scheme(name: string, scheme: AuthScheme): void;
    /** Register authentication strategy */
    strategy(name: string, scheme: string, options?: object): void;
    /** Set default authentication */
    default(options: AuthOptions): void;
    /** Test authentication strategy */
    test(name: string, request: Request): Promise<AuthTestResult>;
    /** Verify request authentication */
    verify(request: Request): Promise<AuthVerifyResult>;
    /** Lookup authentication strategy */
    lookup(name: string): AuthStrategy | null;
}

interface AuthScheme {
    /** Authentication function */
    authenticate(request: Request, h: ResponseToolkit): AuthResult;
    /** Optional payload authentication */
    payload?(request: Request, h: ResponseToolkit): AuthResult;
    /** Optional response decoration */
    response?(request: Request, h: ResponseToolkit): void;
    /** Optional verification function */
    verify?(auth: AuthCredentials): boolean;
    /** Optional strategy options */
    options?: object;
}

type AuthResult = AuthSuccess | AuthError | symbol;

interface AuthSuccess {
    /** Authentication credentials */
    credentials: AuthCredentials;
    /** Authentication artifacts */
    artifacts?: object;
}

interface AuthError {
    /** Error object */
    error: Error;
    /** Authentication credentials if partial success */
    credentials?: AuthCredentials;
    /** Authentication artifacts */
    artifacts?: object;
}

Authentication Schemes

Register authentication schemes that define how authentication works.

/**
 * Register an authentication scheme
 * @param name - Scheme name
 * @param scheme - Scheme implementation
 */
scheme(name: string, scheme: AuthScheme): void;

Usage Examples:

// Basic token authentication scheme
server.auth.scheme('token', (server, options) => {
    return {
        authenticate: (request, h) => {
            const token = request.headers.authorization;
            
            if (!token) {
                return h.unauthenticated(new Error('Missing token'));
            }
            
            // Validate token
            const user = validateToken(token.replace('Bearer ', ''));
            if (!user) {
                return h.unauthenticated(new Error('Invalid token'));
            }
            
            return h.authenticated({
                credentials: { user: user.id, scope: user.permissions },
                artifacts: { token }
            });
        }
    };
});

// Cookie session authentication scheme
server.auth.scheme('session', (server, options) => {
    return {
        authenticate: (request, h) => {
            const session = request.state.session;
            
            if (!session) {
                return h.unauthenticated(new Error('No session'));
            }
            
            // Validate session
            if (session.expires < Date.now()) {
                return h.unauthenticated(new Error('Session expired'));
            }
            
            return h.authenticated({
                credentials: {
                    user: session.userId,
                    scope: session.scope
                },
                artifacts: { sessionId: session.id }
            });
        }
    };
});

Authentication Strategies

Register authentication strategies that use schemes with specific configuration.

/**
 * Register an authentication strategy
 * @param name - Strategy name
 * @param scheme - Scheme name to use
 * @param options - Strategy-specific options
 */
strategy(name: string, scheme: string, options?: object): void;

Usage Examples:

// Register strategies using the schemes
server.auth.strategy('jwt-token', 'token', {
    validate: async (credentials) => {
        const user = await db.users.findById(credentials.user);
        return { isValid: !!user, credentials: { ...credentials, profile: user } };
    }
});

server.auth.strategy('user-session', 'session', {
    cookie: 'sid',
    ttl: 24 * 60 * 60 * 1000, // 1 day
    validateFunc: async (session) => {
        const user = await db.sessions.validate(session.id);
        return { valid: !!user, credentials: user };
    }
});

Default Authentication

Set default authentication requirements for all routes.

/**
 * Set default authentication for all routes
 * @param options - Default authentication options
 */
default(options: AuthOptions): void;

interface AuthOptions {
    /** Strategy name to use */
    strategy?: string;
    /** Authentication mode */
    mode?: 'required' | 'optional' | 'try';
    /** Required scope */
    scope?: string | string[];
    /** Required entity type */
    entity?: 'user' | 'app' | 'any';
    /** Access function for additional validation */
    access?: (request: Request) => boolean;
}

Usage Examples:

// Set default authentication for all routes
server.auth.default({
    strategy: 'jwt-token',
    mode: 'required'
});

// Routes can override default
server.route({
    method: 'GET',
    path: '/public',
    options: {
        auth: false // Disable authentication for this route
    },
    handler: () => ({ message: 'Public endpoint' })
});

server.route({
    method: 'GET',
    path: '/admin',
    options: {
        auth: {
            strategy: 'jwt-token',
            scope: ['admin']
        }
    },
    handler: () => ({ message: 'Admin endpoint' })
});

Authentication Testing

Test authentication strategies programmatically.

/**
 * Test authentication strategy
 * @param name - Strategy name
 * @param request - Request object
 * @returns Authentication test result
 */
test(name: string, request: Request): Promise<AuthTestResult>;

interface AuthTestResult {
    /** Whether authentication succeeded */
    isValid: boolean;
    /** Authentication credentials if valid */
    credentials?: AuthCredentials;
    /** Authentication artifacts */
    artifacts?: object;
    /** Error if authentication failed */
    error?: Error;
}

Usage Examples:

server.route({
    method: 'POST',
    path: '/test-auth',
    handler: async (request, h) => {
        const result = await server.auth.test('jwt-token', request);
        
        return {
            valid: result.isValid,
            user: result.credentials?.user,
            error: result.error?.message
        };
    }
});

Authentication Verification

Verify request authentication credentials programmatically.

/**
 * Verify request authentication
 * @param request - Request object
 * @returns Authentication verification result
 */
verify(request: Request): Promise<AuthVerifyResult>;

interface AuthVerifyResult {
    /** Whether authentication is valid */
    isValid: boolean;
    /** Authentication credentials if valid */
    credentials?: AuthCredentials;
    /** Authentication artifacts */
    artifacts?: object;
    /** Authentication error if invalid */
    error?: Error;
    /** Strategy name used */
    strategy?: string;
}

Usage Examples:

server.ext('onPreHandler', async (request, h) => {
    if (request.path.startsWith('/api/')) {
        const result = await server.auth.verify(request);
        
        if (!result.isValid) {
            return h.response({ error: 'Authentication required' }).code(401);
        }
        
        // Authentication is valid, continue
        return h.continue;
    }
    
    return h.continue;
});

// In a route handler
server.route({
    method: 'POST',
    path: '/secure-action',
    handler: async (request, h) => {
        const verification = await server.auth.verify(request);
        
        if (verification.isValid && verification.credentials.scope.includes('admin')) {
            return { message: 'Admin action completed' };
        }
        
        return h.response({ error: 'Insufficient permissions' }).code(403);
    }
});

Route Authentication Configuration

Configure authentication at the route level.

interface RouteAuthOptions {
    /** Authentication strategy name */
    strategy?: string;
    /** Authentication strategies (multiple) */
    strategies?: string[];
    /** Authentication mode */
    mode?: 'required' | 'optional' | 'try';
    /** Payload authentication */
    payload?: boolean | string;
    /** Required scope */
    scope?: string | string[];
    /** Required entity type */
    entity?: 'user' | 'app' | 'any';
    /** Access requirements */
    access?: AccessOptions | AccessOptions[];
}

interface AccessOptions {
    /** Required scope */
    scope?: string | string[];
    /** Required entity */
    entity?: 'user' | 'app' | 'any';
    /** Custom access function */
    validate?: (request: Request) => boolean;
}

Usage Examples:

// Required authentication
server.route({
    method: 'GET',
    path: '/protected',
    options: {
        auth: {
            strategy: 'jwt-token',
            mode: 'required'
        }
    },
    handler: (request, h) => {
        return {
            message: `Hello ${request.auth.credentials.user}`,
            scope: request.auth.credentials.scope
        };
    }
});

// Optional authentication
server.route({
    method: 'GET',
    path: '/optional-auth',
    options: {
        auth: {
            strategy: 'jwt-token',
            mode: 'optional'
        }
    },
    handler: (request, h) => {
        if (request.auth.isAuthenticated) {
            return { message: `Hello ${request.auth.credentials.user}` };
        }
        return { message: 'Hello anonymous user' };
    }
});

// Multiple strategies
server.route({
    method: 'GET',
    path: '/multi-auth',
    options: {
        auth: {
            strategies: ['jwt-token', 'user-session'],
            mode: 'required'
        }
    },
    handler: (request, h) => {
        return {
            strategy: request.auth.strategy,
            user: request.auth.credentials.user
        };
    }
});

// Scope-based access control
server.route({
    method: 'DELETE',
    path: '/admin/users/{id}',
    options: {
        auth: {
            strategy: 'jwt-token',
            scope: ['admin', 'user:delete']
        }
    },
    handler: (request, h) => {
        return { message: 'User deleted' };
    }
});

Authentication Helpers in Response Toolkit

Helper methods available in the response toolkit for authentication.

/**
 * Set authentication success
 * @param data - Authentication data
 * @returns Authentication result
 */
authenticated(data: AuthCredentials): object;

/**
 * Set authentication failure
 * @param error - Authentication error
 * @param data - Optional partial credentials
 * @returns Authentication result
 */
unauthenticated(error: Error, data?: AuthCredentials): object;

Usage Examples:

// Used within authentication schemes
const customScheme = (server, options) => {
    return {
        authenticate: async (request, h) => {
            try {
                const token = extractToken(request);
                const user = await validateToken(token);
                
                return h.authenticated({
                    credentials: {
                        user: user.id,
                        scope: user.permissions,
                        profile: user
                    },
                    artifacts: { token, validatedAt: Date.now() }
                });
            } catch (error) {
                return h.unauthenticated(error);
            }
        }
    };
};

Types

interface AuthCredentials {
    /** User identifier */
    user?: string;
    /** User scope/permissions */
    scope?: string[];
    /** Authentication strategy used */
    strategy?: string;
    /** Additional credential data */
    [key: string]: any;
}

interface AuthStrategy {
    /** Strategy name */
    name: string;
    /** Scheme name */
    scheme: string;
    /** Strategy options */
    options: object;
    /** Strategy test method */
    test: (request: Request) => Promise<AuthTestResult>;
}

interface AuthVerifyResult {
    /** Whether verification succeeded */
    isValid: boolean;
    /** Updated credentials */
    credentials?: AuthCredentials;
    /** Error if verification failed */
    error?: Error;
}