From 7d9efbcb9068ceec3f548e34c6ff9ff9d3a8d904 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 14 Dec 2019 03:15:33 +0000 Subject: [PATCH] Add authentication to metrics. --- DiscImageChef.Server/BasicAuthMiddleware.cs | 71 +++++++++++++++++++++ DiscImageChef.Server/Startup.cs | 8 ++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 DiscImageChef.Server/BasicAuthMiddleware.cs diff --git a/DiscImageChef.Server/BasicAuthMiddleware.cs b/DiscImageChef.Server/BasicAuthMiddleware.cs new file mode 100644 index 00000000..8f181469 --- /dev/null +++ b/DiscImageChef.Server/BasicAuthMiddleware.cs @@ -0,0 +1,71 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Johan Boström. All rights reserved. +// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace DiscImageChef.Server +{ + public class BasicAuthMiddleware + { + readonly RequestDelegate next; + readonly string realm; + + public BasicAuthMiddleware(RequestDelegate next, string realm) + { + this.next = next; + this.realm = realm; + } + + public async Task Invoke(HttpContext context) + { + string authHeader = context.Request.Headers["Authorization"]; + + if(authHeader != null && + authHeader.StartsWith("Basic ")) + { + // Get the encoded username and password + string encodedUsernamePassword = + authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim(); + + // Decode from Base64 to string + string decodedUsernamePassword = + Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword)); + + // Split username and password + string username = decodedUsernamePassword.Split(':', 2)[0]; + string password = decodedUsernamePassword.Split(':', 2)[1]; + + // Check if login is correct + if(IsAuthorized(username, password)) + { + await next.Invoke(context); + + return; + } + } + + // Return authentication type (causes browser to show login dialog) + context.Response.Headers["WWW-Authenticate"] = "Basic"; + + // Add realm if it is not null + if(!string.IsNullOrWhiteSpace(realm)) + { + context.Response.Headers["WWW-Authenticate"] += $" realm=\"{realm}\""; + } + + // Return unauthorized + context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; + } + + // Make your own implementation of this + // Check that username and password are correct + public bool IsAuthorized(string username, string password) => + username.Equals("User1", StringComparison.InvariantCultureIgnoreCase) && password.Equals("SecretPassword!"); + } +} \ No newline at end of file diff --git a/DiscImageChef.Server/Startup.cs b/DiscImageChef.Server/Startup.cs index c0e8796e..b83b014b 100644 --- a/DiscImageChef.Server/Startup.cs +++ b/DiscImageChef.Server/Startup.cs @@ -71,7 +71,13 @@ namespace DiscImageChef.Server endpoints.MapRazorPages(); }); - app.UseMetricServer(); + app.Map("/metrics", metricsApp => + { + metricsApp.UseMiddleware("DiscImageChef"); + + // We already specified URL prefix in .Map() above, no need to specify it again here. + metricsApp.UseMetricServer(""); + }); } } } \ No newline at end of file