DEV Community

Cover image for How to Secure Your API Against Unauthorized Requests
TiagoMabango
TiagoMabango

Posted on

How to Secure Your API Against Unauthorized Requests

APIs are critical components of modern applications, enabling communication between different systems. However, they are also frequent targets for unauthorized access and abuse. Securing your API requires a layered approach that combines CORS validation, strong authentication mechanisms, and robust monitoring. In this article, we will cover several strategies to protect your API and ensure it is only accessible by trusted clients.


1. Configure CORS Properly

Cross-Origin Resource Sharing (CORS) is an essential layer of security that determines which origins are allowed to interact with your API. Configuring CORS correctly is vital to prevent unauthorized access.

Example in ASP.NET Core:

builder.Services.AddCors(options =>
{
    options.AddPolicy("RestrictOrigins", policy =>
    {
        policy.WithOrigins("https://mywebsite.com", "https://trustedpartner.com") // Allowed origins
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});

// Apply the CORS policy
app.UseCors("RestrictOrigins");
Enter fullscreen mode Exit fullscreen mode

Key Rules:

  • Avoid AllowAnyOrigin: Allowing all origins opens your API to vulnerabilities.
  • Do not use SetIsOriginAllowed(_ => true): This bypasses origin validation entirely.
  • Limit methods and headers: Restrict AllowAnyMethod and AllowAnyHeader to what is strictly necessary.

2. Implement Authentication and Authorization

Authentication ensures that only authorized users or systems can access your endpoints. A common approach is using JSON Web Tokens (JWT).

Steps to Implement JWT:

  1. On the client side, send the JWT in the request header:
   Authorization: Bearer <your-jwt-token>
Enter fullscreen mode Exit fullscreen mode
  1. On the server side, validate the token:
   app.UseAuthentication();
   app.UseAuthorization();
Enter fullscreen mode Exit fullscreen mode

Example Configuration in ASP.NET Core:

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "https://mywebsite.com",
            ValidAudience = "https://mywebsite.com",
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("secret-key"))
        };
    });
Enter fullscreen mode Exit fullscreen mode

3. Validate the Origin Header Explicitly

Even with CORS configured, you can add an extra layer of security by manually validating the Origin header in server-side middleware.

Example:

app.Use(async (context, next) =>
{
    var origin = context.Request.Headers["Origin"].ToString();
    var allowedOrigins = new[] { "https://mywebsite.com", "https://trustedpartner.com" };

    if (!string.IsNullOrEmpty(origin) && !allowedOrigins.Contains(origin))
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        await context.Response.WriteAsync("Origin not allowed.");
        return;
    }

    await next();
});
Enter fullscreen mode Exit fullscreen mode

4. Block Suspicious IPs

Filter and block requests from known malicious IP addresses to reduce attack vectors.

Example Middleware:

app.Use(async (context, next) =>
{
    var clientIp = context.Connection.RemoteIpAddress;
    var blockedIps = new[] { "192.168.1.100", "10.0.0.50" };

    if (blockedIps.Contains(clientIp.ToString()))
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        await context.Response.WriteAsync("Blocked IP.");
        return;
    }

    await next();
});
Enter fullscreen mode Exit fullscreen mode

5. Implement Rate Limiting

Protect your API from abuse and brute force attacks by limiting the number of requests a client can make.

Example with ASP.NET Core:

Install the package:

dotnet add package AspNetCoreRateLimit
Enter fullscreen mode Exit fullscreen mode

Configure rate limiting:

builder.Services.AddMemoryCache();
builder.Services.Configure<IpRateLimitOptions>(options =>
{
    options.GeneralRules = new List<RateLimitRule>
    {
        new RateLimitRule
        {
            Endpoint = "*",
            Limit = 100, // Request limit
            Period = "1m" // Per minute
        }
    };
});

builder.Services.AddInMemoryRateLimiting();
app.UseIpRateLimiting();
Enter fullscreen mode Exit fullscreen mode

