Authorization: Access Control

Authorization is the process of determining what an authenticated user is allowed to do. It controls access to resources based on roles, permissions, or policies after identity verification is complete.

Authorization: Access Control

Authorization is the process of determining what an authenticated user is allowed to do. While authentication answers "Who are you?", authorization answers "What can you do?" Once a user's identity is verified, authorization controls their access to resources, actions, and data based on predefined permissions, roles, or policies. Without proper authorization, authenticated users could access or modify data they should not see or change.

Authorization is a critical component of application security. It ensures that users can only perform actions and access data that their role or permission level permits. To understand authorization properly, it is helpful to be familiar with concepts like authentication mechanisms, web security fundamentals, session management, and security compliance.

What Is Authorization

Authorization is the security process that determines whether an authenticated user has permission to access a specific resource or perform a specific action. It happens after authentication and is enforced at every access attempt. Authorization answers questions like: Can this user view this page? Can this user edit this document? Can this user delete this record?

  • Access Control: Determines who can access what resources.
  • Permission-Based: Grants or denies specific actions (read, write, delete, execute).
  • Post-Authentication: Authorization always follows successful authentication.
  • Enforced at Every Request: Each access attempt is checked independently.
  • Principle of Least Privilege: Users should have only the minimum permissions needed.
Authentication vs Authorization flow:
┌─────────────────────────────────────────────────────────────┐
│              Authentication vs Authorization                 │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   User Request                                               │
│        │                                                     │
│        ▼                                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Authentication (Who are you?)           │   │
│   │  • Username/password                                 │   │
│   │  • MFA / Biometric                                   │   │
│   │  • OAuth / SSO                                       │   │
│   └─────────────────────────────────────────────────────┘   │
│        │                                                     │
│        ▼ (Authenticated)                                     │
│   ┌─────────────────────────────────────────────────────┐   │
│   │              Authorization (What can you do?)        │   │
│   │  • Role checking (admin, editor, viewer)            │   │
│   │  • Permission checking (read, write, delete)        │   │
│   │  • Policy evaluation (time, location, resource)     │   │
│   └─────────────────────────────────────────────────────┘   │
│        │                                                     │
│        ▼                                                     │
│   Access Granted or Denied                                   │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Why Authorization Matters

Authorization is essential for protecting sensitive data and ensuring that users can only perform actions appropriate for their role. Without proper authorization, any authenticated user could access any resource.

  • Data Protection: Prevents unauthorized access to sensitive information.
  • Least Privilege: Enforces the principle that users should have minimal necessary permissions.
  • Compliance: Required by regulations like HIPAA, GDPR, and PCI-DSS for access control.
  • Audit Trail: Authorization logs provide accountability for user actions.
  • Segregation of Duties: Prevents users from having conflicting permissions (e.g., create and approve payments).
  • Prevents Privilege Escalation: Stops users from gaining unauthorized access to higher-level functions.
  • Multi-Tenancy: Ensures users can only access data within their organization or account.

Authorization Models

Several authorization models are used in modern applications. Choosing the right model depends on application complexity, scalability needs, and security requirements.

Role-Based Access Control (RBAC)

RBAC is the most common authorization model. Permissions are assigned to roles, and users are assigned to roles. This simplifies management by grouping permissions rather than assigning them individually.

RBAC example:
Roles:
- Admin: Full system access
- Editor: Create, edit, publish content
- Viewer: Read-only access
- Guest: Limited public access

User Assignments:
- User1 -> Admin role
- User2 -> Editor role
- User3 -> Viewer role

Permission Checking:
if ($user->hasRole('admin')) {
    // Allow delete
}

// Database representation
users: id, name
roles: id, name
user_roles: user_id, role_id
permissions: id, name, resource
role_permissions: role_id, permission_id

Access Control Lists (ACL)

ACL directly associates permissions with specific users or groups for specific resources. This provides fine-grained control but can become complex to manage at scale.

ACL example:
Document: report.pdf
- User1: read, write
- User2: read only
- Group: marketing -> read, write
- Group: finance -> read only

// Database representation
acl_entries: id, resource_type, resource_id, user_id, group_id, permission

// Checking access
function canAccess($userId, $resourceId, $permission) {
    // Check user-specific ACL
    // Check group-specific ACL
    // Check default policy
}

Attribute-Based Access Control (ABAC)

ABAC uses attributes of the user, resource, action, and environment to make access decisions. It is highly flexible and scalable for complex systems.

ABAC example:
Attributes:
- User: department, clearance, location, role
- Resource: classification, owner, type
- Action: read, write, delete, approve
- Environment: time, IP address, device

