Introduction
In distributed systems, ensuring that only authorized users and services can access resources is crucial for maintaining security and integrity. This module covers the fundamental concepts of authentication and authorization, their importance, and how they are implemented in distributed systems.
Key Concepts
Authentication
Authentication is the process of verifying the identity of a user or service. It ensures that the entity requesting access is who it claims to be.
- User Authentication: Verifying the identity of a user through credentials such as usernames and passwords, biometrics, or multi-factor authentication (MFA).
- Service Authentication: Verifying the identity of a service or application, often through API keys, tokens, or certificates.
Authorization
Authorization is the process of determining whether an authenticated entity has permission to access a resource or perform an action.
- Access Control: Mechanisms that enforce what authenticated users or services can do. Common models include Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC).
- Permissions: Specific rights granted to users or services, such as read, write, or execute permissions.
Authentication Methods
Password-Based Authentication
The most common form of authentication where users provide a username and password.
Pros:
- Simple and widely understood.
Cons:
- Vulnerable to attacks such as brute force, phishing, and password reuse.
Multi-Factor Authentication (MFA)
Combines two or more authentication factors:
- Something you know (password).
- Something you have (smartphone, token).
- Something you are (biometrics).
Example:
Pros:
- Significantly increases security.
Cons:
- Can be inconvenient for users.
Token-Based Authentication
Uses tokens (e.g., JWT - JSON Web Tokens) to authenticate users and services.
Example:
Pros:
- Stateless and scalable.
- Can be used across different domains.
Cons:
- Token management can be complex.
Authorization Methods
Role-Based Access Control (RBAC)
Users are assigned roles, and roles are granted permissions.
Example:
Pros:
- Simplifies management of permissions.
Cons:
- Can become complex in large systems with many roles.
Attribute-Based Access Control (ABAC)
Access decisions are based on attributes of the user, resource, and environment.
Example:
User Attribute: Department = Sales Resource Attribute: Document Type = Sales Report Environment Attribute: Time = Business Hours
Pros:
- Highly flexible and fine-grained control.
Cons:
- More complex to implement and manage.
Practical Example: Implementing JWT Authentication
Step 1: User Login
- User sends a login request with credentials.
- Server verifies credentials.
- Server generates a JWT and sends it to the user.
import jwt import datetime def generate_jwt(user_id): payload = { 'user_id': user_id, 'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1) } token = jwt.encode(payload, 'secret_key', algorithm='HS256') return token
Step 2: Accessing a Protected Resource
- User sends a request with the JWT in the Authorization header.
- Server verifies the JWT.
- If valid, server grants access to the resource.
from flask import request, jsonify def protected_route(): token = request.headers.get('Authorization').split()[1] try: payload = jwt.decode(token, 'secret_key', algorithms=['HS256']) user_id = payload['user_id'] # Proceed with accessing the resource return jsonify({'message': 'Access granted'}) except jwt.ExpiredSignatureError: return jsonify({'message': 'Token has expired'}), 401 except jwt.InvalidTokenError: return jsonify({'message': 'Invalid token'}), 401
Exercises
Exercise 1: Implement Basic Authentication
Create a simple authentication system where users can register and login using a username and password. Store user credentials securely using hashing.
Solution:
import hashlib users = {} def register(username, password): hashed_password = hashlib.sha256(password.encode()).hexdigest() users[username] = hashed_password def login(username, password): hashed_password = hashlib.sha256(password.encode()).hexdigest() if users.get(username) == hashed_password: return "Login successful" else: return "Invalid credentials" # Register a user register('johndoe', 'password123') # Attempt to login print(login('johndoe', 'password123')) # Output: Login successful print(login('johndoe', 'wrongpassword')) # Output: Invalid credentials
Exercise 2: Implement Role-Based Access Control
Extend the basic authentication system to include roles and permissions. Implement a function to check if a user has a specific permission.
Solution:
roles = { 'admin': ['read', 'write', 'delete'], 'user': ['read'] } user_roles = { 'johndoe': 'admin', 'janedoe': 'user' } def has_permission(username, permission): role = user_roles.get(username) if role and permission in roles.get(role, []): return True return False # Check permissions print(has_permission('johndoe', 'delete')) # Output: True print(has_permission('janedoe', 'delete')) # Output: False
Common Mistakes and Tips
- Storing Plain Text Passwords: Always hash passwords before storing them.
- Ignoring Token Expiry: Ensure tokens have an expiry time to reduce the risk of misuse.
- Overcomplicating Access Control: Start with simple models like RBAC and evolve as needed.
Conclusion
Authentication and authorization are critical components of distributed systems security. Understanding and implementing these concepts correctly ensures that only authorized users and services can access resources, maintaining the system's integrity and security. In the next module, we will delve into encryption and data protection to further enhance the security of distributed systems.
Distributed Architectures Course
Module 1: Introduction to Distributed Systems
- Basic Concepts of Distributed Systems
- Models of Distributed Systems
- Advantages and Challenges of Distributed Systems