6. Use HTTPS for All Connections

Ensure secure communication between clients and your API by enforcing HTTPS.

Configure HTTPS in ASP.NET Core:

webBuilder.UseKestrel()
          .UseHttps();
Enter fullscreen mode Exit fullscreen mode

Redirect HTTP traffic to HTTPS:

app.UseHttpsRedirection();
Enter fullscreen mode Exit fullscreen mode

7. Monitor and Log Requests

Implement logging to detect unusual patterns, such as multiple requests from unknown origins.

Example:

app.Use(async (context, next) =>
{
    var origin = context.Request.Headers["Origin"].ToString();
    Console.WriteLine($"Request from origin: {origin}");
    await next();
});
Enter fullscreen mode Exit fullscreen mode

Use tools like Application Insights, Serilog, or Elastic Stack for comprehensive monitoring.


8. Avoid Detailed Error Responses

Do not expose sensitive information in error messages, as it can aid attackers.

Example:

app.UseExceptionHandler("/error"); // Redirect errors to a secure page
Enter fullscreen mode Exit fullscreen mode

Conclusion

Securing your API against unauthorized requests requires a multi-layered approach:

  1. Configure CORS properly.
  2. Validate origins and headers explicitly.
  3. Implement authentication and rate limiting.
  4. Use HTTPS and monitor traffic.

By following these best practices, you can significantly reduce the risk of unauthorized access and ensure that only trusted clients can interact with your API.

Top comments (4)

Collapse
 
marciopedrocomba profile image
marciopedrocomba • Edited

Excelente material mas gostaria de adicionar que configurar medidas de segurança, como rate limiting por exemplo, no proxy em vez do servidor de aplicação (como .Net no exemplo) oferece várias vantagens:

Melhor Performance: O proxy é otimizado para lidar com grandes volumes de requisições, aliviando a carga do servidor de aplicação.

Controle Centralizado: Permite gerenciar e aplicar regras de segurança de forma consistente em sistemas distribuídos.

Maior Segurança: Bloqueia tráfego excessivo ou malicioso antes que alcance o servidor, reduzindo vulnerabilidades.

Facilidade de Configuração: Ferramentas como Nginx oferecem módulos prontos, evitando a necessidade de escrever lógica personalizada.

Políticas Avançadas: Suporte a limites dinâmicos, baseados em IP, cabeçalhos ou chaves de API, além de permitir "bursts" temporários.

Escalabilidade: Ajuda a manter o sistema eficiente ao adicionar novos servidores, sem necessidade de sincronizar estados.

Código Mais Limpo: A separação de responsabilidades mantém a lógica de segurança fora do código da aplicação.

Embora a aplicação também possa implementar medidas específicas, como limites baseados em usuários ou lógica de negócios, o uso de um proxy é mais eficiente, seguro e fácil de manter.

Collapse
 
tiagomabango profile image
TiagoMabango

O uso do proxy é uma abordagem muito boa, mas devemos sempre prestar atenção natureza do projecto.

Se for um projecto que tem a margem que crescer em cada ano, a abordagem mais acertiva é usar proxy mas em sistema em ecossistemas pequeno, usar proxy acaba não batendo muito certo.

Muito obrigado pela contribuição, @marciopedrocomba !

Collapse
 
marciopedrocomba profile image
marciopedrocomba • Edited

Certo @tiagomabango mas vale lembrar que hoje em dia usar um proxy é muito barato e fora as questões de segurança você tem ganho de alto throughput, baixa latência, tens a questão de lidar com requisições em paralelo sem sobre carregar a tua aplicação, cache e muito mais. Então usar um proxy independente do tamanho do projecto é um must nos dias de hoje

Thread Thread
 
tiagomabango profile image
TiagoMabango

@marciopedrocomba, um ponto muito importante!.

Obrigado, tomei notado...