Library Integration Enforcement
Native application integration with framework adapters, SDKs, and middleware for fine-grained authorization control
Library Integration Enforcement
Library Integration provides the most natural and flexible way to add FGA authorization to modern applications. By integrating directly with your application frameworks and runtime environments, you get fine-grained control with minimal code changes.
Integration Approaches
ποΈ Framework Adapters
Native integration with popular frameworks:
Spring Security (Java)
// Minimal Spring Security configuration
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AuthonomySecurityConfig {
@Bean
public AuthonomyAuthorizationManager authorizationManager() {
return AuthonomyAuthorizationManager.builder()
.policySet("production_v1")
.cacheEnabled(true)
.build();
}
}
// Use in controllers with annotations
@RestController
public class CustomerController {
@GetMapping("/customers/{id}")
@PreAuthorize("@authonomy.check('can_view', 'customer', #id)")
public Customer getCustomer(@PathVariable String id) {
return customerService.findById(id);
}
}
Express.js (Node.js)
// Express middleware integration
const authonomy = require('@authonomy/express-middleware');
app.use(authonomy.middleware({
policySet: 'production_v1',
userExtractor: (req) => req.user,
resourceExtractor: (req) => ({
type: 'api_endpoint',
id: req.route.path
})
}));
// Route-specific authorization
app.get('/api/customers/:id',
authonomy.authorize('can_view', 'customer'),
(req, res) => {
// Your business logic here
res.json(customerService.findById(req.params.id));
});
Django (Python)
# Django decorator integration
from authonomy.django import require_permission
class CustomerViewSet(ViewSet):
@require_permission('can_view', resource_type='customer')
def retrieve(self, request, pk=None):
customer = Customer.objects.get(pk=pk)
return Response(CustomerSerializer(customer).data)
@require_permission('can_edit', resource_type='customer')
def update(self, request, pk=None):
# Update logic here
pass
ποΈ Middleware Integration
Add authorization to existing middleware chains:
// Express.js middleware example
function authonomyMiddleware(options = {}) {
const client = new AuthonomyClient(options);
return async (req, res, next) => {
try {
const user = extractUser(req);
const resource = extractResource(req);
const action = extractAction(req);
const decision = await client.check({
user: user,
action: action,
resource: resource,
context: extractContext(req)
});
if (decision.allowed) {
req.authonomy = { decision, context: decision.context };
next();
} else {
res.status(403).json({
error: 'Access denied',
reason: decision.reason
});
}
} catch (error) {
// Fail securely - deny access on authorization errors
res.status(500).json({ error: 'Authorization service unavailable' });
}
};
}
π SDK Integration
Direct SDK calls for custom scenarios:
// TypeScript SDK example
import { AuthonomyClient } from '@authonomy/typescript-sdk';
class OrderService {
private authonomy = new AuthonomyClient({
apiKey: process.env.AUTHONOMY_API_KEY,
policySet: 'order_management_v2'
});
async createOrder(user: User, orderData: OrderData): Promise<Order> {
// Check if user can create orders for this customer
const canCreate = await this.authonomy.check({
user: user.id,
action: 'create',
resource: {
type: 'order',
customer_id: orderData.customer_id
}
});
if (!canCreate.allowed) {
throw new ForbiddenError(canCreate.reason);
}
// Business logic continues...
return this.orderRepository.create(orderData);
}
}
Language & Framework Support
β Java Ecosystem
- Spring Boot: Auto-configuration and annotations
- Jersey: JAX-RS filter integration
- Micronaut: Native reactive support
- Quarkus: GraalVM native image support
// Spring Boot auto-configuration
@SpringBootApplication
@EnableAuthonomy
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
π JavaScript/TypeScript
- Express.js: Middleware and route protection
- Fastify: Plugin-based integration
- NestJS: Decorator and guard integration
- Next.js: API route and page protection
// NestJS guard example
@Injectable()
export class AuthonomyGuard implements CanActivate {
constructor(private authonomy: AuthonomyService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const { user, resource, action } = this.extractAuthContext(request);
const decision = await this.authonomy.check({ user, action, resource });
return decision.allowed;
}
}
π Python Ecosystem
- Django: Decorator and middleware integration
- FastAPI: Dependency injection integration
- Flask: Decorator and blueprint integration
- SQLAlchemy: ORM-level authorization
# FastAPI dependency injection
from authonomy.fastapi import AuthonomyChecker
app = FastAPI()
authorize = AuthonomyChecker(policy_set="api_v1")
@app.get("/customers/{customer_id}")
async def get_customer(
customer_id: str,
user: User = Depends(get_current_user),
_auth: None = Depends(authorize.require("can_view", "customer"))
):
return await customer_service.get(customer_id)
βοΈ C# .NET
- ASP.NET Core: Authorization policy integration
- Entity Framework: Query-level authorization
- SignalR: Real-time authorization
- Blazor: Component-level authorization
// ASP.NET Core authorization policy
services.AddAuthorization(options =>
{
options.AddPolicy("CanViewCustomer", policy =>
policy.AddRequirements(new AuthonomyRequirement("can_view", "customer")));
});
// Controller usage
[Authorize(Policy = "CanViewCustomer")]
public IActionResult GetCustomer(int id)
{
var customer = customerService.GetById(id);
return Ok(customer);
}
Runtime Injection Patterns
π― Aspect-Oriented Programming (AOP)
Inject authorization without changing business logic:
// Java AOP example
@Aspect
@Component
public class AuthonomyAuthorizationAspect {
@Around("@annotation(authorize)")
public Object checkAuthorization(ProceedingJoinPoint joinPoint,
Authorize authorize) throws Throwable {
Object[] args = joinPoint.getArgs();
String user = SecurityContext.getCurrentUser();
String resource = extractResource(args);
if (!authonomyClient.check(user, authorize.action(), resource)) {
throw new AccessDeniedException("Insufficient permissions");
}
return joinPoint.proceed();
}
}
π Runtime Bytecode Modification
Inject authorization checks at runtime:
// C# runtime interception with Castle DynamicProxy
public class AuthonomyInterceptor : IInterceptor
{
private readonly IAuthonomyClient authonomy;
public void Intercept(IInvocation invocation)
{
var authorizeAttr = invocation.Method.GetCustomAttribute<AuthorizeAttribute>();
if (authorizeAttr != null)
{
var user = GetCurrentUser();
var resource = ExtractResource(invocation.Arguments);
var allowed = authonomy.Check(user, authorizeAttr.Action, resource);
if (!allowed)
{
throw new UnauthorizedAccessException();
}
}
invocation.Proceed();
}
}
Performance Optimization
β‘ Authorization Caching
Intelligent caching for repeated authorization checks:
// Client-side caching configuration
const authonomy = new AuthonomyClient({
cache: {
type: 'memory',
ttl: 300, // 5 minutes
maxSize: 10000,
// Cache key strategy
keyGenerator: (user, action, resource) =>
`${user.id}:${action}:${resource.type}:${resource.id}`,
// Cache invalidation
invalidateOn: ['user_role_change', 'policy_update']
}
});
π Batch Authorization
Optimize bulk operations:
# Batch authorization for list operations
async def get_customer_list(user: User) -> List[Customer]:
customers = await customer_repository.get_all()
# Batch authorize all customers at once
authorizations = await authonomy.batch_check([
CheckRequest(user=user.id, action="view", resource=f"customer:{c.id}")
for c in customers
])
# Filter based on authorization results
allowed_customers = [
customer for customer, auth in zip(customers, authorizations)
if auth.allowed
]
return allowed_customers
π Performance Monitoring
Track authorization performance in production:
# Performance metrics configuration
monitoring:
metrics:
- name: "authorization_latency"
type: "histogram"
labels: ["user_type", "resource_type", "action"]
- name: "authorization_decisions"
type: "counter"
labels: ["decision", "policy_name"]
- name: "cache_hit_rate"
type: "gauge"
alerting:
- metric: "authorization_latency_p95"
threshold: "> 100ms"
- metric: "cache_hit_rate"
threshold: "< 80%"
Error Handling & Resilience
π‘οΈ Graceful Degradation
Handle authorization service outages gracefully:
// Resilience configuration
const authonomy = new AuthonomyClient({
resilience: {
// Fallback behavior when FGA service is unavailable
fallback: 'deny', // or 'allow', 'cache_only'
// Circuit breaker configuration
circuitBreaker: {
failureThreshold: 5,
recoveryTimeout: 30000,
monitoringPeriod: 10000
},
// Retry configuration
retry: {
maxAttempts: 3,
backoffStrategy: 'exponential',
maxDelay: 5000
}
}
});
π¨ Error Scenarios
Handle common failure modes:
# Comprehensive error handling
try:
decision = await authonomy.check(user, action, resource)
if not decision.allowed:
raise PermissionDenied(decision.reason)
except AuthonomyServiceUnavailable:
# FGA service is down - use fallback
if fallback_mode == 'allow':
logger.warning("FGA unavailable, allowing access")
return True
else:
logger.error("FGA unavailable, denying access")
raise ServiceUnavailable("Authorization service down")
except AuthonomyTimeoutError:
# Request timed out - fail securely
logger.error("Authorization timeout")
raise PermissionDenied("Authorization check timed out")
except AuthonomyPolicyError as e:
# Policy evaluation failed
logger.error(f"Policy error: {e}")
raise InternalServerError("Authorization policy error")
Migration Patterns
π Gradual Integration
Migrate existing authorization code incrementally:
// Phase 1: Add FGA alongside existing authorization
@GetMapping("/customer/{id}")
public Customer getCustomer(@PathVariable String id) {
// Existing authorization (keep temporarily)
if (!legacyAuth.hasRole("ADMIN") && !legacyAuth.canViewCustomer(id)) {
throw new AccessDeniedException("Access denied");
}
// New FGA authorization (shadow mode initially)
boolean fgaAllowed = authonomy.check(getCurrentUser(), "view", "customer:" + id);
if (legacyAuth.isAllowed() != fgaAllowed) {
logger.warn("Authorization mismatch for customer {}", id);
}
return customerService.findById(id);
}
π― Feature Flag Migration
Use feature flags to control authorization method:
// Feature flag controlled authorization
async function checkAuthorization(user: User, action: string, resource: Resource): Promise<boolean> {
if (await featureFlags.isEnabled('fga_enforcement')) {
return await authonomy.check(user, action, resource);
} else {
return await legacyAuthService.check(user, resource);
}
}
// Usage in application code
export async function getCustomerData(userId: string, customerId: string) {
const canView = await checkAuthorization(
{ id: userId },
'view',
{ type: 'customer', id: customerId }
);
if (!canView) {
throw new ForbiddenError('Cannot access customer data');
}
return customerRepository.findById(customerId);
}
Advanced Integration Patterns
π¨ Reactive Authorization
Stream real-time authorization decisions:
// Real-time authorization with WebSockets
const authStream = authonomy.createAuthorizationStream();
authStream.subscribe({
user: currentUser.id,
resources: ['order:*', 'customer:*'],
onAuthorization: (event) => {
if (event.type === 'permission_granted') {
enableFeature(event.resource, event.action);
} else if (event.type === 'permission_revoked') {
disableFeature(event.resource, event.action);
}
}
});
π§© Microservices Authorization
Consistent authorization across microservice architectures:
# Shared authorization configuration
microservices:
customer_service:
authonomy:
policy_set: "customer_management_v1"
resources: ["customer", "customer_profile"]
order_service:
authonomy:
policy_set: "order_management_v1"
resources: ["order", "invoice", "shipment"]
billing_service:
authonomy:
policy_set: "billing_management_v1"
resources: ["payment", "subscription"]
# Cross-service authorization
cross_service_policies:
- name: "customer_order_access"
condition: "customer_service.can_view(customer_id) and order_service.can_view(order_id)"
π Authorization Composition
Combine multiple authorization checks:
# Complex authorization logic
class AdvancedAuthorizationService:
async def check_complex_operation(self, user, operation_context):
checks = [
# Base permission check
self.authonomy.check(user, "execute", operation_context.operation_type),
# Resource-specific authorization
self.check_resource_access(user, operation_context.resources),
# Time-based authorization
self.check_time_restrictions(user, operation_context.schedule),
# Delegation verification
self.check_delegation_chain(user, operation_context.delegated_by)
]
results = await asyncio.gather(*checks, return_exceptions=True)
# All checks must pass
return all(result.allowed for result in results if not isinstance(result, Exception))
Testing & Debugging
π Authorization Testing
Test authorization logic with various scenarios:
// JUnit test example
@Test
public void testCustomerAccessAuthorization() {
// Setup test data
User salesRep = createUser("alice", "sales_rep", "west_region");
Customer customer = createCustomer("12345", "west_region");
// Test authorized access
assertTrue(authonomy.check(salesRep, "view", customer));
// Test unauthorized access (different region)
Customer eastCustomer = createCustomer("67890", "east_region");
assertFalse(authonomy.check(salesRep, "view", eastCustomer));
// Test admin override
User admin = createUser("bob", "admin");
assertTrue(authonomy.check(admin, "view", eastCustomer));
}
π Debug Mode
Enable detailed logging for troubleshooting:
// Debug configuration
const authonomy = new AuthonomyClient({
debug: {
enabled: process.env.NODE_ENV === 'development',
logLevel: 'trace',
includeContext: true,
// Log all authorization decisions
onDecision: (decision) => {
console.log('Authorization Decision:', {
user: decision.user,
action: decision.action,
resource: decision.resource,
allowed: decision.allowed,
reason: decision.reason,
evaluationTime: decision.evaluationTime
});
}
}
});
Production Deployment
π Deployment Configuration
# Production deployment configuration
production:
authonomy:
# Service configuration
endpoint: "https://fga.authonomy.io"
api_key: "${AUTHONOMY_API_KEY}"
policy_set: "production_customer_portal_v3"
# Performance settings
timeout: "5s"
cache_size: 50000
cache_ttl: "10m"
# Resilience settings
circuit_breaker:
failure_threshold: 10
recovery_timeout: "60s"
# Monitoring
metrics:
enabled: true
endpoint: "/metrics"
audit:
level: "info"
destination: "syslog"
π Health Checks & Monitoring
// Application health check with authorization status
app.get('/health', async (req, res) => {
const health = {
status: 'healthy',
timestamp: new Date().toISOString(),
services: {}
};
try {
// Check FGA service connectivity
const fgaHealth = await authonomy.healthCheck();
health.services.authorization = {
status: fgaHealth.healthy ? 'up' : 'down',
latency: fgaHealth.latency,
cacheHitRate: fgaHealth.cacheStats.hitRate
};
} catch (error) {
health.status = 'degraded';
health.services.authorization = {
status: 'down',
error: error.message
};
}
res.json(health);
});
Best Practices
β Implementation Guidelines
- Fail securely: Default to deny when authorization service is unavailable
- Cache wisely: Balance performance and consistency for authorization decisions
- Monitor extensively: Track authorization decisions, performance, and errors
- Test thoroughly: Include authorization in your integration and load testing
π Security Considerations
- API key protection: Secure storage and rotation of Authonomy API keys
- Request validation: Validate and sanitize authorization context data
- Audit trail: Log all authorization decisions for security and compliance
- Error handling: Donβt leak sensitive information in authorization errors
π Performance Tips
- Batch operations: Group multiple authorization checks when possible
- Smart caching: Cache based on user context and resource patterns
- Async processing: Use asynchronous authorization checks where possible
- Connection pooling: Reuse connections to the FGA service
Migration Checklist
β Pre-Migration
- Framework adapter or SDK installed and configured
- Policy set defined and tested
- Error handling and fallback behavior implemented
- Monitoring and logging configured
β During Migration
- Feature flags controlling authorization method
- Shadow mode comparison with legacy authorization
- Performance monitoring active
- Gradual rollout to user segments
β Post-Migration
- Legacy authorization code removed
- Full FGA policy enforcement active
- Performance within acceptable ranges
- Audit logging meeting compliance requirements
Next Steps
With library integration complete, consider:
- Synchronization & Consistency for multi-system environments
- Advanced Policy Management for complex business rules
- Migration Methodology for end-to-end migration planning
Need help with library integration? Contact our integration team for framework-specific guidance and implementation support.