Skip to content

Security Features

GrydAuth includes enterprise-grade security features to protect your application against common threats.

Rate Limiting

Protect endpoints against brute-force attacks and abuse.

Configuration

csharp
builder.Services.AddGrydAuth(options =>
{
    options.RateLimiting.Enabled = true;
    
    // Global rate limit
    options.RateLimiting.GlobalLimit = new RateLimitConfig
    {
        PermitLimit = 1000,
        Window = TimeSpan.FromMinutes(1)
    };
    
    // Auth endpoints (stricter)
    options.RateLimiting.AuthEndpointsLimit = new RateLimitConfig
    {
        PermitLimit = 10,
        Window = TimeSpan.FromMinutes(1)
    };
    
    // Per-user limits
    options.RateLimiting.PerUserLimit = new RateLimitConfig
    {
        PermitLimit = 100,
        Window = TimeSpan.FromMinutes(1)
    };
});

Custom Rate Limit Policies

csharp
builder.Services.AddRateLimiter(options =>
{
    options.AddPolicy("sensitive-operations", context =>
        RateLimitPartition.GetFixedWindowLimiter(
            partitionKey: context.User.Identity?.Name ?? context.Connection.RemoteIpAddress?.ToString(),
            factory: _ => new FixedWindowRateLimiterOptions
            {
                PermitLimit = 5,
                Window = TimeSpan.FromMinutes(15)
            }));
});

// Usage
[EnableRateLimiting("sensitive-operations")]
public IActionResult DeleteAccount() { ... }

Audit Logging

Track all security-related events.

Enable Audit Logging

csharp
builder.Services.AddGrydAuth(options =>
{
    options.AuditLogging.Enabled = true;
    options.AuditLogging.LogSuccessfulLogins = true;
    options.AuditLogging.LogFailedLogins = true;
    options.AuditLogging.LogPermissionChanges = true;
    options.AuditLogging.LogTokenOperations = true;
    options.AuditLogging.RetentionDays = 90;
});

Audit Events

EventDescription
UserLoginSuccessful login
UserLoginFailedFailed login attempt
UserLogoutUser logout
UserRegisteredNew user registration
PasswordChangedPassword change
PasswordResetRequestedPassword reset request
RoleAssignedRole assigned to user
RoleRevokedRole removed from user
PermissionGrantedPermission granted
PermissionRevokedPermission revoked
TokenRefreshedToken refreshed
TokenRevokedToken manually revoked
AccountLockedAccount locked due to failed attempts
AccountUnlockedAccount unlocked

Querying Audit Logs

http
GET /api/audit-logs?userId=550e8400-e29b-41d4-a716-446655440000&eventType=UserLogin&from=2026-01-01&to=2026-01-31
Authorization: Bearer {admin-token}

Response:

json
{
  "items": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "userId": "550e8400-e29b-41d4-a716-446655440000",
      "eventType": "UserLogin",
      "ipAddress": "192.168.1.100",
      "userAgent": "Mozilla/5.0...",
      "timestamp": "2026-01-15T10:30:00Z",
      "success": true,
      "metadata": {
        "method": "Password",
        "mfaUsed": false
      }
    }
  ],
  "totalCount": 42,
  "page": 1,
  "pageSize": 20
}

Custom Audit Events

csharp
public class OrderService
{
    private readonly IAuditLogger _auditLogger;
    
    public async Task<Order> CreateOrderAsync(CreateOrderRequest request)
    {
        var order = await _orderRepository.CreateAsync(request);
        
        await _auditLogger.LogAsync(new AuditEvent
        {
            EventType = "OrderCreated",
            EntityType = "Order",
            EntityId = order.Id.ToString(),
            Metadata = new Dictionary<string, object>
            {
                ["amount"] = order.TotalAmount,
                ["items"] = order.Items.Count
            }
        });
        
        return order;
    }
}

Geo-Location Tracking

Track login locations and detect suspicious activity.

Configuration

csharp
builder.Services.AddGrydAuth(options =>
{
    options.GeoLocation.Enabled = true;
    options.GeoLocation.Provider = GeoLocationProvider.MaxMind;
    options.GeoLocation.BlockSuspiciousLogins = true;
    options.GeoLocation.TrustedCountries = ["US", "CA", "GB", "DE"];
});

MaxMind GeoIP Setup

csharp
builder.Services.AddMaxMindGeoIp(options =>
{
    options.AccountId = Configuration["MaxMind:AccountId"]!;
    options.LicenseKey = Configuration["MaxMind:LicenseKey"]!;
    options.DatabasePath = Path.Combine(AppContext.BaseDirectory, "GeoLite2-City.mmdb");
    options.AutoUpdate = true;
    options.UpdateIntervalDays = 7;
});

Location-Based Alerts

csharp
public class LocationSecurityHandler : ILoginEventHandler
{
    private readonly INotificationService _notifications;
    private readonly IGeoLocationService _geoLocation;
    
    public async Task HandleLoginAsync(LoginEvent loginEvent)
    {
        var currentLocation = await _geoLocation.GetLocationAsync(loginEvent.IpAddress);
        var lastLocation = await GetLastLoginLocationAsync(loginEvent.UserId);
        
        if (lastLocation != null && IsUnusualLocation(currentLocation, lastLocation))
        {
            await _notifications.SendAsync(
                loginEvent.UserId,
                "New Login Location",
                $"We detected a login from {currentLocation.City}, {currentLocation.Country}. " +
                "If this wasn't you, please change your password immediately."
            );
        }
    }
    