Policy Example:
IF user.department == resource.department 
   AND user.clearance >= resource.classification 
   AND action == 'read' 
   AND environment.time BETWEEN 9 AND 17
THEN ALLOW

// XACML (eXtensible Access Control Markup Language)
// Open Policy Agent (OPA) for policy-as-code

Relationship-Based Access Control (ReBAC)

ReBAC grants access based on relationships between users and resources. It is commonly used in social networks and collaborative applications.

ReBAC example:
Relationships:
- User is owner of Document
- User is member of Team
- Team has access to Project

Access Rules:
- Document owner can edit
- Team members can view
- Project collaborators can comment

// Google Zanzibar (used by Google Drive, YouTube, Gmail)
// Authorization based on user-resource relationships

Authorization Implementation in Code

Authorization should be enforced at multiple levels: API endpoints, service methods, and data queries. Never rely solely on hiding UI elements for security.

PHP authorization middleware:
// Authorization middleware
class AuthorizationMiddleware {
    public function handle($request, $next) {
        $user = getCurrentUser();
        $resource = $request->getResource();
        $action = $request->getMethod();
        
        if (!$this->isAuthorized($user, $resource, $action)) {
            http_response_code(403);
            die('Forbidden: You do not have permission to access this resource.');
        }
        
        return $next($request);
    }
    
    private function isAuthorized($user, $resource, $action) {
        // RBAC check
        if ($user->hasRole('admin')) {
            return true;
        }
        
        // Resource ownership check
        if ($resource->owner_id === $user->id && $action === 'read') {
            return true;
        }
        
        // Permission check
        $permission = "{$resource->type}.{$action}";
        return $user->hasPermission($permission);
    }
}

// Route with authorization
$app->get('/api/documents/{id}', function($id) {
    // Authorize before processing
})->add(new AuthorizationMiddleware());
Node.js authorization middleware:
// Authorization middleware (Express)
function requirePermission(permission) {
    return (req, res, next) => {
        const user = req.user;
        
        if (!user) {
            return res.status(401).json({ error: 'Unauthenticated' });
        }
        
        // Check user permissions
        if (!user.permissions || !user.permissions.includes(permission)) {
            return res.status(403).json({ error: 'Forbidden' });
        }
        
        next();
    };
}

// Resource ownership check
function requireOwnership(getResourceId) {
    return async (req, res, next) => {
        const resourceId = getResourceId(req);
        const resource = await db.find(resourceId);
        
        if (resource.user_id !== req.user.id && req.user.role !== 'admin') {
            return res.status(403).json({ error: 'Forbidden' });
        }
        
        req.resource = resource;
        next();
    };
}

// Route usage
app.delete('/api/posts/:id', 
    requirePermission('posts.delete'),
    requireOwnership(req => req.params.id),
    deletePostController
);
Database-level authorization (Row-Level Security):
-- PostgreSQL Row-Level Security (RLS)
-- Enable RLS on table
ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Policy for users to see only their own documents
CREATE POLICY user_documents ON documents
    USING (user_id = current_setting('app.current_user_id')::int);

-- Policy for managers to see team documents
CREATE POLICY manager_documents ON documents
    USING (
        user_id IN (
            SELECT user_id FROM team_members 
            WHERE manager_id = current_setting('app.current_user_id')::int
        )
    );

-- Application sets current user
SET app.current_user_id = 123;
SELECT * FROM documents; -- Only authorized rows returned

Common Authorization Vulnerabilities

Authorization flaws are among the most common and critical security vulnerabilities. Understanding these vulnerabilities helps you prevent them.

Vulnerability Description Example
IDOR (Insecure Direct Object Reference) User can access resources by guessing/modifying IDs /user/profile?id=123 -> /user/profile?id=124
Privilege Escalation User gains higher permissions than intended Normal user accessing admin endpoints
Missing Function-Level Access Control API endpoints lack permission checks DELETE /api/user/123 accessible to any authenticated user
Horizontal Privilege Escalation User accesses another user's data (same role) User A viewing User B's orders
Vertical Privilege Escalation User accesses higher-privilege functions Regular user performing admin actions
Preventing IDOR vulnerability:
// Vulnerable code (IDOR)
app.get('/api/invoice/:id', (req, res) => {
    const invoice = db.findInvoice(req.params.id);
    res.json(invoice); // No ownership check!
});

