using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using Step.Config; using Step.Database.Controllers; using Step.Model.DatabaseModels; using System; using System.Linq; using System.Security.Claims; using System.Security.Principal; using static Step.Config.ServerConfig; using static Step.Model.Constants; namespace Step.Attributes { public class SignalRAuthorizeAttribute : AuthorizeAttribute { public string FunctionAccess; public ACTIONS Action; public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) { string token = request.QueryString["Authorization"]; using (SessionsController sessionsController = new SessionsController()) { // Find user session on this machine SessionModel session = sessionsController.FindSessionByToken(token); if (session == null) return false; } return base.AuthorizeHubConnection(hubDescriptor, request); } protected override bool UserAuthorized(IPrincipal user) { if (!base.UserAuthorized(user)) return false; // Get Claims from context ClaimsIdentity identity = user.Identity as ClaimsIdentity; // Get user id stored in the bearer token var userId = identity.Claims.Where(c => c.Type == USER_ID_KEY).SingleOrDefault(); // Get machine unique id stored in the bearer token var machineId = identity.Claims.Where(c => c.Type == MACHINE_ID_KEY).SingleOrDefault(); //User data not found -> not authorized if (userId == null || machineId == null) return false; // User data not found -> not authorized if (userId == null || machineId == null) return false; // check authorization if (!CheckAuthorization(Convert.ToInt32(machineId.Value), Convert.ToInt32(userId.Value), FunctionAccess)) return false; return true; } public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) { return base.AuthorizeHubMethodInvocation(hubIncomingInvokerContext, appliesToMethod); } private bool CheckAuthorization(int machineId, int userId, string functionName) { // Check if the machine is the same where the user logged in if (machineId != MachineConfig.MachineId) return false; MachineUserModel machineUser = new MachineUserModel(); using (MachinesUsersController machineUsersController = new MachinesUsersController()) { // Find machineUser data and joined to user data, role data, machine data machineUser = machineUsersController.FindByUserId(machineId, userId); } using (FunctionsAccessController acController = new FunctionsAccessController()) { // Read from db function levels FunctionAccessModel functionAccess = acController.FindEnabledFunctionByName(functionName); if (functionAccess != null && ServerConfigController.CheckAreaStatus(functionAccess.Area)) { if (Action == ACTIONS.READ) { // Check read permissions if (functionAccess.ReadLevelMin > machineUser.Role.Level) return false; // Not authorized } else { // Check write permissions if (functionAccess.WriteLevelMin > machineUser.Role.Level) return false; // Not authorized } } else return false; // Authorized return true; } } } }