diff --git a/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj b/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj
index 191b0d1..8aeae5d 100644
--- a/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj
+++ b/AMWD.Common.AspNetCore/AMWD.Common.AspNetCore.csproj
@@ -35,30 +35,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/AMWD.Common.AspNetCore/AuthenticationHandler/BasicAuthenticationHandler.cs b/AMWD.Common.AspNetCore/AuthenticationHandler/BasicAuthenticationHandler.cs
new file mode 100644
index 0000000..22634dc
--- /dev/null
+++ b/AMWD.Common.AspNetCore/AuthenticationHandler/BasicAuthenticationHandler.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Net.Http.Headers;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Microsoft.AspNetCore.Authentication
+{
+ ///
+ /// Implements the for Basic Authentication.
+ ///
+ public class BasicAuthenticationHandler : AuthenticationHandler
+ {
+ private readonly ILogger logger;
+ private readonly IBasicAuthenticationValidator validator;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The authentication scheme options.
+ /// The logger factory.
+ /// The URL encoder.
+ /// The system clock.
+ /// An basic autentication validator implementation.
+ public BasicAuthenticationHandler(IOptionsMonitor options, ILoggerFactory loggerFactory, UrlEncoder encoder, ISystemClock clock, IBasicAuthenticationValidator validator)
+ : base(options, loggerFactory, encoder, clock)
+ {
+ logger = loggerFactory.CreateLogger();
+ this.validator = validator;
+ }
+
+ ///
+ protected override async Task HandleAuthenticateAsync()
+ {
+ var endpoint = Context.GetEndpoint();
+ if (endpoint?.Metadata?.GetMetadata() != null)
+ return AuthenticateResult.NoResult();
+
+ if (!Request.Headers.ContainsKey("Authorization"))
+ return AuthenticateResult.Fail("Authorization header missing");
+
+ ClaimsPrincipal principal;
+ try
+ {
+ var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
+ string plain = Encoding.UTF8.GetString(Convert.FromBase64String(authHeader.Parameter));
+ string[] credentials = plain.Split(':', 2);
+
+ var ipAddress = Context.GetRemoteIpAddress();
+ principal = await validator.ValidateAsync(credentials[0], credentials[1], ipAddress);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, $"Handling the Basic Authentication failed: {ex.Message}");
+ return AuthenticateResult.Fail("Authorization header invalid");
+ }
+
+ if (principal == null)
+ return AuthenticateResult.Fail("Invalid credentials");
+
+ var ticket = new AuthenticationTicket(principal, Scheme.Name);
+ return AuthenticateResult.Success(ticket);
+ }
+ }
+}
diff --git a/AMWD.Common.AspNetCore/AuthenticationHandler/IBasicAuthenticationValidator.cs b/AMWD.Common.AspNetCore/AuthenticationHandler/IBasicAuthenticationValidator.cs
new file mode 100644
index 0000000..6993641
--- /dev/null
+++ b/AMWD.Common.AspNetCore/AuthenticationHandler/IBasicAuthenticationValidator.cs
@@ -0,0 +1,21 @@
+using System.Net;
+using System.Security.Claims;
+using System.Threading.Tasks;
+
+namespace Microsoft.AspNetCore.Authentication
+{
+ ///
+ /// Interface representing the validation of a basic authentication.
+ ///
+ public interface IBasicAuthenticationValidator
+ {
+ ///
+ /// Validates a username and password for Basic Authentication.
+ ///
+ /// A username.
+ /// A password.
+ /// The remote client's IP address.
+ /// The validated user principal or null.
+ Task ValidateAsync(string username, string password, IPAddress remoteAddress);
+ }
+}
diff --git a/AMWD.Common/AMWD.Common.csproj b/AMWD.Common/AMWD.Common.csproj
index c451611..aaf036e 100644
--- a/AMWD.Common/AMWD.Common.csproj
+++ b/AMWD.Common/AMWD.Common.csproj
@@ -36,7 +36,7 @@
-
+
diff --git a/AMWD.Common/Extensions/StringExtensions.cs b/AMWD.Common/Extensions/StringExtensions.cs
index 96cb18b..df766bd 100644
--- a/AMWD.Common/Extensions/StringExtensions.cs
+++ b/AMWD.Common/Extensions/StringExtensions.cs
@@ -5,7 +5,8 @@ using System.Net;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
-using DnsClient;
+using DNS.Client;
+using DNS.Protocol;
namespace System
{
@@ -148,10 +149,10 @@ namespace System
/// You can enhance the check by requesting the MX record of the domain.
///
/// The email address as string to validate.
- /// A value indicating whether to resolve a MX record.
+ /// A value indicating whether to resolve a MX record (Google DNS is used).
/// true when the email address is valid, other wise false.
public static bool IsValidEmailAddress(this string email, bool checkRecordExists = false)
- => email.IsValidEmailAddress(checkRecordExists ? new LookupClient() : null);
+ => email.IsValidEmailAddress(checkRecordExists ? new[] { new IPEndPoint(IPAddress.Parse("8.8.8.8"), 53) } : null);
///
/// Checks whether the given is a valid .
@@ -163,19 +164,36 @@ namespace System
/// A list of s of nameservers.
/// true when the email address is valid, other wise false.
public static bool IsValidEmailAddress(this string email, IEnumerable nameservers)
- => email.IsValidEmailAddress(new LookupClient(nameservers.ToArray()));
-
- private static bool IsValidEmailAddress(this string email, LookupClient lookupClient)
{
try
{
var mailAddress = new MailAddress(email);
bool isValid = mailAddress.Address == email;
- if (isValid && lookupClient != null)
+ if (isValid && nameservers != null)
{
- var result = lookupClient.Query(mailAddress.Host, QueryType.MX);
- isValid &= result.Answers.MxRecords().Any();
+ bool exists = false;
+ foreach (var nameserver in nameservers)
+ {
+ var clientRequest = new ClientRequest(nameserver) { RecursionDesired = true };
+ clientRequest.Questions.Add(new Question(Domain.FromString(mailAddress.Host), RecordType.MX));
+
+ var response = clientRequest.Resolve()
+ .ConfigureAwait(false)
+ .GetAwaiter()
+ .GetResult();
+
+ if (response.ResponseCode != ResponseCode.NoError)
+ continue;
+
+ exists = response.AnswerRecords
+ .Where(r => r.Type == RecordType.MX)
+ .Any();
+
+ break;
+ }
+
+ isValid &= exists;
}
return isValid;