diff --git a/NDB.Security.Authentication.Identity/Abstractions/IAuthenticationOptions.cs b/NDB.Security.Authentication.Identity/Abstractions/IAuthenticationOptions.cs new file mode 100644 index 0000000..a520e24 --- /dev/null +++ b/NDB.Security.Authentication.Identity/Abstractions/IAuthenticationOptions.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Http; +using System; + +namespace NDB.Security.Authentication.Identity.Abstractions +{ + public interface IAuthenticationOptions + { + Func AuthenticateAsGuest { get; } + int GuestUserId { get; } + string GuestUserName { get; } + } +} diff --git a/NDB.Security.Authentication.Identity/BasicAuthenticationExtensions.cs b/NDB.Security.Authentication.Identity/BasicAuthenticationExtensions.cs index f61cf7d..39a2fa1 100644 --- a/NDB.Security.Authentication.Identity/BasicAuthenticationExtensions.cs +++ b/NDB.Security.Authentication.Identity/BasicAuthenticationExtensions.cs @@ -1,6 +1,7 @@ using IdentityServer.Wrapper; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.DependencyInjection; +using NDB.Security.Authentication.Identity.Abstractions; using System; namespace NDB.Security.Authentication.Identity @@ -9,11 +10,17 @@ namespace NDB.Security.Authentication.Identity { public static IServiceCollection AddBasicAuthentication(this IServiceCollection services, string identityServerBaseAddress) { - if (string.IsNullOrEmpty(identityServerBaseAddress)) - throw new Exception($"Identity server base address must be provided."); + services.AddBasicAuthentication(identityServerBaseAddress, new Services.AuthenticationOptions()); + return services; + } + + public static IServiceCollection AddBasicAuthentication(this IServiceCollection services, string identityServerBaseAddress, IAuthenticationOptions authenticationOptions) + { + Validate(identityServerBaseAddress, authenticationOptions); // Identity server services.UseIdentityServices(identityServerBaseAddress); + services.AddSingleton(authenticationOptions); // configure basic authentication services.AddAuthentication("BasicAuthentication") @@ -21,5 +28,15 @@ namespace NDB.Security.Authentication.Identity return services; } + + private static void Validate(string identityServerBaseAddress, IAuthenticationOptions authenticationOptions) + { + if (string.IsNullOrEmpty(identityServerBaseAddress)) + throw new ArgumentException("Identity server base address must be provided."); + + var guestFuncDefined = authenticationOptions.AuthenticateAsGuest != null; + if (guestFuncDefined && string.IsNullOrEmpty(authenticationOptions.GuestUserName)) + throw new ArgumentException("Guest function is defined, but guest user name is not set."); + } } } diff --git a/NDB.Security.Authentication.Identity/BasicAuthenticationHandler.cs b/NDB.Security.Authentication.Identity/BasicAuthenticationHandler.cs index 467ccc0..c921e48 100644 --- a/NDB.Security.Authentication.Identity/BasicAuthenticationHandler.cs +++ b/NDB.Security.Authentication.Identity/BasicAuthenticationHandler.cs @@ -3,6 +3,7 @@ using IdentityServer.Wrapper.Services; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using NDB.Security.Authentication.Identity.Abstractions; using System.Net.Http.Headers; using System.Security.Claims; using System.Text.Encodings.Web; @@ -13,17 +14,28 @@ namespace NDB.Security.Authentication.Identity public class BasicAuthenticationHandler : AuthenticationHandler { private readonly IIdentityService _identityService; + private readonly IAuthenticationOptions _authenticationOptions; - public BasicAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IIdentityService identityService) + public BasicAuthenticationHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IIdentityService identityService, IAuthenticationOptions authenticationOptions) : base(options, logger, encoder, clock) { _identityService = identityService; + _authenticationOptions = authenticationOptions; } protected override async Task HandleAuthenticateAsync() { if (!Request.Headers.ContainsKey("Authorization")) + { + var authenticateAsGuest = _authenticationOptions.AuthenticateAsGuest?.Invoke(Request) ?? false; + if (authenticateAsGuest) + { + var guestTicket = GetAuthenticationTicket(new User() { UserId = _authenticationOptions.GuestUserId, UserName = _authenticationOptions.GuestUserName }); + return AuthenticateResult.Success(guestTicket); + } + return AuthenticateResult.Fail("Missing Authorization Header"); + } User user; try @@ -40,6 +52,12 @@ namespace NDB.Security.Authentication.Identity if (user == null) return AuthenticateResult.Fail("Invalid Username or Password"); + var ticket = GetAuthenticationTicket(user); + return AuthenticateResult.Success(ticket); + } + + private AuthenticationTicket GetAuthenticationTicket(User user) + { var claims = new[] { new Claim(ClaimTypes.NameIdentifier, user.UserId.ToString()), new Claim(ClaimTypes.Name, user.UserName), @@ -49,7 +67,7 @@ namespace NDB.Security.Authentication.Identity var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); - return AuthenticateResult.Success(ticket); + return ticket; } } } diff --git a/NDB.Security.Authentication.Identity/NDB.Security.Authentication.Identity.csproj b/NDB.Security.Authentication.Identity/NDB.Security.Authentication.Identity.csproj index bb96b58..e742ff8 100644 --- a/NDB.Security.Authentication.Identity/NDB.Security.Authentication.Identity.csproj +++ b/NDB.Security.Authentication.Identity/NDB.Security.Authentication.Identity.csproj @@ -7,6 +7,7 @@ https://dev.azure.com/tstanciu94/NDB Git NDB BasicAuthentication Identity + 1.0.1 diff --git a/NDB.Security.Authentication.Identity/Services/AuthenticationOptions.cs b/NDB.Security.Authentication.Identity/Services/AuthenticationOptions.cs new file mode 100644 index 0000000..8558e19 --- /dev/null +++ b/NDB.Security.Authentication.Identity/Services/AuthenticationOptions.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Http; +using NDB.Security.Authentication.Identity.Abstractions; +using System; + +namespace NDB.Security.Authentication.Identity.Services +{ + public class AuthenticationOptions : IAuthenticationOptions + { + public Func AuthenticateAsGuest { get; set; } + + public int GuestUserId { get; set; } + + public string GuestUserName { get; set; } + } +} diff --git a/Notes.txt b/Notes.txt index 31c9069..1dd6b42 100644 --- a/Notes.txt +++ b/Notes.txt @@ -18,11 +18,11 @@ Push packages: dotnet nuget push NDB.Application.DataContracts.1.0.0.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget -dotnet nuget push NDB.Extensions.Swagger.1.0.0.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget +dotnet nuget push NDB.Extensions.Swagger.1.0.1.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget dotnet nuget push NDB.Extensions.Http.1.0.0.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget -dotnet nuget push NDB.Security.Authentication.Identity.1.0.0.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget +dotnet nuget push NDB.Security.Authentication.Identity.1.0.1.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget dotnet nuget push NDB.Extensions.Caching.1.0.0.nupkg -k ***REMOVED*** -s http://stawebsrv:8081/NuGetServer/nuget ####################################################################################################################################################### \ No newline at end of file