SignalR authentication with webAPI Bearer Token

前端 未结 3 1220
悲哀的现实
悲哀的现实 2021-01-31 05:01

+i used this solution to implement Token Based Authentication using ASP.NET Web API 2, Owin, and Identity...which worked out excellently well. i used this other solution and thi

相关标签:
3条回答
  • 2021-01-31 05:23

    Can't comment so adding my answer after the comments on Peter's excellent answer.

    Did a bit more digging and the user id that I had set in my custom owin authorization provider was hiding here (complete hub method shown).

        [Authorize]
        public async Task<int> Test()
        {
            var claims = (Context.User.Identity as System.Security.Claims.ClaimsIdentity).Claims.FirstOrDefault();
            if (claims != null)
            {
                var userId = claims.Value;
    
                //security party!
                return 1;
            }
    
            return 0;
        }
    

    More added for texas697:

    Startup.Auth.cs add this to ConfigureAuth() if not already there:

    app.Map("/signalr", map =>
        {
            map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
            {
                Provider = new QueryStringOAuthBearerProvider() //important bit!
            });
    
            var hubConfiguration = new HubConfiguration
            {
                EnableDetailedErrors = true,
                Resolver = GlobalHost.DependencyResolver,
            };
            map.RunSignalR(hubConfiguration);
        });
    

    The custom auth provider looks like this:

    public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
    {
        public override Task RequestToken(OAuthRequestTokenContext context)
        {
            var value = context.Request.Query.Get("access_token");
    
            if (!string.IsNullOrEmpty(value))
            {
                context.Token = value;
            }
    
            return Task.FromResult<object>(null);
        }
    }
    
    0 讨论(0)
  • 2021-01-31 05:36

    I followed this:

    first Add the JWT to the query string:'

    this.connection = $['hubConnection']();
    this.connection.qs = { 'access_token': token}
    

    then in thestartup.cs,before JwtBearerAuthentication, add the token to the header:

     app.Use(async (context, next) =>
                {
                    if (string.IsNullOrWhiteSpace(context.Request.Headers["Authorization"]) && context.Request.QueryString.HasValue)
                    {
                        var token = context.Request.QueryString.Value.Split('&').SingleOrDefault(x => x.Contains("access_token"))?.Split('=')[1];
                        if (!string.IsNullOrWhiteSpace(token))
                        {
                            context.Request.Headers.Add("Authorization", new[] { $"Bearer {token}" });
                        }
                    }
                    await next.Invoke();
                });
    
    
                var keyResolver = new JwtSigningKeyResolver(new AuthenticationKeyContainer());
                app.UseJwtBearerAuthentication(
                    new JwtBearerAuthenticationOptions
                    {
                        AuthenticationMode = AuthenticationMode.Active,
                        TokenValidationParameters = new TokenValidationParameters()
                        {
                            ValidAudience = ConfigurationUtil.ocdpAuthAudience,
                            ValidIssuer = ConfigurationUtil.ocdpAuthZero,
                            IssuerSigningKeyResolver = (token, securityToken, kid, validationParameters) => keyResolver.GetSigningKey(kid)
                        }
                    });
    
    
                ValidateSignalRConnectionData(app);
                var hubConfiguration = new HubConfiguration
                {
                    EnableDetailedErrors = true
                };
                app.MapSignalR(hubConfiguration);
    
    0 讨论(0)
  • 2021-01-31 05:39

    You need to configure your signalr like this;

    app.Map("/signalr", map =>
    {
        map.UseCors(CorsOptions.AllowAll);
    
        map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
        {
            Provider = new QueryStringOAuthBearerProvider()
        });
    
        var hubConfiguration = new HubConfiguration
        {
            Resolver = GlobalHost.DependencyResolver,
        };
        map.RunSignalR(hubConfiguration);
    });
    

    Then you need to write a basic custom OAuthBearerAuthenticationProvider for signalR which accepts access_token as query string.

    public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
    {
        public override Task RequestToken(OAuthRequestTokenContext context)
        {
            var value = context.Request.Query.Get("access_token");
    
            if (!string.IsNullOrEmpty(value))
            {
                context.Token = value;
            }
    
            return Task.FromResult<object>(null);
        }
    }
    

    After this all you need is to send access_token with signalr connection as querystring.

    $.connection.hub.qs = { 'access_token': token };
    

    And for your hub just ordinary [Authorize] attribute

    public class impAuthHub : Hub
    {
        [Authorize]
        public void SendMessage(string name, string message)
        {
           Clients.All.newMessage(name, message);
        }
    }
    

    Hope this helps. YD.

    0 讨论(0)
提交回复
热议问题