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:
3. With Authorization (Recommended)
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:indexpermissionAdmin 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
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:
Authenticator Class: Complete implementation with security best practices
Spec File: Comprehensive test suite with example test cases
Configuration Example: Ready-to-use configuration for your initializer
Usage Instructions: Step-by-step setup guide with next steps
Example: JWT Authenticator Generation
Creates:
app/tasker/authenticators/company_jwt_authenticator.rb- Full JWT implementationspec/tasker/authenticators/company_jwt_authenticator_spec.rb- Test suiteConfiguration 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
Request arrives at Tasker controller (REST or GraphQL)
Authentication runs first (if enabled)
Authorization extracts
resource:actionfrom route/operationCoordinator checks if current user has permission
Access granted (200 OK) or denied (403 Forbidden)
Available Resources and Actions
Tasks (tasker.task)
tasker.task)index- List all tasksshow- View specific taskcreate- Create new taskupdate- Modify existing taskdestroy- Delete taskretry- Retry failed taskcancel- Cancel running task
Workflow Steps (tasker.workflow_step)
tasker.workflow_step)index- List workflow stepsshow- View specific stepupdate- Modify stepdestroy- Delete stepretry- Retry failed stepcancel- 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)
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::AuthenticationErrorif authentication failsShould return truthy value on success
Called automatically by the
Authenticatableconcern
current_user(controller)
current_user(controller)Purpose: Return the currently authenticated user object.
Parameters:
controller: The Rails controller instance
Returns:
User object if authenticated
nilif not authenticated
Notes:
Should be memoized for performance
User object can be any class that represents your authenticated user
Optional Methods
authenticated?(controller)
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 = {})
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 statusauthenticate_tasker_user!: Manually trigger authentication (called automatically)
Authorization Methods:
authorization_coordinator: Returns the current authorization coordinatorauthorize_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
Use Strong Secrets: Minimum 32 characters for JWT secrets
Choose Secure Algorithms: Prefer HS256/HS512 for HMAC, RS256+ for RSA
Validate Configuration: Implement
validate_configurationfor security checksHandle Errors Gracefully: Never expose sensitive information in error messages
Implement Token Expiration: Always set reasonable expiration times
Authorization Security
Default Deny: Always default to denying access unless explicitly granted
Resource-Specific Logic: Implement granular permissions per resource type
Context-Aware Authorization: Use context for ownership and relationship checks
Admin Override Pattern: Allow admins to bypass specific restrictions safely
Audit Trails: Log authorization decisions for security monitoring
Performance
Authentication Performance
Memoize User Lookups: Cache user objects within request scope
Efficient Database Queries: Use
find_byinstead of exceptions for user lookupMinimal Token Validation: Only decode/validate tokens once per request
Authorization Performance
Cache Permission Checks: Memoize authorization decisions within request scope
Efficient Permission Storage: Use optimized data structures for permission lookups
Minimal Database Hits: Load user permissions once per request
Smart GraphQL Batching: Group permission checks for related operations
Development
General Development
Use Different Configs for Environments: Separate dev/test/production settings
Provide Clear Error Messages: Help developers debug configuration issues
Document Your Authenticator: Include usage examples and configuration options
Test Edge Cases: Expired tokens, malformed headers, missing users
Authorization Development
Resource Constants: Always use
ResourceConstantsinstead of hardcoded stringsComprehensive Testing: Test both positive and negative authorization scenarios
Clear Coordinator Logic: Separate resource authorization into dedicated methods
Context Documentation: Document what context information your coordinator uses
Code Organization
Production Considerations
Monitoring & Observability
Log Authorization Failures: Track unauthorized access attempts
Monitor Performance: Track authorization overhead
Alert on Anomalies: Detect unusual permission patterns
Audit Admin Actions: Log all administrative overrides
Scaling Authorization
Permission Caching: Cache user permissions with appropriate TTL
Database Optimization: Index permission lookup columns
Background Processing: Refresh permissions asynchronously when possible
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