diff --git a/Newsbot.Collector.Api/Middleware/ApiKeyAuthentication.cs b/Newsbot.Collector.Api/Middleware/ApiKeyAuthentication.cs new file mode 100644 index 0000000..9837003 --- /dev/null +++ b/Newsbot.Collector.Api/Middleware/ApiKeyAuthentication.cs @@ -0,0 +1,41 @@ +namespace Newsbot.Collector.Api.Authentication; + +public class ApiKeyAuthAuthentication +{ + public const string HeaderApiKey = "x-api-key"; + + private readonly RequestDelegate _next; + + public ApiKeyAuthAuthentication(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + if (!context.Request.Headers.TryGetValue(HeaderApiKey, out var extractedApiKey)) + { + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Api key was not provided."); + return; + } + + var appSettings = context.RequestServices.GetRequiredService(); + + var keys = appSettings.GetSection("AuthKeys").Get(); + keys ??= Array.Empty(); + //var apiKey = appSettings.GetValue>("AuthKeys") ?? ""; + + foreach (var apiKey in keys) + { + if (apiKey.Equals(extractedApiKey)) + { + await _next(context); + return; + } + } + + context.Response.StatusCode = 401; + await context.Response.WriteAsync("Unauthorized"); + } +} \ No newline at end of file diff --git a/Newsbot.Collector.Api/Program.cs b/Newsbot.Collector.Api/Program.cs index 3e1192b..04c1b6c 100644 --- a/Newsbot.Collector.Api/Program.cs +++ b/Newsbot.Collector.Api/Program.cs @@ -2,7 +2,9 @@ using Hangfire; using Hangfire.MemoryStorage; using HealthChecks.UI.Client; using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.OpenApi.Models; using Newsbot.Collector.Api; +using Newsbot.Collector.Api.Authentication; using Newsbot.Collector.Domain.Consts; using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models.Config; @@ -42,6 +44,33 @@ builder.Services.Configure(config.GetSection(ConfigSectio builder.Services.Configure(config.GetSection(ConfigSectionsConst.Youtube)); //builder.Services.Configure< +builder.Services.AddSwaggerGen(cfg => +{ + cfg.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme + { + Description = "The API key to access the API", + Type = SecuritySchemeType.ApiKey, + Name = "x-api-key", + In = ParameterLocation.Header, + Scheme = "ApiKeyScheme" + }); + + var scheme = new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + }, + In = ParameterLocation.Header + }; + var requirement = new OpenApiSecurityRequirement + { + { scheme, new List() } + }; + cfg.AddSecurityRequirement(requirement); +}); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -58,6 +87,8 @@ BackgroundJobs.SetupRecurringJobs(config); app.UseAuthorization(); +app.UseMiddleware(); + app.MapHealthChecks("/health", new HealthCheckOptions { Predicate = _ => true,