Security Documentation
Enterprise-grade security implementation & best practices
Security Architecture Overview
The Shirinzad E-Commerce Platform implements a comprehensive, multi-layered security architecture following industry best practices and OWASP guidelines.
Security Layers
graph TD
A[Client Request] --> B[Rate Limiting Layer]
B --> C[Authentication Layer
JWT Bearer Tokens] C --> D[Authorization Layer
Roles & Permissions] D --> E[Input Validation Layer
Data Annotations & Sanitization] E --> F[Business Logic Layer
Domain Rules] F --> G[Data Access Layer
Parameterized Queries] G --> H[Audit Logging Layer
14 Properties Tracked] style A fill:#6366f1 style C fill:#059669 style D fill:#d97706 style H fill:#7c3aed
JWT Bearer Tokens] C --> D[Authorization Layer
Roles & Permissions] D --> E[Input Validation Layer
Data Annotations & Sanitization] E --> F[Business Logic Layer
Domain Rules] F --> G[Data Access Layer
Parameterized Queries] G --> H[Audit Logging Layer
14 Properties Tracked] style A fill:#6366f1 style C fill:#059669 style D fill:#d97706 style H fill:#7c3aed
Security Posture: The platform implements defense-in-depth strategy with multiple security layers protecting against common vulnerabilities.
1. Authentication
JWT Bearer Token Authentication (OpenIddict)
The platform uses OpenIddict for OAuth 2.0 and OpenID Connect authentication with JWT bearer tokens.
Implementation Details:
| Feature | Implementation | Status |
|---|---|---|
| Token Type | JWT (JSON Web Tokens) | Implemented |
| Token Lifetime | 3600 seconds (1 hour) | Implemented |
| Refresh Tokens | 7 days sliding expiration | Implemented |
| Token Encryption | Production certificate (openiddict.pfx) | Implemented |
| Multi-Factor Auth (MFA) | Not implemented | Recommended |
Configuration (ShopWebModule.cs):
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("Shop");
options.UseLocalServer();
options.UseAspNetCore();
});
});
// Production certificate configuration
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<OpenIddictServerBuilder>(serverBuilder =>
{
serverBuilder.AddProductionEncryptionAndSigningCertificate(
"openiddict.pfx",
"f49b2364-8c08-491c-ba29-16c17d2e91a8"
);
});
}
Authentication Flow:
sequenceDiagram
participant Client
participant API
participant OpenIddict
participant Database
Client->>API: POST /api/account/login
API->>Database: Validate credentials
Database-->>API: User verified
API->>OpenIddict: Generate JWT token
OpenIddict-->>API: Access token + Refresh token
API-->>Client: Return tokens
Client->>API: GET /api/products (with Bearer token)
API->>OpenIddict: Validate token
OpenIddict-->>API: Token valid
API-->>Client: Return data
Password Security (ABP Identity)
| Feature | Configuration | Status |
|---|---|---|
| Hashing Algorithm | PBKDF2 (Password-Based Key Derivation Function 2) | Implemented |
| Minimum Length | 6 characters (configurable) | Implemented |
| Complexity Requirements | Uppercase, lowercase, digit, special char | Implemented |
| Password History | Prevents reuse of last 3 passwords | Recommended |
| Password Expiration | Not implemented | Recommended |
Account Security Features
- Login Attempts Tracking: Database table tracks failed login attempts with IP address and timestamp
- Account Lockout: Automatic lockout after 5 failed login attempts
- Lockout Duration: 15 minutes (configurable)
- Email Confirmation: Required for new account activation
- Phone Verification: OTP-based phone number verification
- Password Reset: Secure token-based password recovery
- Two-Factor Authentication: Email/SMS OTP support (needs implementation)
Login Attempts Table Schema:
CREATE TABLE LoginAttempts (
Id UNIQUEIDENTIFIER PRIMARY KEY,
UserId UNIQUEIDENTIFIER NULL,
UserNameOrEmail NVARCHAR(256) NOT NULL,
IpAddress NVARCHAR(45) NULL,
UserAgent NVARCHAR(512) NULL,
IsSuccessful BIT NOT NULL,
FailureReason NVARCHAR(256) NULL,
AttemptTime DATETIME2 NOT NULL,
CreationTime DATETIME2 NOT NULL
);
2. Authorization
Role-Based Access Control (RBAC)
| Role | Description | Permissions |
|---|---|---|
| Admin | Full system access | All CRUD operations, user management, settings, reports |
| Customer | Standard user account | Browse products, place orders, manage profile, reviews |
| Guest | Unauthenticated user | Browse products, view categories (read-only) |
Usage Example:
// Require authentication
[Authorize]
public class OrderAppService : ApplicationService
{
// Only authenticated users can access
}
// Require specific role
[Authorize(Roles = "Admin")]
public class AdminDashboardAppService : ApplicationService
{
// Only admins can access
}
// Check role programmatically
if (CurrentUser.IsInRole("Admin"))
{
// Admin-specific logic
}
Permission-Based Authorization
ABP Framework provides granular permission system for fine-grained access control.
Permission Definition Example:
public class ShopPermissions
{
public const string GroupName = "Shop";
public static class Products
{
public const string Default = GroupName + ".Products";
public const string Create = Default + ".Create";
public const string Edit = Default + ".Edit";
public const string Delete = Default + ".Delete";
}
public static class Orders
{
public const string Default = GroupName + ".Orders";
public const string Create = Default + ".Create";
public const string Edit = Default + ".Edit";
public const string Cancel = Default + ".Cancel";
}
}
// Permission usage
[Authorize(ShopPermissions.Products.Create)]
public async Task<ProductDto> CreateAsync(CreateProductDto input)
{
// Only users with Products.Create permission can execute
}
Data Access Authorization
- User Isolation: Users can only access their own orders, carts, wishlists
- Tenant Isolation: Multi-tenancy support with complete data isolation
- Soft Delete: Sensitive data marked as deleted instead of hard deletion
- Field-Level Security: Sensitive fields (passwords, tokens) never exposed in DTOs
3. Rate Limiting
Enhanced Rate Limiting Service
Comprehensive rate limiting implementation to prevent API abuse, DoS attacks, and brute force attempts.
Endpoint-Specific Limits:
| Endpoint Category | Limit | Window | Reason |
|---|---|---|---|
| Authentication (Login, Register) | 3-5 requests | 15 min - 1 hour | Prevent brute force attacks |
| Phone OTP / Email OTP | 3-5 requests | 15 min - 1 hour | Prevent SMS/email spam |
| Public Endpoints (Products, Categories) | 60-120 requests | 1 minute | Prevent scraping/abuse |
| Authenticated User (Cart, Orders) | 30-120 requests | 1 minute | Normal user protection |
| File Upload | 10 requests | 1 hour | Prevent storage abuse |
| Contact Forms | 5 requests | 1 hour | Prevent spam |
| Admin Endpoints | 300 requests | 1 minute | Higher limits for admins |
Role-Based Multipliers:
- Admin Users: 3x the normal limit
- Premium Users: 2x the normal limit
- Regular Users: Standard limits
- Anonymous Users: Strictest limits
Implementation (EnhancedRateLimitService.cs):
public class EnhancedRateLimitService : IRateLimitService
{
private readonly Dictionary<string, RateLimitRule> _endpointRules = new()
{
["/api/auth/login/phone-otp"] = new(3, TimeSpan.FromHours(1)),
["/api/auth/verify/phone-otp"] = new(5, TimeSpan.FromMinutes(15)),
["/api/products"] = new(60, TimeSpan.FromMinutes(1)),
["/api/cart"] = new(120, TimeSpan.FromMinutes(1)),
["/api/files/upload"] = new(10, TimeSpan.FromHours(1))
};
public async Task<RateLimitResult> CheckLimitAsync(
string endpoint,
string identifier,
ClaimsPrincipal? user = null)
{
var rule = GetRuleForEndpoint(endpoint);
// Apply role-based multiplier
if (user?.IsInRole("Admin") == true)
{
rule = new RateLimitRule(rule.Limit * 3, rule.Window);
}
// Check and update counter in Redis cache
var cacheKey = $"ratelimit:{endpoint}:{identifier}";
var currentCount = await _cache.GetStringAsync(cacheKey);
if (currentCount >= rule.Limit)
{
return new RateLimitResult
{
IsAllowed = false,
RetryAfter = rule.Window
};
}
// Increment counter
await _cache.SetStringAsync(cacheKey,
(currentCount + 1).ToString(),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = rule.Window
});
return new RateLimitResult { IsAllowed = true };
}
}
Response Headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1609459200
Retry-After: 60
4. Audit Logging
Comprehensive Audit Trail
The platform tracks all user actions and system events for security monitoring, compliance, and forensic analysis.
Tracked Properties (14 fields):
| Property | Type | Description |
|---|---|---|
| Id | Guid | Unique log entry identifier |
| UserId | Guid? | User who performed the action |
| UserName | string | Username for easy identification |
| ActionType | string | Create, Update, Delete, Login, Logout, etc. |
| EntityType | string | Affected entity type (Product, Order, etc.) |
| EntityId | string | Affected entity identifier |
| HttpMethod | string | GET, POST, PUT, DELETE |
| Url | string | Request URL |
| IpAddress | string | User IP address for geolocation |
| UserAgent | string | Browser/device information |
| DurationMs | int? | Request duration in milliseconds |
| StatusCode | int? | HTTP status code (200, 404, 500, etc.) |
| ErrorMessage | string | Error details if action failed |
| AdditionalInfo | string (JSON) | Extra context data |
Audit Log Entity (AuditLog.cs):
public class AuditLog : CreationAuditedAggregateRoot<Guid>
{
public Guid? UserId { get; set; }
public string? UserName { get; set; }
public string ActionType { get; set; }
public string? EntityType { get; set; }
public string? EntityId { get; set; }
public string? HttpMethod { get; set; }
public string? Url { get; set; }
public string? IpAddress { get; set; }
public string? UserAgent { get; set; }
public int? DurationMs { get; set; }
public int? StatusCode { get; set; }
public string? ErrorMessage { get; set; }
public string? AdditionalInfo { get; set; }
public bool IsSuccessful { get; set; }
}
Retention Policy:
- Retention Period: 90 days (configurable)
- Archive Strategy: Move old logs to archive storage
- Compliance: Meets GDPR and data protection requirements
- Access Control: Only admins can view audit logs
Monitored Actions
Authentication Events
- Login attempts (success/failure)
- Logout events
- Password changes
- Password reset requests
- Account lockouts
- OTP generation and verification
Data Modification Events
- Product creation/updates/deletion
- Order placement and status changes
- Payment processing
- User profile changes
- Settings modifications
- Administrative actions
5. Input Validation & Sanitization
Server-Side Validation
All user inputs are validated on the server using Data Annotations and FluentValidation.
Data Annotations Example:
public class CreateProductDto
{
[Required]
[StringLength(256)]
public string Name { get; set; }
[Required]
[StringLength(256)]
[RegularExpression(@"^[a-z0-9-]+$")]
public string Slug { get; set; }
[Range(0, double.MaxValue)]
public decimal Price { get; set; }
[Range(0, int.MaxValue)]
public int Stock { get; set; }
[EmailAddress]
public string? ContactEmail { get; set; }
[Url]
public string? MainImageUrl { get; set; }
}
Custom Validation Rules:
- Business rule validation in domain entities
- Cross-field validation (e.g., discount price must be less than price)
- Unique constraint validation (e.g., slug uniqueness)
- File upload validation (type, size, content)
Input Sanitization
| Input Type | Sanitization Method | Status |
|---|---|---|
| HTML Content | HTML encoding, strip dangerous tags | Implemented |
| User Text | Trim, normalize whitespace | Implemented |
| URLs | URL validation, protocol whitelist | Implemented |
| File Names | Path traversal prevention, extension validation | Implemented |
| Rich Text (Blog/CMS) | HTML sanitizer library | Recommended |
6. Security Protection Mechanisms
SQL Injection Protection
- Entity Framework Core: All queries use parameterized commands
- LINQ Queries: Automatically parameterized
- Raw SQL Prevention: No raw SQL queries allowed
- Stored Procedures: Use parameters, not string concatenation
Safe Query Example:
// Safe - Parameterized query via LINQ
var products = await _repository
.Where(p => p.Name.Contains(searchTerm))
.ToListAsync();
// Generated SQL:
// SELECT * FROM Products
// WHERE Name LIKE @p0
// Parameters: @p0 = '%searchTerm%'
Cross-Site Scripting (XSS) Protection
- HTML Encoding: All user input automatically encoded
- Content Security Policy: Restrict inline scripts
- Anti-Forgery Tokens: CSRF protection on forms
- Safe DOM Manipulation: Use framework bindings
Response Headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'
CORS Configuration
- Allowed Origins: Whitelist specific domains
- Allowed Methods: GET, POST, PUT, DELETE
- Allowed Headers: Content-Type, Authorization
- Credentials: Allow credentials for same-origin
Configuration:
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins(
"https://shop.shirinzad.ir",
"https://admin.shirinzad.ir"
)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
Security Headers
| Header | Value | Purpose |
|---|---|---|
| Strict-Transport-Security | max-age=31536000 | Force HTTPS |
| X-Content-Type-Options | nosniff | Prevent MIME sniffing |
| X-Frame-Options | DENY | Prevent clickjacking |
| X-XSS-Protection | 1; mode=block | Enable XSS filter |
| Referrer-Policy | strict-origin-when-cross-origin | Control referrer info |
7. File Upload Security
Current Implementation
| Security Measure | Implementation | Status |
|---|---|---|
| File Size Limit | 20MB maximum (configurable) | Implemented |
| Extension Whitelist | jpg, jpeg, png, gif, pdf, docx | Recommended |
| MIME Type Validation | Check actual file content | Recommended |
| Virus Scanning | Not implemented | Recommended |
| Filename Sanitization | Remove special characters, path traversal | Implemented |
| Storage Location | Outside web root (wwwroot/uploads) | Implemented |
Recommended Enhancements:
- Implement virus scanning (ClamAV integration)
- Add MIME type validation
- Generate random filenames to prevent overwrite attacks
- Store files in cloud storage (Azure Blob, AWS S3)
- Implement file quarantine for suspicious uploads
8. OWASP Top 10 Compliance
Security Assessment Against OWASP Top 10 (2021)
| Vulnerability | Risk Level | Mitigation | Status |
|---|---|---|---|
| A01: Broken Access Control | Critical | JWT auth, RBAC, permission checks | Mitigated |
| A02: Cryptographic Failures | High | HTTPS, password hashing (PBKDF2), encrypted tokens | Mitigated |
| A03: Injection | High | Parameterized queries, input validation, EF Core | Mitigated |
| A04: Insecure Design | Medium | Secure architecture, threat modeling, rate limiting | Mitigated |
| A05: Security Misconfiguration | Medium | Production certificates, secure defaults, hardening | Partial |
| A06: Vulnerable Components | Medium | Regular dependency updates, .NET 9.0, ABP 9.3.5 | Mitigated |
| A07: Auth & Session Management | High | JWT tokens, secure session, account lockout | Mitigated |
| A08: Software & Data Integrity | Medium | Code signing, secure CI/CD pipeline | Partial |
| A09: Security Logging & Monitoring | Medium | Comprehensive audit logging, 14 properties tracked | Mitigated |
| A10: Server-Side Request Forgery | Low | Input validation, URL whitelist | Mitigated |
Production Security Checklist
Implemented Features
- JWT Bearer token authentication
- Role-based authorization (Admin, Customer)
- Permission-based access control
- Endpoint-specific rate limiting
- Comprehensive audit logging (14 properties)
- Password hashing (PBKDF2)
- Account lockout after failed attempts
- Login attempts tracking
- Input validation and sanitization
- SQL injection protection (EF Core)
- XSS protection (HTML encoding)
- CORS configuration
- Security headers
- HTTPS enforcement
- Anti-forgery tokens
Recommended Enhancements
- Multi-Factor Authentication (MFA)
- Password expiration policy
- Password history (prevent reuse)
- File upload virus scanning
- MIME type validation
- Web Application Firewall (WAF)
- DDoS protection (Cloudflare/Azure)
- Security information and event management (SIEM)
- Penetration testing
- Security awareness training
- Regular security audits
- Bug bounty program