Project
Secure Design Patterns
February 2023
Building Security Into Software Design: A Practical Guide to Secure Design Patterns
A comprehensive exploration of six fundamental security patterns with working implementations
Introduction: The Security-by-Design Imperative
In today’s threat landscape, security cannot be an afterthought. According to research from Carnegie Mellon’s Software Engineering Institute, fixing security vulnerabilities after deployment costs exponentially more than addressing them during the design phase (Dougherty et al., 2009). Yet, traditional software development often treats security as something to “bolt on” after the core architecture is complete—a reactive approach that leads to scattered security controls, inconsistent enforcement, and persistent vulnerabilities.
What if we could weave security directly into the architectural patterns that form the foundation of our applications? This is the promise of secure design patterns: reusable solutions that integrate security controls at the design level rather than as aftermarket patches.
My repository, secure-design-patterns, provides practical, runnable Java implementations of six fundamental secure design patterns. Each pattern demonstrates how to embed authentication, authorization, and least privilege principles directly into object-oriented designs, creating systems that are secure by construction rather than by accident.
The Problem with Bolt-On Security
Traditional approaches to software security typically follow this pattern:
- Design the application architecture
- Implement core business logic
- Add authentication checks where needed
- Sprinkle authorization logic throughout
- Hope nothing was missed
This reactive methodology creates several critical problems:
- Scattered Security Controls: Authentication and authorization logic becomes distributed across the codebase, making it difficult to audit and maintain
- Inconsistent Enforcement: Without a unified approach, security policies are applied inconsistently, creating potential bypass opportunities
- High Maintenance Burden: Security logic entangled with business logic makes both harder to modify and test
- Increased Attack Surface: Each ad-hoc security check represents a potential point of failure
Research from academic institutions like Michigan State University has shown that using UML diagrams and patterns to model security requirements early in the software development lifecycle significantly reduces security vulnerabilities (Wassermann & Cheng, 2007).
Understanding Design Patterns in Security Context
Design patterns, as introduced by the Gang of Four (Gamma et al., 1994), provide reusable solutions to common software design problems. When extended with security considerations, these patterns become powerful tools for building secure-by-design systems. As noted in the Software Engineering Institute’s research on secure design patterns, “the creation of secure design patterns by generalizing and cataloging existing best practices benefits the developers of secure software products” (Dougherty et al., 2009).
The six patterns in my repository demonstrate how classic Gang of Four patterns can be enhanced with security-specific functionality:
1. Secure Factory Pattern
Security Principle: Centralized credential validation before object instantiation
The Factory Method pattern is one of the fundamental creational patterns that “defines an interface for creating an object, but lets subclasses decide which class to instantiate” (Gamma et al., 1994). In its secure variant, the factory validates credentials before creating sensitive objects like database connections or privileged resources.
UML Structure: The pattern follows the classic factory structure with an additional layer of credential checking:
┌─────────────────┐
│ <<interface>> │
│ Factory │
└─────────────────┘
△
│
┌───────┴────────┐
│SecureFactory │
│+ authenticate()│
│+ createObject()│
└────────────────┘
Key Security Benefits:
- Single point of control for object creation
- Credential validation happens before instantiation
- Failed authentication prevents resource allocation
- Consistent security policy enforcement across all object creation
Real-World Applications:
- Database connection pooling with role-based access
- API client factory with OAuth token validation
- File system access with permission checking
For detailed UML diagrams of the Factory Method pattern, see the comprehensive examples at Wikipedia and UML-Diagrams.org.
2. Secure Builder Factory Pattern
Security Principle: Restricting complex object construction to trusted builders
The Builder pattern, traditionally used to construct complex objects step-by-step, can be secured by ensuring only authorized builders can assemble sensitive objects. This pattern combines the factory’s centralized control with the builder’s flexibility.
UML Structure: This pattern combines Factory and Builder patterns:
┌──────────────┐ ┌──────────────┐
│ SecureFactory│────────>│ Builder │
│+ createBuild │ │+ buildPart() │
└──────────────┘ └──────────────┘
│ △
│ │
│ ┌───────┴────────┐
│ │ TrustedBuilder │
└───validates───>│+ authenticate()│
└────────────────┘
Key Security Benefits:
- Multi-step validation during object construction
- Prevention of partially-constructed objects in invalid states
- Builder authorization separate from user authorization
- Immutable objects with verified configurations
Real-World Applications:
- Configuration objects with validated parameters
- Encrypted message builders with key management
- Secure session objects with verified attributes
3. Secure Strategy Factory Pattern
Security Principle: Runtime algorithm selection based on caller privileges
The Strategy pattern encapsulates algorithms behind a common interface, allowing them to be selected and swapped at runtime. In its secure form, the pattern ensures only authorized users can invoke certain strategies (e.g., biometric authentication vs. password-based authentication).
UML Structure:
┌─────────────────┐ ┌──────────────┐
│StrategyFactory │─────>│<<interface>> │
│+ getStrategy() │ │ Strategy │
│+ checkPrivilege │ └──────────────┘
└─────────────────┘ △
│
┌───────────────┴────────────────┐
│ │
┌───────┴────────┐ ┌─────────┴────────┐
│PasswordStrategy│ │BiometricStrategy │
│+ authenticate()│ │+ authenticate() │
└────────────────┘ └──────────────────┘
Key Security Benefits:
- Different authentication mechanisms based on security context
- Privilege escalation prevention through factory control
- Centralized algorithm selection logic
- Easy addition of new authentication methods
Real-World Applications:
- Multi-factor authentication systems
- Payment processing with different security levels
- Data encryption with algorithm selection based on classification
4. Secure Chain of Responsibility Pattern
Security Principle: Multi-layered validation through handler pipeline
The Chain of Responsibility pattern allows multiple objects to handle a request by passing it along a chain until one object handles it (or all objects process it). For security, this creates a validation pipeline where each handler can approve, reject, or pass the request forward.
UML Structure: The pattern creates a linked chain of validators:
┌─────────────────────┐
│ <<interface>> │
│ Handler │
│+ setNext(Handler) │
│+ handle(Request) │
└─────────────────────┘
△
│
┌───────┴──────────────────────────────────────┐
│ │
┌───┴────────────┐ ┌─────────────────┐ ┌────────┴──────────┐
│ LoggingHandler │ │ AuthHandler │ │AuthorizationHandler│
│+ handle() │ │+ authenticate() │ │+ authorize() │
└────────────────┘ └─────────────────┘ └───────────────────┘
The Chain of Responsibility pattern is extensively documented with UML examples at Wikipedia and in academic research by Wassermann & Cheng (2007).
Key Security Benefits:
- Defense in depth through multiple validation layers
- Request logging at entry point
- Sequential authentication and authorization checks
- Easy addition or removal of security checks
Real-World Applications:
- HTTP request filtering (CORS, authentication, rate limiting)
- Email spam filtering with multiple heuristics
- Network packet inspection and firewall rules
Implementation Example:
// From the repository
public abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract boolean handle(Request request);
}
5. Secure State Machine Pattern
Security Principle: Explicit state modeling with guarded transitions
State machines model an object’s lifecycle through discrete states and transitions. A secure state machine explicitly models authentication and authorization states, ensuring that state transitions only occur when security conditions are met.
UML State Diagram: Security states with guarded transitions:
┌─────────────┐ credentials ┌──────────────┐
│Unauthenticat├────────────>│ Authenticated│
│ -ed │ │ │
└─────────────┘ └───────┬──────┘
│ [hasRole(admin)]
│
┌──────┴─────────┐
│ Authorized │
│ (Admin) │
└────────────────┘
UML State Machine diagrams for security are extensively covered in research literature. Sparx Systems provides excellent tutorials on State Machine Diagrams, while academic research by Bajaj & Ramachandran (2015) demonstrates how to represent security specifications in UML State Machine diagrams.
Key Security Benefits:
- Explicit modeling of security states
- Impossible to reach privileged states without proper transitions
- Clear audit trail of state changes
- Prevention of privilege escalation through invalid transitions
Real-World Applications:
- User session management (anonymous → authenticated → authorized)
- Document workflow with approval states
- Payment processing state machines
Carnegie Mellon’s research on secure state machines shows this pattern effectively prevents unauthorized state transitions, a common source of security vulnerabilities (Dougherty et al., 2009).
6. Secure Visitor Pattern
Security Principle: Adding access control operations without modifying protected classes
The Visitor pattern allows adding new operations to objects without modifying their classes. In its secure form, visitors implement different access control operations (guest access, user access, admin access) that can be applied to protected content.
UML Structure: The visitor with role-based access:
┌──────────────────┐ ┌─────────────────┐
│ <<interface>> │ │ <<interface>> │
│ Element │ │ Visitor │
│+ accept(Visitor) │ │+ visit(Element) │
└──────────────────┘ └─────────────────┘
△ △
│ │
┌───────┴─────────┐ ┌───────┴──────────┐
│ ProtectedContent│ │ AccessCheckVisitor│
│+ accept() │<───────│+ visit() │
│+ getContent() │ │+ checkPermission()│
└─────────────────┘ └──────────────────┘
The Visitor pattern’s UML structure and security implications are well-documented at Wikipedia and in educational resources from Baeldung.
Key Security Benefits:
- New security operations without modifying protected classes
- Separation of access control logic from business logic
- Role-based access control through different visitor implementations
- Open/Closed Principle for security features
Real-World Applications:
- Content management systems with role-based viewing
- Document redaction based on clearance level
- API response filtering by user permissions
Practical Implementation: Getting Started
All six patterns in the repository are implemented in plain Java with no framework dependencies. This makes them ideal for:
- Educational purposes: Understanding secure design principles
- Reference implementations: Adapting patterns to your language and framework
- Prototyping: Quickly testing security architectures
- Code reviews: Having examples of secure patterns for comparison
Repository Structure
secure-design-patterns/
├── SecureFactory/
│ └── src/
│ └── org/secureFactoryExample/
├── SecureBuilderFactory/
│ └── src/
├── SecureStrategyFactory/
│ └── src/
├── SecureChainOfResponsibility/
│ └── src/
├── SecureStateMachine/
│ └── src/
└── SecureVisitor/
└── src/
Running the Examples
Each pattern can be compiled and run independently:
# Navigate to a pattern directory
cd SecureChainOfResponsibility
# Compile the source files
javac -d out $(find src -name "*.java")
# Run the main class
java -cp out Main
Example Output: Chain of Responsibility
[LOG] Request received from user: alice
[AUTH] Authenticating user: alice
[AUTH] User authenticated successfully
[AUTHZ] Checking authorization for operation: readData
[AUTHZ] User authorized for operation
[HANDLER] Processing request for authorized user
Academic and Industry Foundation
The patterns implemented in this repository are grounded in both academic research and industry best practices:
Academic Research
-
Software Engineering Institute (CMU) - Dougherty, Sayre, and Seacord’s comprehensive report on “Secure Design Patterns” (2009) catalogs patterns at architecture, design, and implementation levels. Their research demonstrates that using patterns reduces both development costs and post-deployment security risks.
-
Michigan State University - Wassermann and Cheng’s work on “Security Patterns” shows how UML-based security patterns can be formally verified and integrated into existing software development processes.
-
Pattern-Based Security Methodology - Research published in IARIA conferences demonstrates how UML diagrams combined with security patterns provide a semi-formal approach to secure system design that is both practical and verifiable.
Industry Standards
The patterns align with established security principles:
- OWASP Secure Coding Practices: Particularly principle of “Defense in Depth” (Chain of Responsibility) and “Fail Securely” (State Machine)
- NIST Cybersecurity Framework: Supporting the “Protect” function through secure-by-design architectures
- ISO/IEC 27034: Application Security standard emphasizing security controls integrated into design
Why These Patterns Matter
1. Prevention Over Detection
By designing security into your architecture, you prevent entire classes of vulnerabilities rather than trying to catch them through testing or monitoring. As the Software Engineering Institute notes, secure design patterns “eliminate the accidental insertion of vulnerabilities into code” (Dougherty et al., 2009).
2. Clarity and Maintainability
When security is part of the design pattern, it’s immediately clear to all developers:
- Where security controls are enforced
- What the security requirements are
- How to extend the system securely
3. Scalability
These patterns scale naturally as applications grow. Unlike ad-hoc security measures that become unwieldy in large codebases, pattern-based security maintains its structure and effectiveness.
4. Communication and Documentation
Patterns provide a common vocabulary for discussing security architecture. Rather than lengthy prose descriptions, teams can reference well-known patterns with understood security properties.
5. Testability
Security logic encapsulated in patterns can be unit tested independently from business logic. The Chain of Responsibility, for example, allows each handler to be tested in isolation.
Educational Value
This repository serves multiple educational purposes:
For Students
- Concrete examples of secure coding principles
- Runnable code that can be experimented with
- Progressive complexity from simple (Secure Factory) to complex (Secure Visitor)
For Professional Developers
- Reference implementations for code reviews
- Starting points for secure refactoring
- Patterns to discuss in architecture review sessions
For Security Professionals
- Examples of security-by-design thinking
- Patterns that align with security frameworks
- Teaching tools for security training programs
Extending the Patterns
Each pattern in the repository includes extension suggestions. For example:
Secure Factory: Add credential caching, implement password policies, integrate with identity providers
Chain of Responsibility: Add rate limiting handlers, implement circuit breakers, create audit logging
State Machine: Model complex approval workflows, implement timeout transitions, add compensation states
Visitor: Implement content redaction, create permission inheritance, add temporal access control
Real-World Applications
These patterns aren’t just academic exercises—they appear throughout production systems:
Enterprise Applications
- Spring Security uses Chain of Responsibility for filter chains
- Hibernate uses Visitor for query parsing and optimization
- Apache Shiro uses Factory patterns for security managers
Cloud Platforms
- AWS IAM uses State Machines for permission evaluation
- Azure’s resource providers use Factory patterns with authentication
- Google Cloud’s IAM uses Visitor-like patterns for policy evaluation
Financial Systems
- Payment processors use State Machines for transaction lifecycles
- Banking systems use Chain of Responsibility for fraud detection
- Trading platforms use Strategy patterns for authentication methods
Performance Considerations
Secure design patterns do introduce some overhead, but this is typically negligible compared to their security benefits:
- Factory patterns: Single additional credential check per object creation
- Chain of Responsibility: Linear overhead proportional to chain length
- State Machines: Constant-time state transition validation
- Visitor patterns: Additional indirection through double-dispatch
In performance-critical paths, consider:
- Caching authentication results
- Optimizing chain handler order (fail-fast)
- Pre-compiling state transition tables
Common Pitfalls and How to Avoid Them
1. Over-Engineering
Problem: Applying patterns where simple solutions suffice Solution: Use patterns when you have multiple security operations or complex state management needs
2. Incomplete Implementation
Problem: Implementing the pattern structure but skipping security checks Solution: Include security checks in code reviews and security testing
3. Tight Coupling
Problem: Concrete implementations depend on specific credential types Solution: Use interfaces for credentials and security contexts
4. State Explosion
Problem: State machines with too many states become unmanageable Solution: Use hierarchical state machines or composite patterns
Future Directions
This repository continues to evolve. Planned additions include:
Additional Patterns
- Secure Proxy: Access control and monitoring for remote objects
- Secure Decorator: Adding security features to existing objects
- Secure Template Method: Security-aware algorithm skeletons
Expanded Languages
- Python implementations for data science applications
- Go implementations for microservices
- Rust implementations emphasizing compile-time security
Integration Examples
- Spring Framework integration
- Jakarta EE security integration
- Microservices patterns with OAuth2
Formal Verification
- Model checking for state machines
- Property-based testing examples
- Security protocol verification
Conclusion: Security as a First-Class Concern
The fundamental lesson of secure design patterns is that security cannot be an afterthought. By treating security as a first-class design concern—on par with performance, maintainability, and scalability—we can build systems that are secure by construction.
The patterns in this repository demonstrate that secure design doesn’t require sacrificing code quality or developer productivity. Instead, it provides structure, clarity, and confidence that security requirements are consistently enforced.
Whether you’re designing a new system or refactoring an existing one, these patterns offer proven approaches to common security challenges. They embody decades of collective wisdom from both academic research and industry practice, condensed into runnable examples that you can experiment with, learn from, and adapt to your needs.
Getting Involved
The repository is open source and welcomes contributions:
- Try the examples: Clone the repository and run the patterns
- Provide feedback: Open issues for bugs or suggestions
- Contribute patterns: Add new secure patterns or language implementations
- Share experiences: Discuss real-world applications of these patterns
Visit the repository at github.com/dschulmeist/secure-design-patterns
References and Further Reading
Primary Sources
Dougherty, C., Sayre, K., Seacord, R. C., Svoboda, D., & Togashi, K. (2009). Secure Design Patterns. Software Engineering Institute, Carnegie Mellon University. Technical Report CMU/SEI-2009-TR-010. Available at: https://resources.sei.cmu.edu/library/asset-view.cfm?assetid=9115
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley.
Wassermann, R., & Cheng, B. H. C. (2007). Security Patterns. Michigan State University Technical Report MSU-CSE-03-23.
UML and Design Pattern Resources
UML State Machines: https://www.uml-diagrams.org/state-machine-diagrams.html
Factory Method Pattern: https://en.wikipedia.org/wiki/Factory_method_pattern
Chain of Responsibility Pattern: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
Visitor Pattern: https://en.wikipedia.org/wiki/Visitor_pattern
Refactoring Guru - Design Patterns: https://refactoring.guru/design-patterns
Security Standards and Frameworks
OWASP Secure Coding Practices: https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/
NIST Cybersecurity Framework: https://www.nist.gov/cyberframework
Software Engineering Institute - Secure Design: https://www.sei.cmu.edu/our-work/secure-design/
Academic Papers
Bajaj, M., & Ramachandran, S. (2015). “Representing Security Specifications in UML State Machine Diagrams.” Procedia Computer Science, 57, 1150-1158.
Fernandez, E. B., & Pan, R. (2001). “A Pattern Language for Security Models.” PLoP Conference Proceedings.
Schumacher, M., Fernandez-Buglioni, E., Hybertson, D., Buschmann, F., & Sommerlad, P. (2006). Security Patterns: Integrating Security and Systems Engineering. Wiley.
Educational Resources
Sparx Systems UML Tutorials: https://sparxsystems.com/resources/tutorials/uml2/
Visual Paradigm Design Pattern Tutorials: https://www.visual-paradigm.com/tutorials/
GeeksforGeeks System Design: https://www.geeksforgeeks.org/system-design/
Last updated: January 2024
Questions or suggestions? Open an issue on GitHub or reach out to discuss how you’re applying these patterns in your projects!