/// <summary> /// Método construtor /// </summary> /// <param name="logger">Instância do serviço de log</param> /// <param name="requiredPermissions">Permissões requeridas pelo atributo</param> /// <param name="provider">Instância do provedor de serviços</param> /// <param name="configuration">Instância do container de configurações</param> public PermissionAttributeImpl(ILogger <PermissionAttribute> logger, PermissionsAuthorizationRequirement requiredPermissions, IServiceProvider provider, IConfiguration configuration) { this._logger = logger; this._requiredPermission = requiredPermissions; this._provider = provider; this._configuration = configuration; }
/// <summary> /// Método que efetua a verificação de permissão de uma identidade considerando o requerimento de permissão informado. /// </summary> /// <param name="requiredPermission">Requerimento de permissão</param> /// <param name="missingPermissions"></param> /// <returns>Verdadeiro caso o usuário atenda aos critérios requisitados e falso caso contrário</returns> public virtual bool ValidatePermissionByClaims(PermissionsAuthorizationRequirement requiredPermission, out List <string> missingPermissions) { var result = false; if (this.SystemUser.IsRoot()) { this.Logger.LogInformation(Resource.AUTHORIZATION_USER_ISROOT); missingPermissions = new List <string>(); return(true); } var usrPermissions = this.SystemUser.Permissions.Select(x => x.Value).ToList(); var ownedPermissions = requiredPermission.Permissions.Where(x => usrPermissions.Contains(x)).ToList(); missingPermissions = requiredPermission.Permissions.Where(x => !usrPermissions.Contains(x)).ToList(); result = requiredPermission.ValidationType switch { PermissionValidationType.RequireOneOf => ownedPermissions.Any(), PermissionValidationType.RequireAll => ownedPermissions.Count() == requiredPermission.Permissions.Count(), _ => true, }; return(result); }
/// <summary> /// Método construtor. /// </summary> /// <param name="method">Método de execução do endpoint</param> /// <param name="validationType">Tipo de validação de permissão. Veja <see cref="PermissionValidationType"/></param> /// <param name="permissions">Permissões requeridas para autorização</param> public PermissionAttribute(Method method, PermissionValidationType validationType, params string[] permissions) : base(typeof(PermissionAttributeImpl)) { var permission = new PermissionsAuthorizationRequirement(method, validationType, permissions); Arguments = new[] { permission }; }
/// <summary> /// Método que efetua a validação da autorização de acesso. /// </summary> /// <param name="context">Contexto de autorização</param> /// <param name="requiredPermission">Requerimento de permissão</param> public async Task Authorize(AuthorizationFilterContext context, PermissionsAuthorizationRequirement requiredPermission) { // Se permite anônimo, não é necessário validar nada. if (requiredPermission.ValidationType.Equals(PermissionValidationType.Annonymous)) { this.Logger.LogInformation(Resource.AUTHORIZATION_ANNONYMOUS, this.Accessor.HttpContext.Request.Path, this.SystemUser.RemoteIpAddress); return; } this.Logger.LogInformation(Resource.AUTHORIZATION_PROTECTED, this.Accessor.HttpContext.Request.Path, this.SystemUser.RemoteIpAddress); // Obtendo configurações da autoridade. var settings = this.Configuration.GetIdentityConfigurations(); // Obtendo token de autorização. var token = context.GetAuthorizationToken(); var tokenDecoder = new JwtSecurityTokenHandler(); this.Logger.LogInformation(Resource.AUTHORIZATION_VALIDATIND_TOKEN); // Verificando se é possível ler o token. if (!tokenDecoder.CanReadToken(token)) { this.Logger.LogWarning(Resource.AUTHORIZATION_ERROR_TOKEN_WRONG_FORMAT); context.Result = this.Unauthorized(); return; } // Fazendo a leitura do token. var jwtToken = tokenDecoder.ReadJwtToken(token); // Efetuando a validação do token junto a autoridade. var result = await jwtToken.ValidateAsync(settings); // Se o resultado não é válido, retorna 401. if (!result.IsValid) { this.Logger.LogWarning(Resource.AUTHORIZATION_ERROR_INVALID_TOKEN, result.Status, result.Message); context.Result = this.Unauthorized(); return; } // Se os dados do usuário são nulos, não possui identidade ou não está autenticado, retorna 401. if (result.Principal == null || !result.Principal.Identities.Any() || !result.Principal.Identity.IsAuthenticated) { this.Logger.LogWarning(Resource.AUTHORIZATION_USER_UNHAUTHORIZED); context.Result = this.Unauthorized(); return; } this.Logger.LogInformation(Resource.AUTHORIZATION_ADDING_USER_DETAILS); // Atualizando dados do usuário. try { await this.UpdateSystemUser(settings, token); this.SystemUser.Update(); } catch (IdentityException ex) { this.Logger.LogError(Resource.ERROR_GET_USERINFO, ex.StatusCode, ex.Message); context.Result = this.Unauthorized(); return; } // Se é necessária apenas autenticação, não há porquê continuar. if (requiredPermission.ValidationType.Equals(PermissionValidationType.RequireAuthenticatedOnly)) { this.Logger.LogInformation(Resource.AUTHORIZATION_USER_AUTHORIZED, this.SystemUser.DisplayName, this.Accessor.HttpContext.Request.Path); return; } // Se há uma permissão padrão, transforme-a em permissão de controller. if (requiredPermission.Contains(IdentityConstants.PERMISSION_DEFAULT_TAG)) { var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor; var controllerType = actionDescriptor.ControllerTypeInfo.AsType(); requiredPermission.ReplaceDefault(controllerType.GetControllerDefaultPermission()); } var havePermission = false; var missingPermissions = new List <string>(); switch (settings.PermissionsValidationType) { case PermissionsValidationType.Claim: havePermission = ValidatePermissionByClaims(requiredPermission, out missingPermissions); break; case PermissionsValidationType.Authority: throw new NotImplementedException($"The validation type {settings.PermissionsValidationType} isn't implemented!"); } // Se o usuário não possui permissão para acesso ao serviço, retorna 401. if (!havePermission) { this.LogPermissionErrorMessage(requiredPermission.ValidationType, missingPermissions); context.Result = this.Unauthorized(); return; } this.Logger.LogInformation(Resource.AUTHORIZATION_USER_AUTHORIZED, this.SystemUser.DisplayName, this.Accessor.HttpContext.Request.Path); }