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 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 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.
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.
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.
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.
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.
// 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());
// 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
);
-- 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 |
// 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
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
- 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. - 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. - 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). - 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. - 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. - 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.
