Fix signalR auth
This commit is contained in:
Binary file not shown.
@@ -108,7 +108,8 @@ namespace Step.App_Start
|
||||
|
||||
map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
|
||||
{
|
||||
Provider = new SignalROAuthBearerProvider()
|
||||
Provider = new SignalROAuthBearerProvider(),
|
||||
AuthenticationType = AUTHENTICATION_TYPE
|
||||
});
|
||||
var hubConfiguration = new HubConfiguration
|
||||
{
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
using Microsoft.AspNet.SignalR;
|
||||
using Microsoft.AspNet.SignalR.Hubs;
|
||||
using Microsoft.AspNet.SignalR.Owin;
|
||||
using Step.App_Start;
|
||||
using Step.Config;
|
||||
using Step.Database.Controllers;
|
||||
using Step.Model.DatabaseModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using static Step.Config.ServerConfig;
|
||||
using static Step.Model.Constants;
|
||||
using static Step.Listeners.SignalRStaticObjects;
|
||||
|
||||
namespace Step.Attributes
|
||||
{
|
||||
@@ -32,75 +36,86 @@ namespace Step.Attributes
|
||||
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.FirstOrDefault(c => c.Type == USER_ID_KEY);
|
||||
|
||||
// Get machine unique id stored in the bearer token
|
||||
var machineId = identity.Claims.FirstOrDefault(c => c.Type == MACHINE_ID_KEY);
|
||||
|
||||
//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())
|
||||
var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
|
||||
var request = hubIncomingInvokerContext.Hub.Context.Request;
|
||||
var token = request.QueryString.Get("Authorization");
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
// 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
|
||||
// check authorization
|
||||
if (!CheckAuthorization(FunctionAccess, token, out int machineId, out int userId))
|
||||
return false;
|
||||
|
||||
// Authorized
|
||||
var claims = new ClaimsIdentity(AUTHENTICATION_TYPE);
|
||||
claims.AddClaim(new Claim(USER_ID_KEY, userId.ToString()));
|
||||
claims.AddClaim(new Claim(MACHINE_ID_KEY, machineId.ToString()));
|
||||
|
||||
Dictionary<string, object> _DCI = new Dictionary<string, object>();
|
||||
_DCI.Add("server.User", claims as IPrincipal);
|
||||
hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(_DCI), connectionId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckAuthorization(string functionName, string token, out int machineId, out int userId)
|
||||
{
|
||||
machineId = userId = 0;
|
||||
using (SessionsController sessionsController = new SessionsController())
|
||||
{
|
||||
// Find user session on this machine
|
||||
SessionModel session = sessionsController.FindSessionByToken(token);
|
||||
if (session == null)
|
||||
return false;
|
||||
|
||||
// Check if the machine is the same where the user logged in
|
||||
if (session.MachineUser.MachineId != MachineConfig.MachineId)
|
||||
return false;
|
||||
|
||||
machineId = session.MachineUser.MachineId;
|
||||
userId = session.MachineUser.UserId;
|
||||
|
||||
MachineUserModel machineUser = new MachineUserModel();
|
||||
using (MachinesUsersController machineUsersController = new MachinesUsersController())
|
||||
{
|
||||
// Find machineUser data and joined to user data, role data, machine data
|
||||
machineUser = machineUsersController.FindByIdWithData(session.MachineUserId);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Check if PLC bit exists
|
||||
if (functionAccess.PlcId != 0)
|
||||
{
|
||||
// Check if functionality is enabled by PLC
|
||||
var functionalityIsEnabled = LastRuntimeFunctionality.Where(x => x.Name == functionName).FirstOrDefault();
|
||||
if (functionalityIsEnabled == null || functionalityIsEnabled.Enabled == false)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
// Authorized
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ namespace Step
|
||||
{
|
||||
public string FunctionAccess;
|
||||
public ACTIONS Action;
|
||||
protected override bool IsAuthorized(HttpActionContext actionContext)
|
||||
protected override bool IsAuthorized(HttpActionContext actionContext)
|
||||
{
|
||||
// Get token from headers
|
||||
if (actionContext.Request.Headers.Authorization == null)
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Step.Provider
|
||||
{
|
||||
public class SignalROAuthBearerProvider : OAuthBearerAuthenticationProvider
|
||||
{
|
||||
public override Task RequestToken(OAuthRequestTokenContext context)
|
||||
public override Task RequestToken(OAuthRequestTokenContext context)
|
||||
{
|
||||
var token = context.Request.Query.Get("Authorization");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user