Authentication & Authorization

Overview

Tasker provides a comprehensive, flexible authentication and authorization system that works with any Rails authentication solution. The system uses dependency injection and resource-based authorization to allow host applications to provide their own authentication logic while maintaining enterprise-grade security for both REST APIs and GraphQL endpoints.

System Status

Phase 5 Controller Integration - Complete

The authentication and authorization system includes comprehensive controller integration:

  • GraphQL Operation-Level Authorization: Automatically maps GraphQL operations to resource:action permissions

  • Automatic Controller Authorization: All REST and GraphQL endpoints protected seamlessly

  • Resource Registry: Centralized constants eliminate hardcoded strings throughout codebase

  • Complete Test Coverage: 674/674 tests passing with comprehensive integration testing

  • Zero Breaking Changes: All features are opt-in and backward compatible

  • State Isolation: Robust test infrastructure prevents configuration leakage

The authentication and authorization system is production-ready with enterprise-grade security for both REST APIs and GraphQL endpoints.

Key Benefits

  • Provider Agnostic: Works with Devise, JWT, OmniAuth, custom authentication, or no authentication

  • Dependency Injection: Host applications implement authenticators rather than building provider-specific code into Tasker

  • Resource-Based Authorization: Granular permissions using resource:action patterns (e.g., tasker.task:create)

  • GraphQL Operation-Level Authorization: Advanced security for GraphQL that maps operations to resource permissions

  • Automatic Controller Integration: Authentication and authorization work seamlessly across REST and GraphQL

  • Interface Validation: Ensures authenticators implement required methods with helpful error messages

  • Configuration Validation: Built-in validation with security best practices

  • Flexible Configuration: Support for multiple strategies and environment-specific settings

  • Zero Breaking Changes: All features are opt-in and backward compatible

Table of Contents

Quick Start

1. No Authentication (Default)

By default, Tasker requires no authentication:

2. Custom Authentication

For any authentication system, enable authentication and specify your authenticator class:

Enable both authentication and authorization for complete security:

Authorization Quick Start

Authorization in Tasker uses a resource:action permission model that works seamlessly with both REST APIs and GraphQL.

1. Enable Authorization

2. Create Authorization Coordinator

3. Add Authorization to User Model

4. Automatic Protection

With authorization enabled, all Tasker endpoints are automatically protected:

Health Status Authorization

Tasker provides optional authorization for health monitoring endpoints, designed for production security while maintaining Kubernetes compatibility:

Health Endpoint Security Model

Configuration

Enable health status authorization:

Authorization Implementation

Add health status authorization to your coordinator:

Security Benefits

  • K8s Compatibility: Ready/live endpoints never require authorization

  • Granular Control: Status endpoint uses specific health_status:index permission

  • Admin Override: Admin users always have health status access

  • Optional Authentication: Can require authentication without authorization

  • Production Ready: Designed for enterprise security requirements

For complete health monitoring documentation, see Health Monitoring Guide.

GraphQL Authorization

Tasker provides revolutionary GraphQL authorization that automatically maps GraphQL operations to resource:action permissions.

How It Works

The system parses GraphQL queries and mutations to extract the underlying operations, then checks permissions for each operation:

GraphQL Operation Mapping

GraphQL Operation
Resource:Action Permission

query { tasks }

tasker.task:index

query { task(taskId: "123") }

tasker.task:show

mutation { createTask(...) }

tasker.task:create

mutation { updateTask(...) }

tasker.task:update

mutation { cancelTask(...) }

tasker.task:cancel

query { step(...) }

tasker.workflow_step:show

mutation { updateStep(...) }

tasker.workflow_step:update

mutation { cancelStep(...) }

tasker.workflow_step:cancel

GraphQL Authorization Examples

GraphQL with Context

GraphQL authorization includes context information for advanced logic:

Authenticator Generator

Tasker provides a Rails generator to quickly create authenticator templates for common authentication systems:

Basic Usage

Generator Options

  • --type: Authenticator type (jwt, devise, api_token, omniauth, custom)

  • --user-class: User model class name (default: User)

  • --directory: Output directory (default: app/tasker/authenticators)

  • --with-spec/--no-with-spec: Generate spec file (default: true)

What the Generator Creates

