using MarketAlly.AIPlugin; using MarketAlly.AIPlugin.Security.Plugins; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace MarketAlly.AIPlugin.Security.Plugins { /// /// Reviews authentication and authorization implementation for security best practices /// [AIPlugin("AuthenticationAnalyzer", "Reviews authentication and authorization implementation for security best practices")] public class AuthenticationAnalyzerPlugin : IAIPlugin { [AIParameter("Full path to the file or directory to analyze", required: true)] public string Path { get; set; } [AIParameter("Check JWT implementation", required: false)] public bool CheckJwt { get; set; } = true; [AIParameter("Check OAuth implementation", required: false)] public bool CheckOAuth { get; set; } = true; [AIParameter("Check session management", required: false)] public bool CheckSessions { get; set; } = true; [AIParameter("Check authorization patterns", required: false)] public bool CheckAuthorization { get; set; } = true; [AIParameter("Check password handling", required: false)] public bool CheckPasswords { get; set; } = true; public IReadOnlyDictionary SupportedParameters => new Dictionary { ["path"] = typeof(string), ["checkJwt"] = typeof(bool), ["checkOAuth"] = typeof(bool), ["checkSessions"] = typeof(bool), ["checkAuthorization"] = typeof(bool), ["checkPasswords"] = typeof(bool) }; // Authentication security patterns private static readonly Dictionary AuthPatterns = new() { // JWT Security Issues ["jwt_none_algorithm"] = (new Regex(@"(algorithm|alg)\s*[=:]\s*['""]none['""]", RegexOptions.IgnoreCase), "JWT", "Critical", "JWT using 'none' algorithm - bypasses signature verification"), ["jwt_weak_secret"] = (new Regex(@"(jwt|token).*(secret|key)\s*[=:]\s*['""][^'""]{1,15}['""]", RegexOptions.IgnoreCase), "JWT", "High", "JWT secret appears too short (less than 16 characters)"), ["jwt_hardcoded_secret"] = (new Regex(@"(jwt|token).*(secret|key)\s*[=:]\s*['""].*['""]", RegexOptions.IgnoreCase), "JWT", "High", "JWT secret appears to be hardcoded"), ["jwt_no_expiration"] = (new Regex(@"new\s+JwtSecurityToken\([^)]*\)(?!.*exp)", RegexOptions.IgnoreCase), "JWT", "Medium", "JWT token created without expiration"), ["jwt_long_expiration"] = (new Regex(@"(exp|expires|expiry).*(\d{4,}|TimeSpan\.FromDays\(\s*[3-9]\d+)", RegexOptions.IgnoreCase), "JWT", "Medium", "JWT token has very long expiration time"), // Password Security Issues ["plain_text_password"] = (new Regex(@"password\s*[=:]\s*['""][^'""]*['""](?!.*hash|Hash|encrypt|Encrypt)", RegexOptions.IgnoreCase), "Password", "Critical", "Password appears to be stored or compared in plain text"), ["weak_hash_algorithm"] = (new Regex(@"(MD5|SHA1|CRC32)\s*\(", RegexOptions.IgnoreCase), "Password", "High", "Using weak hashing algorithm for passwords"), ["no_salt"] = (new Regex(@"(SHA256|SHA512|MD5|SHA1)\s*\([^)]*password[^)]*\)(?!.*salt)", RegexOptions.IgnoreCase), "Password", "High", "Password hashing without salt"), ["hardcoded_salt"] = (new Regex(@"salt\s*[=:]\s*['""][^'""]*['""]", RegexOptions.IgnoreCase), "Password", "High", "Hardcoded salt value"), ["weak_password_policy"] = (new Regex(@"password.*length.*[1-5]", RegexOptions.IgnoreCase), "Password", "Medium", "Weak password length requirement (less than 6 characters)"), // Session Management Issues ["session_fixation"] = (new Regex(@"Session\[.*\]\s*=.*(?!.*Regenerate|regenerate)", RegexOptions.IgnoreCase), "Session", "Medium", "Session value assignment without regeneration"), ["insecure_session_cookie"] = (new Regex(@"(HttpOnly|Secure)\s*[=:]\s*false", RegexOptions.IgnoreCase), "Session", "High", "Session cookie missing security flags"), ["long_session_timeout"] = (new Regex(@"timeout\s*[=:]\s*['""]?\d{4,}['""]?", RegexOptions.IgnoreCase), "Session", "Medium", "Very long session timeout"), ["session_without_timeout"] = (new Regex(@"session.*(?!.*timeout|Timeout|expire|Expire)", RegexOptions.IgnoreCase), "Session", "Low", "Session configuration without explicit timeout"), // OAuth Security Issues ["oauth_state_missing"] = (new Regex(@"oauth.*authorize.*(?!.*state)", RegexOptions.IgnoreCase), "OAuth", "High", "OAuth authorization without state parameter (CSRF vulnerable)"), ["oauth_pkce_missing"] = (new Regex(@"oauth.*code.*(?!.*code_challenge)", RegexOptions.IgnoreCase), "OAuth", "Medium", "OAuth authorization code flow without PKCE"), ["oauth_implicit_flow"] = (new Regex(@"response_type\s*[=:]\s*['""]token['""]", RegexOptions.IgnoreCase), "OAuth", "High", "OAuth implicit flow usage (deprecated and insecure)"), ["oauth_insecure_redirect"] = (new Regex(@"redirect_uri.*http://", RegexOptions.IgnoreCase), "OAuth", "High", "OAuth redirect URI using HTTP instead of HTTPS"), // Authorization Issues ["missing_authorization"] = (new Regex(@"public\s+\w+\s+\w+\s*\([^)]*\)(?!.*\[Authorize\]|\[AllowAnonymous\])", RegexOptions.IgnoreCase), "Authorization", "Medium", "Public action method without authorization attribute"), ["overly_permissive_auth"] = (new Regex(@"\[AllowAnonymous\]", RegexOptions.IgnoreCase), "Authorization", "Low", "Method allows anonymous access - verify if intentional"), ["role_hardcoded"] = (new Regex(@"Roles?\s*[=:]\s*['""][^'""]*['""]", RegexOptions.IgnoreCase), "Authorization", "Medium", "Hardcoded role names in authorization"), ["privilege_escalation"] = (new Regex(@"(IsInRole|HasClaim|HasPermission).*(?!.*current.*user)", RegexOptions.IgnoreCase), "Authorization", "Medium", "Potential privilege escalation - not checking current user context"), // General Authentication Issues ["insecure_authentication"] = (new Regex(@"(authenticate|login).*http://", RegexOptions.IgnoreCase), "Authentication", "High", "Authentication over insecure HTTP connection"), ["weak_encryption"] = (new Regex(@"(DES|3DES|RC4)\s*\(", RegexOptions.IgnoreCase), "Authentication", "High", "Using weak encryption algorithm"), ["insecure_random"] = (new Regex(@"Random\s*\(\).*password|token|secret", RegexOptions.IgnoreCase), "Authentication", "Medium", "Using non-cryptographic random for security tokens"), ["authentication_bypass"] = (new Regex(@"if\s*\([^)]*debug[^)]*\).*return.*true", RegexOptions.IgnoreCase), "Authentication", "Critical", "Potential authentication bypass in debug mode"), // Multi-Factor Authentication ["missing_2fa"] = (new Regex(@"login|authenticate(?!.*two.*factor|2fa|mfa|totp)", RegexOptions.IgnoreCase), "Authentication", "Low", "Authentication without multi-factor authentication"), ["insecure_2fa"] = (new Regex(@"(sms|email).*token.*authenticate", RegexOptions.IgnoreCase), "Authentication", "Medium", "Using SMS/Email for 2FA (less secure than TOTP/hardware keys)") }; // Positive authentication patterns (good practices) private static readonly Dictionary GoodAuthPatterns = new() { ["bcrypt_usage"] = new Regex(@"BCrypt\.(HashPassword|VerifyPassword)", RegexOptions.IgnoreCase), ["argon2_usage"] = new Regex(@"Argon2", RegexOptions.IgnoreCase), ["pbkdf2_usage"] = new Regex(@"PBKDF2|Rfc2898DeriveBytes", RegexOptions.IgnoreCase), ["secure_jwt"] = new Regex(@"(HS256|RS256|ES256)", RegexOptions.IgnoreCase), ["jwt_validation"] = new Regex(@"ValidateIssuer|ValidateAudience|ValidateLifetime", RegexOptions.IgnoreCase), ["authorize_attribute"] = new Regex(@"\[Authorize\]", RegexOptions.IgnoreCase), ["https_enforcement"] = new Regex(@"RequireHttps|UseHttpsRedirection", RegexOptions.IgnoreCase), ["secure_cookies"] = new Regex(@"HttpOnly\s*=\s*true|Secure\s*=\s*true", RegexOptions.IgnoreCase), ["csrf_protection"] = new Regex(@"ValidateAntiForgeryToken|AntiForgeryToken", RegexOptions.IgnoreCase), ["rate_limiting"] = new Regex(@"RateLimit|Throttle", RegexOptions.IgnoreCase), ["account_lockout"] = new Regex(@"LockoutEnabled|MaxFailedAttempts", RegexOptions.IgnoreCase), ["password_complexity"] = new Regex(@"RequiredLength|RequireDigit|RequireUppercase", RegexOptions.IgnoreCase) }; public async Task ExecuteAsync(IReadOnlyDictionary parameters) { try { // Extract parameters string path = parameters["path"].ToString(); bool checkJwt = parameters.TryGetValue("checkJwt", out var jwtObj) ? Convert.ToBoolean(jwtObj) : true; bool checkOAuth = parameters.TryGetValue("checkOAuth", out var oauthObj) ? Convert.ToBoolean(oauthObj) : true; bool checkSessions = parameters.TryGetValue("checkSessions", out var sessionObj) ? Convert.ToBoolean(sessionObj) : true; bool checkAuthorization = parameters.TryGetValue("checkAuthorization", out var authzObj) ? Convert.ToBoolean(authzObj) : true; bool checkPasswords = parameters.TryGetValue("checkPasswords", out var pwdObj) ? Convert.ToBoolean(pwdObj) : true; // Validate path exists if (!File.Exists(path) && !Directory.Exists(path)) { return new AIPluginResult( new FileNotFoundException($"Path not found: {path}"), "Path not found" ); } // Collect files to analyze var filesToAnalyze = GetFilesToAnalyze(path); var results = new AuthenticationAnalysisResults { AnalyzedPath = path, FilesAnalyzed = filesToAnalyze.Count }; // Analyze each file foreach (var file in filesToAnalyze) { var content = await File.ReadAllTextAsync(file); var fileName = System.IO.Path.GetFileName(file); if (checkJwt) { await AnalyzeJwtSecurity(file, content, results); } if (checkOAuth) { await AnalyzeOAuthSecurity(file, content, results); } if (checkSessions) { await AnalyzeSessionManagement(file, content, results); } if (checkAuthorization) { await AnalyzeAuthorizationPatterns(file, content, results); } if (checkPasswords) { await AnalyzePasswordSecurity(file, content, results); } // Check for good authentication practices await AnalyzeGoodPractices(file, content, results); } // Calculate compliance score results.ComplianceScore = CalculateComplianceScore(results); // Generate security recommendations results.SecurityRecommendations = GenerateSecurityRecommendations(results); return new AIPluginResult(results, $"Authentication analysis completed. Found {results.GetTotalIssues()} authentication/authorization issues."); } catch (Exception ex) { return new AIPluginResult(ex, $"Authentication analysis failed: {ex.Message}"); } } /// /// Generates security recommendations based on findings /// private List GenerateSecurityRecommendations(AuthenticationAnalysisResults results) { var recommendations = new List(); // Critical issues first var criticalIssues = results.AuthenticationIssues.Where(i => i.Severity == "Critical").ToList(); if (criticalIssues.Any()) { recommendations.Add("🚨 **CRITICAL AUTHENTICATION ISSUES**:"); foreach (var issue in criticalIssues.Take(3)) { recommendations.Add($" • {issue.Description} (Line {issue.LineNumber} in {System.IO.Path.GetFileName(issue.File)})"); } recommendations.Add(" → These issues can lead to complete authentication bypass!"); } // High severity issues var highIssues = results.AuthenticationIssues.Where(i => i.Severity == "High").ToList(); if (highIssues.Any()) { recommendations.Add("⚠️ **HIGH PRIORITY AUTHENTICATION ISSUES**:"); recommendations.Add($" • {highIssues.Count} high-severity authentication vulnerabilities found"); var issueTypes = highIssues.GroupBy(i => i.Type).ToList(); foreach (var group in issueTypes) { recommendations.Add($" • {group.Key}: {group.Count()} issues"); } } // Authorization issues if (results.AuthorizationIssues.Any()) { recommendations.Add("🛡️ **AUTHORIZATION IMPROVEMENTS NEEDED**:"); var authzByType = results.AuthorizationIssues.GroupBy(i => i.Description).ToList(); foreach (var group in authzByType.Take(3)) { recommendations.Add($" • {group.Key}: {group.Count()} instances"); } } // Specific technology recommendations var jwtIssues = results.AuthenticationIssues.Where(i => i.Type.Contains("JWT")).Count(); if (jwtIssues > 0) { recommendations.Add("🔑 **JWT SECURITY IMPROVEMENTS**:"); recommendations.Add(" • Use strong secrets (32+ characters) or RSA keys"); recommendations.Add(" • Implement short token lifetimes (15-60 minutes)"); recommendations.Add(" • Add proper token validation and algorithm verification"); recommendations.Add(" • Consider using refresh tokens for long-lived sessions"); } var passwordIssues = results.AuthenticationIssues.Where(i => i.Type.Contains("Password")).Count(); if (passwordIssues > 0) { recommendations.Add("🔒 **PASSWORD SECURITY IMPROVEMENTS**:"); recommendations.Add(" • Use bcrypt, Argon2, or PBKDF2 for password hashing"); recommendations.Add(" • Implement unique salts for each password"); recommendations.Add(" • Enforce strong password policies (8+ chars, complexity)"); recommendations.Add(" • Never store passwords in plain text or use weak hashes"); } var sessionIssues = results.AuthenticationIssues.Where(i => i.Type.Contains("Session")).Count(); if (sessionIssues > 0) { recommendations.Add("📝 **SESSION MANAGEMENT IMPROVEMENTS**:"); recommendations.Add(" • Set HttpOnly and Secure flags on session cookies"); recommendations.Add(" • Implement appropriate session timeouts"); recommendations.Add(" • Regenerate session IDs after authentication"); recommendations.Add(" • Use secure session storage mechanisms"); } // General security recommendations recommendations.Add("📋 **GENERAL AUTHENTICATION BEST PRACTICES**:"); recommendations.Add(" • Enforce HTTPS for all authentication endpoints"); recommendations.Add(" • Implement rate limiting on login attempts"); recommendations.Add(" • Add account lockout protection"); recommendations.Add(" • Use multi-factor authentication where possible"); recommendations.Add(" • Implement proper CSRF protection"); recommendations.Add(" • Log and monitor authentication events"); // Positive reinforcement for good practices if (results.GoodPractices.Any()) { recommendations.Add("✅ **GOOD SECURITY PRACTICES FOUND**:"); foreach (var practice in results.GoodPractices.Take(5)) { recommendations.Add($" • {practice}"); } } // Compliance score recommendations if (results.ComplianceScore >= 80) { recommendations.Add("🌟 **EXCELLENT**: Your authentication implementation follows security best practices!"); recommendations.Add(" • Continue regular security reviews and updates"); } else if (results.ComplianceScore >= 60) { recommendations.Add("👍 **GOOD**: Address remaining issues to strengthen authentication security"); recommendations.Add(" • Focus on high and critical severity issues first"); } else if (results.ComplianceScore >= 40) { recommendations.Add("⚡ **NEEDS IMPROVEMENT**: Significant authentication security gaps found"); recommendations.Add(" • Prioritize fixing critical and high-severity issues immediately"); recommendations.Add(" • Consider security training for the development team"); } else { recommendations.Add("🚨 **CRITICAL**: Authentication security requires immediate attention"); recommendations.Add(" • Conduct thorough security review and remediation"); recommendations.Add(" • Consider engaging security experts for assessment"); recommendations.Add(" • Implement security-first development practices"); } return recommendations; } /// Gets list of files to analyze based on path /// private List GetFilesToAnalyze(string path) { var files = new List(); if (File.Exists(path)) { files.Add(path); } else if (Directory.Exists(path)) { // Focus on authentication-related files var extensions = new[] { "*.cs", "*.js", "*.ts", "*.py", "*.java", "*.php", "*.config", "*.json" }; foreach (var extension in extensions) { files.AddRange(Directory.GetFiles(path, extension, SearchOption.AllDirectories)); } // Filter to files likely to contain authentication code files = files.Where(f => f.Contains("auth", StringComparison.OrdinalIgnoreCase) || f.Contains("login", StringComparison.OrdinalIgnoreCase) || f.Contains("security", StringComparison.OrdinalIgnoreCase) || f.Contains("jwt", StringComparison.OrdinalIgnoreCase) || f.Contains("oauth", StringComparison.OrdinalIgnoreCase) || f.Contains("controller", StringComparison.OrdinalIgnoreCase) || f.Contains("service", StringComparison.OrdinalIgnoreCase) || System.IO.Path.GetFileName(f).Equals("startup.cs", StringComparison.OrdinalIgnoreCase) || System.IO.Path.GetFileName(f).Equals("program.cs", StringComparison.OrdinalIgnoreCase) ).ToList(); // If no specific auth files found, include all code files (up to 20) if (files.Count == 0) { foreach (var extension in extensions) { files.AddRange(Directory.GetFiles(path, extension, SearchOption.AllDirectories).Take(20)); } } } // Exclude common non-auth directories var excludedDirs = new[] { "node_modules", "bin", "obj", ".git", ".vs", "packages", "target", "build" }; files = files.Where(f => !excludedDirs.Any(dir => f.Contains($"{System.IO.Path.DirectorySeparatorChar}{dir}{System.IO.Path.DirectorySeparatorChar}"))).ToList(); return files.Take(50).ToList(); // Limit to 50 files for performance } /// /// Analyzes JWT security implementation /// private async Task AnalyzeJwtSecurity(string filePath, string content, AuthenticationAnalysisResults results) { var jwtPatterns = AuthPatterns.Where(p => p.Value.Type == "JWT").ToList(); foreach (var pattern in jwtPatterns) { var matches = pattern.Value.Pattern.Matches(content); foreach (Match match in matches) { results.AuthenticationIssues.Add(new AuthenticationIssue { Type = "JWT Security", Severity = pattern.Value.Severity, Description = pattern.Value.Description, File = filePath, LineNumber = GetLineNumber(content, match.Index), Code = GetContextLines(content, match.Index, 2), Recommendation = GetJwtRecommendation(pattern.Key) }); } } } /// /// Analyzes OAuth security implementation /// private async Task AnalyzeOAuthSecurity(string filePath, string content, AuthenticationAnalysisResults results) { var oauthPatterns = AuthPatterns.Where(p => p.Value.Type == "OAuth").ToList(); foreach (var pattern in oauthPatterns) { var matches = pattern.Value.Pattern.Matches(content); foreach (Match match in matches) { results.AuthenticationIssues.Add(new AuthenticationIssue { Type = "OAuth Security", Severity = pattern.Value.Severity, Description = pattern.Value.Description, File = filePath, LineNumber = GetLineNumber(content, match.Index), Code = GetContextLines(content, match.Index, 2), Recommendation = GetOAuthRecommendation(pattern.Key) }); } } } /// /// Analyzes session management security /// private async Task AnalyzeSessionManagement(string filePath, string content, AuthenticationAnalysisResults results) { var sessionPatterns = AuthPatterns.Where(p => p.Value.Type == "Session").ToList(); foreach (var pattern in sessionPatterns) { var matches = pattern.Value.Pattern.Matches(content); foreach (Match match in matches) { results.AuthenticationIssues.Add(new AuthenticationIssue { Type = "Session Management", Severity = pattern.Value.Severity, Description = pattern.Value.Description, File = filePath, LineNumber = GetLineNumber(content, match.Index), Code = GetContextLines(content, match.Index, 2), Recommendation = GetSessionRecommendation(pattern.Key) }); } } } /// /// Analyzes authorization patterns /// private async Task AnalyzeAuthorizationPatterns(string filePath, string content, AuthenticationAnalysisResults results) { var authzPatterns = AuthPatterns.Where(p => p.Value.Type == "Authorization").ToList(); foreach (var pattern in authzPatterns) { var matches = pattern.Value.Pattern.Matches(content); foreach (Match match in matches) { // Skip if this is a documented exception if (IsDocumentedException(content, match.Index)) continue; results.AuthorizationIssues.Add(new AuthorizationIssue { Type = "Authorization", Severity = pattern.Value.Severity, Description = pattern.Value.Description, File = filePath, LineNumber = GetLineNumber(content, match.Index), Code = GetContextLines(content, match.Index, 2), Recommendation = GetAuthorizationRecommendation(pattern.Key) }); } } } /// /// Analyzes password security practices /// private async Task AnalyzePasswordSecurity(string filePath, string content, AuthenticationAnalysisResults results) { var passwordPatterns = AuthPatterns.Where(p => p.Value.Type == "Password").ToList(); foreach (var pattern in passwordPatterns) { var matches = pattern.Value.Pattern.Matches(content); foreach (Match match in matches) { results.AuthenticationIssues.Add(new AuthenticationIssue { Type = "Password Security", Severity = pattern.Value.Severity, Description = pattern.Value.Description, File = filePath, LineNumber = GetLineNumber(content, match.Index), Code = GetContextLines(content, match.Index, 2), Recommendation = GetPasswordRecommendation(pattern.Key) }); } } } /// /// Analyzes good authentication practices /// private async Task AnalyzeGoodPractices(string filePath, string content, AuthenticationAnalysisResults results) { foreach (var pattern in GoodAuthPatterns) { if (pattern.Value.IsMatch(content)) { var practiceDescription = GetGoodPracticeDescription(pattern.Key); if (!results.GoodPractices.Contains(practiceDescription)) { results.GoodPractices.Add(practiceDescription); } } } } /// /// Checks if an issue is documented as an exception /// private bool IsDocumentedException(string content, int index) { var contextLines = GetContextLines(content, index, 3); return contextLines.Contains("// Security exception:", StringComparison.OrdinalIgnoreCase) || contextLines.Contains("// Allow anonymous:", StringComparison.OrdinalIgnoreCase) || contextLines.Contains("// Public API", StringComparison.OrdinalIgnoreCase); } /// /// Gets line number for a character index /// private int GetLineNumber(string content, int index) { return content.Take(index).Count(c => c == '\n') + 1; } /// /// Gets context lines around a match /// private string GetContextLines(string content, int index, int contextLines) { var lines = content.Split('\n'); var targetLine = GetLineNumber(content, index) - 1; var startLine = Math.Max(0, targetLine - contextLines); var endLine = Math.Min(lines.Length - 1, targetLine + contextLines); var contextList = new List(); for (int i = startLine; i <= endLine; i++) { var marker = i == targetLine ? ">>> " : " "; contextList.Add($"{marker}{i + 1}: {lines[i]}"); } return string.Join("\n", contextList); } /// /// Gets JWT-specific recommendations /// private string GetJwtRecommendation(string patternKey) { return patternKey switch { "jwt_none_algorithm" => "Never use 'none' algorithm for JWT. Use HS256, RS256, or ES256 instead.", "jwt_weak_secret" => "Use a strong JWT secret with at least 32 characters. Consider using RSA keys for RS256.", "jwt_hardcoded_secret" => "Store JWT secrets in environment variables or secure key management systems.", "jwt_no_expiration" => "Always set expiration time for JWT tokens. Use short lifetimes (15-60 minutes) with refresh tokens.", "jwt_long_expiration" => "Use shorter JWT expiration times (15-60 minutes) and implement refresh token mechanism.", _ => "Follow JWT security best practices: strong secrets, proper algorithms, and reasonable expiration times." }; } /// /// Gets OAuth-specific recommendations /// private string GetOAuthRecommendation(string patternKey) { return patternKey switch { "oauth_state_missing" => "Always include and validate the 'state' parameter to prevent CSRF attacks.", "oauth_pkce_missing" => "Implement PKCE (Proof Key for Code Exchange) for public clients and mobile apps.", "oauth_implicit_flow" => "Replace implicit flow with authorization code flow + PKCE for better security.", "oauth_insecure_redirect" => "Use HTTPS for all OAuth redirect URIs to prevent token interception.", _ => "Follow OAuth 2.1 security best practices and avoid deprecated flows." }; } /// /// Gets session-specific recommendations /// private string GetSessionRecommendation(string patternKey) { return patternKey switch { "session_fixation" => "Regenerate session IDs after authentication to prevent session fixation attacks.", "insecure_session_cookie" => "Set HttpOnly=true and Secure=true for session cookies.", "long_session_timeout" => "Use shorter session timeouts (30-60 minutes) for better security.", "session_without_timeout" => "Configure explicit session timeouts based on your security requirements.", _ => "Implement secure session management with proper timeouts and cookie security flags." }; } /// /// Gets authorization-specific recommendations /// private string GetAuthorizationRecommendation(string patternKey) { return patternKey switch { "missing_authorization" => "Add [Authorize] attribute to actions that require authentication. Use [AllowAnonymous] only when necessary.", "overly_permissive_auth" => "Review [AllowAnonymous] usage. Document why anonymous access is needed.", "role_hardcoded" => "Use configuration or constants for role names instead of hardcoding strings.", "privilege_escalation" => "Always check authorization against the current user context, not just role existence.", _ => "Implement proper authorization with appropriate attributes and user context validation." }; } /// /// Gets password-specific recommendations /// private string GetPasswordRecommendation(string patternKey) { return patternKey switch { "plain_text_password" => "Never store or compare passwords in plain text. Use bcrypt, Argon2, or PBKDF2.", "weak_hash_algorithm" => "Use strong password hashing algorithms like bcrypt, Argon2, or PBKDF2 instead of MD5/SHA1.", "no_salt" => "Always use unique salts for password hashing to prevent rainbow table attacks.", "hardcoded_salt" => "Generate unique, random salts for each password instead of using hardcoded values.", "weak_password_policy" => "Implement strong password policies: minimum 8 characters, complexity requirements.", _ => "Use industry-standard password hashing with salts and implement strong password policies." }; } /// /// Gets description for good practices /// private string GetGoodPracticeDescription(string patternKey) { return patternKey switch { "bcrypt_usage" => "Uses BCrypt for secure password hashing", "argon2_usage" => "Uses Argon2 for secure password hashing", "pbkdf2_usage" => "Uses PBKDF2 for secure password hashing", "secure_jwt" => "Uses secure JWT algorithms (HS256/RS256/ES256)", "jwt_validation" => "Implements proper JWT validation", "authorize_attribute" => "Uses [Authorize] attributes for access control", "https_enforcement" => "Enforces HTTPS for secure communications", "secure_cookies" => "Uses secure cookie settings (HttpOnly, Secure)", "csrf_protection" => "Implements CSRF protection", "rate_limiting" => "Implements rate limiting for authentication", "account_lockout" => "Implements account lockout protection", "password_complexity" => "Enforces password complexity requirements", _ => $"Implements {patternKey} security feature" }; } /// /// Calculates compliance score based on findings /// private int CalculateComplianceScore(AuthenticationAnalysisResults results) { var baseScore = 100; var severityPenalties = new Dictionary { ["Critical"] = 30, ["High"] = 20, ["Medium"] = 10, ["Low"] = 5 }; // Deduct points for authentication issues foreach (var issue in results.AuthenticationIssues) { baseScore -= severityPenalties.GetValueOrDefault(issue.Severity, 10); } // Deduct points for authorization issues foreach (var issue in results.AuthorizationIssues) { baseScore -= severityPenalties.GetValueOrDefault(issue.Severity, 10); } // Add bonus points for good practices (up to 25 points) var bonusPoints = Math.Min(25, results.GoodPractices.Count * 3); baseScore += bonusPoints; return Math.Max(0, Math.Min(100, baseScore)); } } /// /// Results of authentication analysis /// public class AuthenticationAnalysisResults { public string AnalyzedPath { get; set; } public int FilesAnalyzed { get; set; } public List AuthenticationIssues { get; set; } = new List(); public List AuthorizationIssues { get; set; } = new List(); public List GoodPractices { get; set; } = new List(); public List SecurityRecommendations { get; set; } = new List(); public int ComplianceScore { get; set; } public int GetTotalIssues() => AuthenticationIssues.Count + AuthorizationIssues.Count; } /// /// Represents an authentication security issue /// public class AuthenticationIssue { public string Type { get; set; } public string Severity { get; set; } public string Description { get; set; } public string File { get; set; } public int LineNumber { get; set; } public string Code { get; set; } public string Recommendation { get; set; } } /// /// Represents an authorization security issue /// public class AuthorizationIssue { public string Type { get; set; } public string Severity { get; set; } public string Description { get; set; } public string File { get; set; } public int LineNumber { get; set; } public string Code { get; set; } public string Recommendation { get; set; } } }