Unable to Identify User Context in SignalR hub decorated with “Authorize” attribute

前端 未结 2 500
没有蜡笔的小新
没有蜡笔的小新 2021-01-24 02:42

Server

SignalR hub within MVC 5 WebApi 2, Security: Bearer token

Client

C# class using HttpWebRequest to retrieve bearer token from WebApi controller /

相关标签:
2条回答
  • 2021-01-24 02:48

    Here is my solution, WORK on Azure and local. AngularJS, Web API and SignalR request.Environment["server.User"] this code doesn't work on Azure. First i create my Custom Filter Class.

    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
        public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute
        {
            public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
            {
                var _Authorization = request.QueryString.Get("Bearer");
            if (!string.IsNullOrEmpty(_Authorization))
            {
                var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(_Authorization);
    
                if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
                {
                    request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
                    return true;
                }
            }
            return false;
            }
            public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
            {
                var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
                var request=hubIncomingInvokerContext.Hub.Context.Request;
                var _Authorization = request.QueryString.Get("Bearer");
                if (!string.IsNullOrEmpty(_Authorization))
                {
                    //var token = _Authorization.Replace("Bearer ", "");
                    var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(_Authorization);
    
                    if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
                    {
                        Dictionary<string, object> _DCI = new Dictionary<string, object>();
                        _DCI.Add("server.User", new ClaimsPrincipal(ticket.Identity));
                        hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(_DCI), connectionId);
                        return true;
                    }
                }
                return false;
            }
    }
    

    Then in all my connection from SignalR i put

    connection.qs = { Bearer: localStorageService.get('authorizationData').token };

    My Startup Class

    public void Configuration(IAppBuilder app)
            {
                app.Map("/signalr", map =>
                {
                    map.UseCors(CorsOptions.AllowAll);
                    var hubConfiguration = new HubConfiguration
                    {
                        EnableDetailedErrors = true
                    };
                    var authorizer = new QueryStringBearerAuthorizeAttribute();
                    var module = new AuthorizeModule(authorizer, authorizer);
                    GlobalHost.HubPipeline.AddModule(module);
                    map.RunSignalR(hubConfiguration);
                });
                GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule());
                ConfigureAuth(app);
            }
    

    It works perfect for me, i'm not sure if sending my token for quesry string instead from header is a security issue. Thats my solution using angularjs, asp.net web api, signal r for autenticate SignalR hubs with a beared token.

    In your Hub you can Access to User variable in this way

    public ClaimsPrincipal _User { get { return Context.Request.Environment["server.User"] as ClaimsPrincipal; } }
    
    0 讨论(0)
  • 2021-01-24 03:09

    Finally figured this out, I was using the wrong library to decrypt the token. DpapiDataProtectionProvider is used in self-host scenarios, we are hosted in IIS. Here is the functioning code.

     public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor    hubDescriptor, IRequest request)
     {
           var token = request.QueryString.Get("Bearer");
           var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(token);
    
            if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
            {
                 // set the authenticated user principal into environment so that it can be used in the future
                 request.Environment["server.User"] = new ClaimsPrincipal(ticket.Identity);
                 return true;
            }
    
           return false;
      }
    
    0 讨论(0)
提交回复
热议问题