diff --git a/src/Gemstone.Web/APIController/ModelController.cs b/src/Gemstone.Web/APIController/ModelController.cs index c1130a52..c4f2311c 100644 --- a/src/Gemstone.Web/APIController/ModelController.cs +++ b/src/Gemstone.Web/APIController/ModelController.cs @@ -23,7 +23,6 @@ // ReSharper disable StaticMemberInGenericType using System; -using System.Linq; using System.Threading; using System.Threading.Tasks; using Gemstone.Data; diff --git a/src/Gemstone.Web/Security/IAuthenticationWebBuilder.cs b/src/Gemstone.Web/Security/IAuthenticationWebBuilder.cs index 1f52340c..9678072f 100644 --- a/src/Gemstone.Web/Security/IAuthenticationWebBuilder.cs +++ b/src/Gemstone.Web/Security/IAuthenticationWebBuilder.cs @@ -24,6 +24,7 @@ using System; using System.IO; using System.Net; +using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Gemstone.Security.AuthenticationProviders; @@ -171,7 +172,16 @@ private static async Task HandleLogoutRequestAsync(HttpContext httpContext) // If the sign out procedure did not trigger any errors or redirects, // this asks the cookie authentication scheme to redirect to the login page if (IsSuccess(httpContext.Response.StatusCode) && !IsAjaxRequest(httpContext.Request)) - await httpContext.ChallengeAsync(new AuthenticationProperties() { RedirectUri = "/" }); + { + string redirectUri = httpContext.Request.PathBase.HasValue + ? $"{httpContext.Request.PathBase}/" + : "/"; + + await httpContext.ChallengeAsync(new AuthenticationProperties() + { + RedirectUri = redirectUri + }); + } } private static async Task HandleAccessDeniedAsync(HttpContext httpContext) @@ -256,6 +266,12 @@ public static AuthenticationBuilder ConfigureOAuthProvider(this AuthenticationBu foreach (string scope in providerOptions.Scopes.Split(' ', StringSplitOptions.RemoveEmptyEntries)) config.Scope.Add(scope); + + config.Events.OnTokenValidated = context => + { + AddProviderIdentityClaim(context.Principal, OAuthAuthenticationProviderExtensions.DefaultIdentity); + return Task.CompletedTask; + }; }); } @@ -318,7 +334,30 @@ private static AuthenticationBuilder ConfigureGemstoneWebDefaults(this IServiceC return services .AddWindowsAuthenticationProvider() .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) - .AddNegotiate("windows", _ => { }) - .AddCookie(); + .AddNegotiate("windows", options => + { + if (options.Events is not null) + { + options.Events.OnAuthenticated = context => + { + AddProviderIdentityClaim(context.Principal, WindowsAuthenticationProviderExtensions.DefaultIdentity); + return Task.CompletedTask; + }; + } + }).AddCookie(); + } + + /// + /// Adds a claim to the principal indicating the identity of the provider that authenticated the user, if it does not already exist. + /// + /// The claims principal + /// The identity of the authentication provider + private static void AddProviderIdentityClaim(ClaimsPrincipal? principal, string providerIdentity) + { + if (principal?.Identity is not ClaimsIdentity identity) + return; + + if (!identity.HasClaim("Gemstone.ProviderIdentity", providerIdentity)) + identity.AddClaim(new Claim("Gemstone.ProviderIdentity", providerIdentity)); } } diff --git a/src/Gemstone.Web/WebExtensions.cs b/src/Gemstone.Web/WebExtensions.cs index 16fa28c0..b42df9c7 100644 --- a/src/Gemstone.Web/WebExtensions.cs +++ b/src/Gemstone.Web/WebExtensions.cs @@ -33,7 +33,6 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Primitives; namespace Gemstone.Web {