    private bool IsUnusualLocation(GeoLocation current, GeoLocation last)
    {
        // Check if locations are suspiciously far apart for the time elapsed
        var distance = CalculateDistance(current, last);
        var timeElapsed = current.Timestamp - last.Timestamp;
        var maxPossibleSpeed = 1000; // km/h (roughly commercial airline speed)
        
        return distance / timeElapsed.TotalHours > maxPossibleSpeed;
    }
}

Token Security

Token Invalidation

csharp
// Invalidate specific token
await _tokenService.RevokeTokenAsync(refreshToken);

// Invalidate all user tokens
await _tokenService.RevokeAllUserTokensAsync(userId);

// Invalidate with reason
await _tokenService.RevokeTokenAsync(refreshToken, new RevocationReason
{
    Type = RevocationType.SecurityConcern,
    Description = "Suspicious activity detected"
});

Token Versioning

GrydAuth uses token versioning to invalidate tokens instantly:

csharp
public class User : AggregateRoot<Guid>
{
    public long TokenVersion { get; private set; } = 1;
    
    public void IncrementTokenVersion()
    {
        TokenVersion++;
        AddDomainEvent(new TokensInvalidatedEvent(Id, TokenVersion));
    }
}

All tokens issued before the current version are automatically rejected.

Blacklist Caching

csharp
builder.Services.AddGrydAuth(options =>
{
    options.TokenBlacklist.Enabled = true;
    options.TokenBlacklist.CacheProvider = BlacklistCacheProvider.Redis;
    options.TokenBlacklist.CacheDuration = TimeSpan.FromDays(7);
});

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
    options.InstanceName = "GrydAuth:";
});

Security Headers

GrydAuth automatically adds security headers:

csharp
app.UseGrydAuth(); // Adds security middleware

// Headers added:
// X-Content-Type-Options: nosniff
// X-Frame-Options: DENY
// X-XSS-Protection: 1; mode=block
// Referrer-Policy: strict-origin-when-cross-origin
// Content-Security-Policy: default-src 'self'

Custom Security Headers

csharp
builder.Services.AddGrydAuth(options =>
{
    options.SecurityHeaders.EnableHSTS = true;
    options.SecurityHeaders.HSTSMaxAge = TimeSpan.FromDays(365);
    options.SecurityHeaders.IncludeSubDomains = true;
    options.SecurityHeaders.CustomHeaders = new Dictionary<string, string>
    {
        ["Permissions-Policy"] = "geolocation=(), microphone=(), camera=()"
    };
});

Input Validation

Automatic Sanitization

csharp
builder.Services.AddGrydAuth(options =>
{
    options.InputValidation.SanitizeHtml = true;
    options.InputValidation.PreventSqlInjection = true;
    options.InputValidation.MaxRequestBodySize = 1024 * 1024; // 1MB
});

Request Validation

csharp
public class LoginRequestValidator : AbstractValidator<LoginRequest>
{
    public LoginRequestValidator()
    {
        RuleFor(x => x.Email)
            .NotEmpty()
            .EmailAddress()
            .MaximumLength(256);
        
        RuleFor(x => x.Password)
            .NotEmpty()
            .MinimumLength(8)
            .MaximumLength(128)
            .Must(NotContainSqlInjection).WithMessage("Invalid characters detected");
    }
    
    private bool NotContainSqlInjection(string password)
    {
        var sqlPatterns = new[] { "'", "--", ";", "/*", "*/", "xp_" };
        return !sqlPatterns.Any(p => password.Contains(p, StringComparison.OrdinalIgnoreCase));
    }
}

CORS Configuration

csharp
builder.Services.AddCors(options =>
{
    options.AddPolicy("GrydAuthPolicy", policy =>
    {
        policy
            .WithOrigins(
                "https://yourapp.com",
                "https://admin.yourapp.com"
            )
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials()
            .SetPreflightMaxAge(TimeSpan.FromMinutes(10));
    });
});

app.UseCors("GrydAuthPolicy");

Encryption

Data Encryption

csharp
builder.Services.AddGrydAuth(options =>
{
    options.Encryption.EncryptSensitiveData = true;
    options.Encryption.Algorithm = EncryptionAlgorithm.AES256;
    options.Encryption.KeyVaultUrl = Configuration["Azure:KeyVaultUrl"];
});

Password Hashing

GrydAuth uses bcrypt for password hashing:

csharp
builder.Services.AddGrydAuth(options =>
{
    options.PasswordHashing.Algorithm = HashingAlgorithm.BCrypt;
    options.PasswordHashing.WorkFactor = 12; // Higher = more secure but slower
});

Security Monitoring

Health Checks

csharp
builder.Services.AddHealthChecks()
    .AddGrydAuthHealthChecks();

app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});

Security Metrics

csharp
builder.Services.AddGrydAuth(options =>
{
    options.Metrics.Enabled = true;
    options.Metrics.Provider = MetricsProvider.Prometheus;
});

// Metrics exposed:
// gryd_auth_login_attempts_total
// gryd_auth_login_failures_total
// gryd_auth_tokens_issued_total
// gryd_auth_tokens_revoked_total
// gryd_auth_active_sessions_current

Security Checklist

Before going to production, ensure:

  • [ ] JWT secret is stored in secure vault (not appsettings.json)
  • [ ] HTTPS is enforced everywhere
  • [ ] Rate limiting is enabled for auth endpoints
  • [ ] Audit logging is enabled
  • [ ] Password policy meets requirements
  • [ ] Token expiration times are appropriate
  • [ ] CORS is properly configured
  • [ ] Security headers are enabled
  • [ ] Database connections are encrypted (SSL/TLS)
  • [ ] Sensitive data is encrypted at rest
  • [ ] Regular security audits are scheduled

Released under the MIT License.