The generator creates:

  1. Authenticator Class: Complete implementation with security best practices

  2. Spec File: Comprehensive test suite with example test cases

  3. Configuration Example: Ready-to-use configuration for your initializer

  4. Usage Instructions: Step-by-step setup guide with next steps

Example: JWT Authenticator Generation

Creates:

  • app/tasker/authenticators/company_jwt_authenticator.rb - Full JWT implementation

  • spec/tasker/authenticators/company_jwt_authenticator_spec.rb - Test suite

  • Configuration example and setup instructions

Generated features:

  • JWT signature verification with configurable algorithms

  • Bearer token and raw token support

  • Comprehensive validation with security checks

  • Test token generation helper for testing

  • Memoized user lookup for performance

Configuration Options

Authentication Configuration Block

Configuration Validation

Tasker validates configuration at startup and provides helpful error messages:

Authentication Configuration

No Authentication (Default)

By default, authentication is disabled. All users are considered "authenticated" with no user object.

Use Cases:

  • Development environments

  • Internal tools without user management

  • Public APIs

  • Testing scenarios

Custom Authentication

Host application provides a custom authenticator class that implements the authentication interface.

Use Cases:

  • Devise integration

  • JWT authentication

  • OmniAuth integration

  • Custom authentication systems

  • Multi-tenant authentication

Authorization System

Tasker's authorization system provides enterprise-grade security through a resource-based permission model. The system uses resource constants and authorization coordinators to ensure consistent, maintainable authorization logic.

Resource Registry

All authorization revolves around the central resource registry:

Authorization Coordinator Interface

Authorization coordinators must implement the BaseCoordinator interface:

Controller Integration

Authorization is automatically applied to all Tasker controllers:

Permission Checking Flow

  1. Request arrives at Tasker controller (REST or GraphQL)

  2. Authentication runs first (if enabled)

  3. Authorization extracts resource:action from route/operation

  4. Coordinator checks if current user has permission

  5. Access granted (200 OK) or denied (403 Forbidden)

Available Resources and Actions

Tasks (tasker.task)

  • index - List all tasks

  • show - View specific task

  • create - Create new task

  • update - Modify existing task

  • destroy - Delete task

  • retry - Retry failed task

  • cancel - Cancel running task

Workflow Steps (tasker.workflow_step)

  • index - List workflow steps

  • show - View specific step

  • update - Modify step

  • destroy - Delete step

  • retry - Retry failed step

  • cancel - Cancel running step

Building Authorization Coordinators

Authorization coordinators provide the business logic for permission checking. Here's how to build effective coordinators:

Basic Coordinator Structure

Advanced Authorization Patterns

Role-Based Authorization

Context-Based Authorization

Time-Based Authorization

Building Custom Authenticators

Authentication Interface

All custom authenticators must implement the Tasker::Authentication::Interface:

Required Methods

authenticate!(controller)

Purpose: Authenticate the current request and raise an exception if authentication fails.

Parameters:

  • controller: The Rails controller instance

Behavior:

  • Must raise Tasker::Authentication::AuthenticationError if authentication fails

  • Should return truthy value on success

  • Called automatically by the Authenticatable concern

current_user(controller)

Purpose: Return the currently authenticated user object.

Parameters:

  • controller: The Rails controller instance

Returns:

  • User object if authenticated

  • nil if not authenticated

Notes:

  • Should be memoized for performance

  • User object can be any class that represents your authenticated user

Optional Methods

authenticated?(controller)

Purpose: Check if the current request is authenticated.

Default Implementation: Returns current_user(controller).present?

Override: When you need custom authentication logic beyond user presence.

validate_configuration(options = {})

Purpose: Validate authenticator-specific configuration options.

Parameters:

  • options: Hash of configuration options

Returns: Array of error message strings (empty array if valid)

Best Practices:

  • Check for required configuration options

  • Validate external dependencies (gems, classes)

  • Verify security settings (key lengths, algorithm choices)

JWT Authentication Example

Our ExampleJWTAuthenticator demonstrates a production-ready JWT implementation:

Basic Configuration

Environment-Specific Configuration

Implementation Highlights

The ExampleJWTAuthenticator includes:

Security Features

  • Signature Verification: Validates JWT signatures to prevent tampering

  • Expiration Checking: Automatically rejects expired tokens

  • Algorithm Validation: Ensures only approved algorithms are used

  • Secret Length Validation: Enforces minimum security standards

  • Error Handling: Graceful handling of malformed or invalid tokens