// Secure code with ownership check
app.get('/api/invoice/:id', (req, res) => {
    const invoice = db.findInvoice(req.params.id);
    
    // Verify ownership
    if (invoice.user_id !== req.user.id && req.user.role !== 'admin') {
        return res.status(403).json({ error: 'Access denied' });
    }
    
    res.json(invoice);
});

// Alternative: Use UUIDs instead of sequential IDs
// Sequential IDs: 1, 2, 3 (guessable)
// UUIDs: 550e8400-e29b-41d4-a716-446655440000 (unguessable)

Authorization Best Practices

Following these best practices ensures your authorization implementation is secure and maintainable.

  • Enforce on Server Side Only: Never rely on client-side authorization (hiding buttons is not security).
  • Deny by Default: Start with no access, explicitly grant permissions.
  • Check at Every Layer: Enforce authorization at API, service, and database layers.
  • Use Principle of Least Privilege: Grant minimal permissions necessary for each role.
  • Implement Defense in Depth: Multiple authorization checks provide redundancy.
  • Log Authorization Failures: Monitor for potential attacks and misconfigurations.
  • Use Centralized Authorization Logic: Avoid scattered permission checks throughout code.
  • Regularly Audit Permissions: Review and remove unnecessary permissions.
  • Use Policy-as-Code: Define authorization policies in code for version control and review.
Centralized authorization service example:
// Centralized Authorization Service
class AuthorizationService {
    private $policies = [];
    
    public function define($resource, $action, $callback) {
        $this->policies[$resource][$action] = $callback;
    }
    
    public function can($user, $resource, $action, $context = []) {
        // Check if policy exists
        if (!isset($this->policies[$resource][$action])) {
            return false;
        }
        
        // Execute policy callback
        return $this->policies[$resource][$action]($user, $context);
    }
}

// Define policies
$auth = new AuthorizationService();

$auth->define('document', 'view', function($user, $context) {
    return $user->hasRole('admin') || $context['document']->owner_id === $user->id;
});

$auth->define('document', 'delete', function($user, $context) {
    return $user->hasRole('admin');
});

$auth->define('document', 'edit', function($user, $context) {
    return $user->hasRole('editor') && $context['document']->status !== 'published';
});

// Usage
if ($auth->can($currentUser, 'document', 'delete', ['document' => $doc])) {
    // Allow delete
}

Authorization vs Authentication vs Access Control

These terms are often confused but serve different purposes. Understanding the distinctions is important for designing secure systems.

Concept Question Description Timing
Authentication Who are you? Verifies user identity First (login)
Authorization What can you do? Determines permissions After authentication
Access Control How is access enforced? Mechanism to enforce authorization During each request

Frequently Asked Questions

  1. What is the difference between authentication and authorization?
    Authentication verifies identity ("Who are you?"). Authorization determines permissions ("What can you do?"). Authentication happens first, then authorization.
  2. What is RBAC?
    Role-Based Access Control assigns permissions to roles, and users to roles. It is the most common authorization model because it simplifies permission management.
  3. What is IDOR and how do I prevent it?
    Insecure Direct Object Reference occurs when users can access resources by guessing IDs. Prevent it by checking ownership/permissions for every request and using unguessable identifiers (UUIDs).
  4. Should authorization be on client or server?
    Authorization must be enforced on the server. Client-side hiding of UI elements is for user experience, not security. Attackers can bypass client-side controls.
  5. What is the principle of least privilege?
    Users should have only the minimum permissions necessary to perform their job functions. This limits damage from compromised accounts or mistakes.
  6. What should I learn next after understanding authorization?
    After mastering authorization, explore authentication mechanisms, RBAC implementation, JWT for authorization, and web security fundamentals for comprehensive access control.

Conclusion

Authorization is a critical security control that determines what authenticated users can do. It ensures that users can only access resources and perform actions appropriate for their role or permission level. Without proper authorization, any authenticated user could access any resource, leading to data breaches and privilege escalation attacks.

Several authorization models exist: RBAC (most common), ACL (fine-grained), ABAC (flexible), and ReBAC (relationship-based). The right model depends on your application's complexity and security requirements. Authorization must be enforced on the server side at every request, never rely on client-side hiding for security.

Common authorization vulnerabilities include IDOR, privilege escalation, and missing access controls. Prevention strategies include ownership checks, deny-by-default policies, centralized authorization logic, and regular permission audits. Following the principle of least privilege reduces the impact of compromised accounts.

To deepen your understanding, explore related topics like authentication mechanisms, RBAC implementation, JWT for authorization, web security fundamentals, and security compliance. Together, these skills form a complete foundation for building secure access control systems.