From a1c512426955693cfb31713280dfb8d3c4da7504 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Mon, 25 Jun 2018 12:48:11 +0100 Subject: [PATCH] Swap out the old way of validating the API key with a real middlewear this time. --- src/Ombi/ApiKeyMiddlewear.cs | 105 ++++++++++++++++++++++++++++++++++ src/Ombi/Startup.cs | 3 +- src/Ombi/StartupExtensions.cs | 40 ------------- 3 files changed, 107 insertions(+), 41 deletions(-) create mode 100644 src/Ombi/ApiKeyMiddlewear.cs diff --git a/src/Ombi/ApiKeyMiddlewear.cs b/src/Ombi/ApiKeyMiddlewear.cs new file mode 100644 index 000000000..d30ba0d21 --- /dev/null +++ b/src/Ombi/ApiKeyMiddlewear.cs @@ -0,0 +1,105 @@ +using System; +using System.Linq; +using System.Net; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Settings.Settings.Models; + +namespace Ombi +{ + public class ApiKeyMiddlewear + { + public ApiKeyMiddlewear(RequestDelegate next, ISettingsService repo, OmbiUserManager um) + { + _next = next; + _repo = repo; + _userManager = um; + } + private readonly RequestDelegate _next; + private readonly ISettingsService _repo; + private readonly OmbiUserManager _userManager; + + public async Task Invoke(HttpContext context) + { + if (context.Request.Path.StartsWithSegments(new PathString("/api"))) + { + //Let's check if this is an API Call + if (context.Request.Headers.Keys.Contains("ApiKey")) + { + // validate the supplied API key + // Validate it + var headerKey = context.Request.Headers["ApiKey"].FirstOrDefault(); + await ValidateApiKey(context, _next, headerKey); + } + else if (context.Request.Query.ContainsKey("apikey")) + { + if (context.Request.Query.TryGetValue("apikey", out var queryKey)) + { + await ValidateApiKey(context, _next, queryKey); + } + } + // User access token used by the mobile app + else if (context.Request.Headers["UserAccessToken"].Any()) + { + var headerKey = context.Request.Headers["UserAccessToken"].FirstOrDefault(); + await ValidateUserAccessToken(context, _next, headerKey); + } + else + { + await _next.Invoke(context); + } + } + else + { + await _next.Invoke(context); + } + } + + private async Task ValidateUserAccessToken(HttpContext context, RequestDelegate next, string key) + { + if (string.IsNullOrEmpty(key)) + { + await context.Response.WriteAsync("Invalid User Access Token"); + return; + } + + var user = await _userManager.Users.FirstOrDefaultAsync(x => x.UserAccessToken == key); + if (user == null) + { + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + await context.Response.WriteAsync("Invalid User Access Token"); + } + else + { + + var identity = new GenericIdentity(user.UserName); + var roles = await _userManager.GetRolesAsync(user); + var principal = new GenericPrincipal(identity, roles.ToArray()); + context.User = principal; + await next.Invoke(context); + } + } + + private async Task ValidateApiKey(HttpContext context, RequestDelegate next, string key) + { + var ombiSettings = await _repo.GetSettingsAsync(); + var valid = ombiSettings.ApiKey.Equals(key, StringComparison.CurrentCultureIgnoreCase); + if (!valid) + { + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + await context.Response.WriteAsync("Invalid API Key"); + } + else + { + var identity = new GenericIdentity("API"); + var principal = new GenericPrincipal(identity, new[] { "Admin", "ApiUser" }); + context.User = principal; + await next.Invoke(context); + } + } + } +} \ No newline at end of file diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 8037a3021..1daaad05b 100644 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -217,8 +217,9 @@ namespace Ombi app.UseAuthentication(); app.UseMiddleware(); + app.UseMiddleware(); - app.ApiKeyMiddlewear(app.ApplicationServices); + //app.ApiKeyMiddlewear(app.ApplicationServices); app.UseSwagger(); app.UseSwaggerUI(c => { diff --git a/src/Ombi/StartupExtensions.cs b/src/Ombi/StartupExtensions.cs index e4dae18e4..5c6355bb0 100644 --- a/src/Ombi/StartupExtensions.cs +++ b/src/Ombi/StartupExtensions.cs @@ -115,46 +115,6 @@ namespace Ombi }); } - - public static void ApiKeyMiddlewear(this IApplicationBuilder app, IServiceProvider serviceProvider) - { - app.Use(async (context, next) => - { - if (context.Request.Path.StartsWithSegments(new PathString("/api"))) - { - // Let's check if this is an API Call - if (context.Request.Headers["ApiKey"].Any()) - { - // validate the supplied API key - // Validate it - var headerKey = context.Request.Headers["ApiKey"].FirstOrDefault(); - await ValidateApiKey(serviceProvider, context, next, headerKey); - } - else if (context.Request.Query.ContainsKey("apikey")) - { - if (context.Request.Query.TryGetValue("apikey", out var queryKey)) - { - await ValidateApiKey(serviceProvider, context, next, queryKey); - } - } - // User access token used by the mobile app - else if (context.Request.Headers["UserAccessToken"].Any()) - { - var headerKey = context.Request.Headers["UserAccessToken"].FirstOrDefault(); - await ValidateUserAccessToken(serviceProvider, context, next, headerKey); - } - else - { - await next(); - } - } - else - { - await next(); - } - }); - } - private static async Task ValidateUserAccessToken(IServiceProvider serviceProvider, HttpContext context, Func next, string key) { if (key.IsNullOrEmpty())