Integration with Controllers

Automatic Integration

Controllers inherit both authentication and authorization automatically:

Automatic Authorization

All Tasker controllers automatically enforce authorization when enabled:

Available Helper Methods

In any Tasker controller, you have access to:

Controller Methods

Authentication Methods:

  • current_tasker_user: Returns the current user object (or nil)

  • tasker_user_authenticated?: Returns boolean authentication status

  • authenticate_tasker_user!: Manually trigger authentication (called automatically)

Authorization Methods:

  • authorization_coordinator: Returns the current authorization coordinator

  • authorize_tasker_action!: Manually trigger authorization (called automatically)

  • skip_authorization?: Check if authorization should be skipped

REST API Authorization

REST endpoints map directly to resource:action permissions:

GraphQL Integration

GraphQL endpoints inherit both authentication and authorization with operation-level granular security:

GraphQL Resolver Authorization

In GraphQL resolvers, you have access to authorization context:

Manual Authorization

You can also perform manual authorization checks:

Error Handling

Authentication Errors

The system provides standardized error handling:

Error Types

Custom Error Messages

Authenticators can provide meaningful error messages:

Testing Authentication

Test Authenticator

For testing, use the provided TestAuthenticator:

JWT Testing

For JWT authenticator testing:

Testing Authorization

Authorization Test Setup

For authorization testing, use comprehensive integration tests:

GraphQL Authorization Testing

Custom Authorization Coordinator Testing

State Isolation

Ensure tests don't leak configuration state:

Best Practices

Security

Authentication Security

  1. Use Strong Secrets: Minimum 32 characters for JWT secrets

  2. Choose Secure Algorithms: Prefer HS256/HS512 for HMAC, RS256+ for RSA

  3. Validate Configuration: Implement validate_configuration for security checks

  4. Handle Errors Gracefully: Never expose sensitive information in error messages

  5. Implement Token Expiration: Always set reasonable expiration times

Authorization Security

  1. Default Deny: Always default to denying access unless explicitly granted

  2. Resource-Specific Logic: Implement granular permissions per resource type

  3. Context-Aware Authorization: Use context for ownership and relationship checks

  4. Admin Override Pattern: Allow admins to bypass specific restrictions safely

  5. Audit Trails: Log authorization decisions for security monitoring

Performance

Authentication Performance

  1. Memoize User Lookups: Cache user objects within request scope

  2. Efficient Database Queries: Use find_by instead of exceptions for user lookup

  3. Minimal Token Validation: Only decode/validate tokens once per request

Authorization Performance

  1. Cache Permission Checks: Memoize authorization decisions within request scope

  2. Efficient Permission Storage: Use optimized data structures for permission lookups

  3. Minimal Database Hits: Load user permissions once per request

  4. Smart GraphQL Batching: Group permission checks for related operations

Development

General Development

  1. Use Different Configs for Environments: Separate dev/test/production settings

  2. Provide Clear Error Messages: Help developers debug configuration issues

  3. Document Your Authenticator: Include usage examples and configuration options

  4. Test Edge Cases: Expired tokens, malformed headers, missing users

Authorization Development

  1. Resource Constants: Always use ResourceConstants instead of hardcoded strings

  2. Comprehensive Testing: Test both positive and negative authorization scenarios

  3. Clear Coordinator Logic: Separate resource authorization into dedicated methods

  4. Context Documentation: Document what context information your coordinator uses

Code Organization

Production Considerations

Monitoring & Observability

  1. Log Authorization Failures: Track unauthorized access attempts

  2. Monitor Performance: Track authorization overhead

  3. Alert on Anomalies: Detect unusual permission patterns

  4. Audit Admin Actions: Log all administrative overrides

Scaling Authorization

  1. Permission Caching: Cache user permissions with appropriate TTL

  2. Database Optimization: Index permission lookup columns

  3. Background Processing: Refresh permissions asynchronously when possible

  4. Circuit Breakers: Graceful degradation when authorization services are unavailable

Example Authenticator Template

Common Integration Patterns

Devise Integration

API Token Authentication

This authentication system provides the flexibility to integrate with any authentication solution while maintaining security, performance, and developer experience. The dependency injection pattern ensures that Tasker remains authentication-agnostic while providing a robust foundation for secure applications.

Last updated