Segurança de Aplicações .NET
🔐 OAuth 2.0 e OpenID Connect
OAuth 2.0 Flows
Authorization Code Flow
csharp
public class OAuth2Client
{
private readonly HttpClient _httpClient;
private readonly string _clientId;
private readonly string _clientSecret;
public async Task<TokenResponse> GetTokenAsync(string code)
{
var tokenRequest = new TokenRequest
{
GrantType = "authorization_code",
Code = code,
RedirectUri = "https://app.com/callback",
ClientId = _clientId,
ClientSecret = _clientSecret
};
return await _httpClient.PostAsJsonAsync("/token", tokenRequest);
}
}Client Credentials Flow
csharp
public async Task<TokenResponse> GetClientCredentialsTokenAsync()
{
var tokenRequest = new TokenRequest
{
GrantType = "client_credentials",
ClientId = _clientId,
ClientSecret = _clientSecret,
Scope = "api.read api.write"
};
return await _httpClient.PostAsJsonAsync("/token", tokenRequest);
}OpenID Connect
JWT Token Validation
csharp
public class JwtTokenValidator
{
private readonly SecurityKey _signingKey;
private readonly string _issuer;
private readonly string _audience;
public ClaimsPrincipal ValidateToken(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
var validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
ValidateIssuer = true,
ValidIssuer = _issuer,
ValidateAudience = true,
ValidAudience = _audience,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
return tokenHandler.ValidateToken(token, validationParameters, out _);
}
}Identity Providers Integration
Azure AD
csharp
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));
services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireRole("Admin"));
});Auth0
csharp
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://your-domain.auth0.com/";
options.Audience = "https://your-api.com";
});🛡️ OWASP Top 10
1. Broken Access Control
csharp
[Authorize(Roles = "Admin")]
public class AdminController : ControllerBase
{
[HttpGet("users")]
public async Task<IActionResult> GetUsers()
{
var currentUser = User.Identity.Name;
var userRole = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value;
if (userRole != "Admin")
{
return Forbid();
}
return Ok(await _userService.GetAllUsers());
}
}2. Cryptographic Failures
csharp
public class EncryptionService
{
private readonly byte[] _key;
private readonly byte[] _iv;
public string Encrypt(string plainText)
{
using var aes = Aes.Create();
aes.Key = _key;
aes.IV = _iv;
using var encryptor = aes.CreateEncryptor();
using var msEncrypt = new MemoryStream();
using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
using var swEncrypt = new StreamWriter(csEncrypt);
swEncrypt.Write(plainText);
swEncrypt.Close();
return Convert.ToBase64String(msEncrypt.ToArray());
}
}3. Injection
csharp
// SQL Injection Prevention
public async Task<User> GetUserByIdAsync(int id)
{
return await _context.Users
.FirstOrDefaultAsync(u => u.Id == id);
}
// XSS Prevention
public string SanitizeHtml(string input)
{
var sanitizer = new HtmlSanitizer();
return sanitizer.Sanitize(input);
}🔒 Autenticação e Autorização
Custom Authentication Handler
csharp
public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Authorization"))
{
return AuthenticateResult.Fail("Authorization header not found");
}
var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
try
{
var claims = ValidateToken(token);
var identity = new ClaimsIdentity(claims, Scheme.Name);
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return AuthenticateResult.Success(ticket);
}
catch
{
return AuthenticateResult.Fail("Invalid token");
}
}
}Role-Based Authorization
csharp
[Authorize(Roles = "Admin,Manager")]
public class SecureController : ControllerBase
{
[Authorize(Policy = "MinimumAge")]
public IActionResult GetSensitiveData()
{
return Ok("Sensitive data");
}
}
// Custom Policy
services.AddAuthorization(options =>
{
options.AddPolicy("MinimumAge", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
c.Type == "Age" &&
int.Parse(c.Value) >= 18)));
});🔐 Secrets Management
Azure Key Vault
csharp
public class KeyVaultService
{
private readonly SecretClient _secretClient;
public async Task<string> GetSecretAsync(string secretName)
{
var secret = await _secretClient.GetSecretAsync(secretName);
return secret.Value.Value;
}
}
// Configuration
services.AddAzureClients(builder =>
{
builder.AddSecretClient(new Uri("https://your-keyvault.vault.azure.net/"));
});Environment Variables
csharp
// appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=MyDb;"
}
}
// Program.cs
builder.Configuration.AddEnvironmentVariables();📊 Security Headers
Middleware Configuration
csharp
app.Use(async (context, next) =>
{
context.Response.Headers.Add("X-Frame-Options", "DENY");
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");
context.Response.Headers.Add("X-XSS-Protection", "1; mode=block");
context.Response.Headers.Add("Referrer-Policy", "strict-origin-when-cross-origin");
context.Response.Headers.Add("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'");
await next();
});🧪 Security Testing
Unit Tests
csharp
[Test]
public async Task GetUser_WithInvalidToken_ReturnsUnauthorized()
{
var controller = new UserController(_userService);
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext()
};
var result = await controller.GetUser(1);
Assert.IsInstanceOf<UnauthorizedResult>(result);
}Integration Tests
csharp
[Test]
public async Task AdminEndpoint_WithUserRole_ReturnsForbidden()
{
var client = _factory.CreateClient();
var token = await GetUserTokenAsync(client);
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var response = await client.GetAsync("/admin/users");
Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode);
}📋 Checklist de Segurança
- [ ] Implementar HTTPS em produção
- [ ] Configurar headers de segurança
- [ ] Validar todas as entradas do usuário
- [ ] Implementar rate limiting
- [ ] Usar autenticação forte (OAuth 2.0/OpenID Connect)
- [ ] Implementar autorização baseada em roles
- [ ] Criptografar dados sensíveis
- [ ] Gerenciar secrets de forma segura
- [ ] Implementar logging de auditoria
- [ ] Realizar testes de segurança regulares
- [ ] Manter dependências atualizadas
- [ ] Implementar CORS adequadamente
- [ ] Configurar backup e recuperação
- [ ] Documentar políticas de segurança