using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.Cookies; using Oqtane.Infrastructure; using Oqtane.Models; using Oqtane.Extensions; using Oqtane.Shared; using Oqtane.Managers; namespace Oqtane.Security { public static class PrincipalValidator { public static Task ValidateAsync(CookieValidatePrincipalContext context) { if (context != null && context.Principal.Identity.IsAuthenticated && context.Principal.Identity.Name != null) { var config = context.HttpContext.RequestServices.GetService(typeof(IConfigManager)) as IConfigManager; string path = context.Request.Path.ToString().ToLower(); // check if framework is installed if (config.IsInstalled() && !path.StartsWith("/_")) // ignore Blazor framework requests { var _logger = context.HttpContext.RequestServices.GetService(typeof(ILogManager)) as ILogManager; var alias = context.HttpContext.GetAlias(); if (alias != null) { var userManager = context.HttpContext.RequestServices.GetService(typeof(IUserManager)) as IUserManager; var user = userManager.GetUser(context.Principal.UserId(), alias.SiteId); // cached // check if user is valid, not deleted, has roles, and security stamp has not changed if (user != null && !user.IsDeleted && user.Roles.Any() && context.Principal.SecurityStamp() == user.SecurityStamp) { // validate sitekey in case user has changed sites in installation if (context.Principal.SiteKey() != alias.SiteKey || !context.Principal.Roles().Any()) { // refresh principal var identity = UserSecurity.CreateClaimsIdentity(alias, user); context.ReplacePrincipal(new ClaimsPrincipal(identity)); context.ShouldRenew = true; Log(_logger, alias, "Permissions Refreshed For User {Username} Accessing {Url}", context.Principal.Identity.Name, path); } } else { // remove principal (ie. log user out) Log(_logger, alias, "Permissions Removed For User {Username} Accessing {Url}", context.Principal.Identity.Name, path); context.RejectPrincipal(); } } else { // user is signed in but site cannot be determined Log(_logger, alias, "Alias Could Not Be Resolved For User {Username} Accessing {Url}", context.Principal.Identity.Name, path); } } } return Task.CompletedTask; } private static void Log (ILogManager logger, Alias alias, string message, string username, string path) { if (!path.StartsWith("/api/")) // reduce log verbosity { logger.Log(alias.SiteId, LogLevel.Information, "LoginValidation", Enums.LogFunction.Security, message, username, path); } } } }