Resumen

La autenticación es la primera barrera de seguridad en una API. Aquí verás cómo activar autenticación básica con usuario y contraseña codificados en Base64 usando un middleware en .NET, cómo evitar errores 401 al probar con Swagger y Postman, y qué ajustes aplicar en OpenAPI para enviar credenciales desde la documentación. Todo con un enfoque práctico y directo.

¿Cómo implementar autenticación básica con middleware en .NET?

La idea central es crear una clase llamada BasicAuthMiddleware.cs que intercepte cada request, valide el encabezado de autorización y, si las credenciales son correctas, permita continuar con el siguiente componente del pipeline.

  • El middleware controla el acceso a los endpoints mediante usuario y contraseña en Base64.
  • Se excluyen rutas de documentación como Swagger, Scalar y OpenAPI para poder usar la interfaz de pruebas.
  • Si faltan credenciales o no coinciden, se responde con 401 (Unauthorized) según el patrón REST.
  • Mejora sugerida: mover usuario y contraseña a appsettings y considerar cifrado, en lugar de “quemarlas” en el código.

¿Qué hace la clase BasicAuthMiddleware.cs?

La clase define dos valores para usuario y contraseña, recibe el request delegate (el next) y, en su InvokeAsync, ejecuta la lógica de autenticación. Si pasa, llama al siguiente middleware; si no, devuelve 401.

// BasicAuthMiddleware.cs (estructura simplificada)
public class BasicAuthMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _user = "<usuario>";
    private readonly string _password = "<contraseña>";

    public BasicAuthMiddleware(RequestDelegate next) => _next = next;

    public async Task InvokeAsync(HttpContext context)
    {
        var path = context.Request.Path.Value ?? string.Empty;
        // Omitir Swagger/Scalar/OpenAPI para poder usar la documentación
        if (path.Contains("swagger", StringComparison.OrdinalIgnoreCase) ||
            path.Contains("scalar", StringComparison.OrdinalIgnoreCase) ||
            path.Contains("openapi", StringComparison.OrdinalIgnoreCase))
        {
            await _next(context);
            return;
        }

        if (!context.Request.Headers.TryGetValue("Authorization", out var header) ||
            !header.ToString().StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            return;
        }

        var token = header.ToString().Substring("Basic ".Length).Trim();
        var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(token));
        var parts = decoded.Split(':', 2);
        var user = parts.ElementAtOrDefault(0);
        var pass = parts.ElementAtOrDefault(1);

        if (user == _user && pass == _password)
            await _next(context);
        else
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
    }
}

public static class BasicAuthExtensions
{
    public static IApplicationBuilder UseBasicAuth(this IApplicationBuilder app)
        => app.UseMiddleware<BasicAuthMiddleware>();
}

¿En qué orden va en el pipeline de middlewares?

La autenticación debe ejecutarse antes de la autorización. Se registra el middleware con el método de extensión para asegurar el orden correcto.

// Program.cs (fragmento ilustrativo)
var app = builder.Build();

// Primero autenticación
app.UseBasicAuth();

// Luego autorización si aplica
// app.UseAuthorization();

app.Run();

¿Cómo probar con Swagger y Postman sin errores 401?

Inicialmente, al usar el botón Try it out en Swagger, verás 401 porque la UI no envía credenciales. En Postman, selecciona Basic Auth en Authorization, ingresa el usuario y la contraseña, y la API responde correctamente. En el ejemplo, se usaron credenciales “Plaxy” y “12345” para validar que la autenticación funciona.

  • En Postman, usa Basic Auth y envía usuario y contraseña.
  • En Swagger, habilita el botón Authorize añadiendo el esquema de seguridad basic en OpenAPI.
  • Marca el esquema como requirement para que el encabezado Authorization se incluya en los requests.

¿Cómo habilitar Basic Auth en Swagger con OpenAPI?

Se agrega una definición de seguridad tipo http con esquema "basic" y un requirement para que Swagger envíe el encabezado en cada request.

// Program.cs (configuración de Swagger/OpenAPI)
builder.Services.AddSwaggerGen(c =>
{
    c.AddSecurityDefinition("basic", new OpenApiSecurityScheme
    {
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        Scheme = "basic",
        In = ParameterLocation.Header,
        Description = "Usuario y contraseña con *Basic Auth*."
    });

    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "basic"
                }
            },
            Array.Empty<string>()
        }
    });
});

¿Qué buenas prácticas y siguientes pasos recomienda el instructor?

Aunque este enfoque brinda un mínimo de seguridad, no es recomendado para producción.

  • Para producción, usar JSON Web Token, OAuth2, Identity, Microsoft Entra o Cognito.
  • Centralizar credenciales en appsettings y evaluar cifrado en reposo.
  • Verificar que todos los endpoints devuelvan 401 si no se envían credenciales, ya sea desde Scalar, Swagger o Postman.
  • Añadir soporte similar en Scalar y, si se desea, precargar usuario y contraseña para agilizar pruebas.
  • Mantener el orden: autenticación antes de autorización en el pipeline.

¿Te quedó alguna duda o quieres compartir tu implementación con Basic Auth y Swagger? Comenta tus preguntas y hallazgos para seguir mejorando juntos.