public IServiceTransport CreateConnection(OpenConnectionMessage message, IServiceConnection serviceConnection) { var dispatcher = new HubDispatcher(_configuration); dispatcher.Initialize(_configuration.Resolver); var responseStream = new MemoryStream(); var hostContext = GetHostContext(message, responseStream, serviceConnection); if (dispatcher.Authorize(hostContext.Request)) { // ProcessRequest checks if the connectionToken matches "{connectionid}:{userName}" format with context.User _ = dispatcher.ProcessRequest(hostContext); // TODO: check for errors written to the response if (hostContext.Response.StatusCode != 200) { Log.ProcessRequestError(_logger, message.ConnectionId, hostContext.Request.QueryString.ToString()); Debug.Fail("Response StatusCode is " + hostContext.Response.StatusCode); var errorResponse = GetContentAndDispose(responseStream); throw new InvalidOperationException(errorResponse); } return((AzureTransport)hostContext.Environment[AspNetConstants.Context.AzureSignalRTransportKey]); } // This happens when hub is not found Debug.Fail("Unauthorized"); throw new InvalidOperationException("Unable to authorize request"); }
public void DuplicateHubNamesThrows() { // Arrange var mockHub = new Mock <IHub>(); var mockHubManager = new Mock <IHubManager>(); mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() }); var serviceProvider = new ServiceCollection() .AddOptions() .AddHosting() .AddDataProtection() .AddSignalR() .AddInstance <IHubManager>(mockHubManager.Object) .BuildServiceProvider(); var dispatcher = new HubDispatcher(serviceProvider.GetRequiredService <IOptions <SignalROptions> >()); var testContext = new TestContext("/ignorePath", new Dictionary <string, string> { { "connectionData", @"[{name: ""foo""}, {name: ""Foo""}]" }, }); // Act & Assert dispatcher.Initialize(serviceProvider); Assert.Throws <InvalidOperationException>(() => dispatcher.Authorize(testContext.MockRequest.Object)); }
public void DuplicateHubNamesThrows() { // Arrange var dispatcher = new HubDispatcher(new HubConfiguration()); var request = new Mock <IRequest>(); var qs = new NameValueCollection(); request.Setup(m => m.QueryString).Returns(qs); qs["connectionData"] = @"[{name: ""foo""}, {name: ""Foo""}]"; var mockHub = new Mock <IHub>(); var mockHubManager = new Mock <IHubManager>(); mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() }); var dr = new DefaultDependencyResolver(); dr.Register(typeof(IHubManager), () => mockHubManager.Object); dispatcher.Initialize(dr, new HostContext(null, null)); Assert.Throws <InvalidOperationException>(() => dispatcher.Authorize(request.Object)); }
public void DuplicateHubNamesThrows() { // Arrange var mockHub = new Mock<IHub>(); var mockHubManager = new Mock<IHubManager>(); mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() }); var serviceProvider = ServiceProviderHelper.CreateServiceProvider(services => services.AddInstance(mockHubManager.Object)); var dispatcher = new HubDispatcher(serviceProvider.GetRequiredService<IOptions<SignalROptions>>()); var testContext = new TestContext("/ignorePath", new Dictionary<string, string> { {"connectionData", @"[{name: ""foo""}, {name: ""Foo""}]"}, }); // Act & Assert dispatcher.Initialize(serviceProvider); Assert.Throws<InvalidOperationException>(() => dispatcher.Authorize(testContext.MockRequest.Object)); }
public void DuplicateHubNamesThrows() { // Arrange var dispatcher = new HubDispatcher(new HubConfiguration()); var request = new Mock<IRequest>(); var qs = new NameValueCollection(); request.Setup(m => m.QueryString).Returns(new NameValueCollectionWrapper(qs)); qs["connectionData"] = @"[{name: ""foo""}, {name: ""Foo""}]"; var mockHub = new Mock<IHub>(); var mockHubManager = new Mock<IHubManager>(); mockHubManager.Setup(m => m.GetHub("foo")).Returns(new HubDescriptor { Name = "foo", HubType = mockHub.Object.GetType() }); var dr = new DefaultDependencyResolver(); dr.Register(typeof(IHubManager), () => mockHubManager.Object); dispatcher.Initialize(dr); Assert.Throws<InvalidOperationException>(() => dispatcher.Authorize(request.Object)); }
private Task ProcessNegotiationRequest(IOwinContext owinContext, HostContext context) { var claims = BuildClaims(owinContext, context.Request); var dispatcher = new HubDispatcher(_configuration); try { dispatcher.Initialize(_configuration.Resolver); if (!dispatcher.Authorize(context.Request)) { string error = null; if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated) { // If the user is authenticated and authorize failed then 403 error = "Forbidden"; context.Response.StatusCode = 403; } else { // If failed to authorize the request then return 401 error = "Unauthorized"; context.Response.StatusCode = 401; } Log.NegotiateFailed(_logger, error); return(context.Response.End(error)); } } catch (Exception e) { Log.NegotiateFailed(_logger, e.Message); context.Response.StatusCode = 500; return(context.Response.End("")); } IServiceEndpointProvider provider; try { // Take the service endpoints for the app provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(owinContext, _endpointManager.GetEndpoints(_appName))); // When status code changes, we consider the inner router changed the response, then we stop here if (context.Response.StatusCode != 200) { // Inner handler already write to context.Response, no need to continue with error case return(Task.CompletedTask); } // Consider it as internal server error when we don't successfully get negotiate response if (provider == null) { var message = "Unable to get the negotiate endpoint"; Log.NegotiateFailed(_logger, message); context.Response.StatusCode = 500; return(context.Response.End(message)); } } catch (AzureSignalRNotConnectedException e) { Log.NegotiateFailed(_logger, e.Message); context.Response.StatusCode = 500; return(context.Response.End(e.Message)); } // Redirect to Service var clientProtocol = context.Request.QueryString["clientProtocol"]; string originalPath = null; string queryString = null; // add OriginalPath and QueryString when the clients protocol is higher than 2.0, earlier ASP.NET SignalR clients does not support redirect URL with query parameters if (!string.IsNullOrEmpty(clientProtocol) && Version.TryParse(clientProtocol, out var version) && version >= ClientSupportQueryStringVersion) { var clientRequestId = _connectionRequestIdProvider.GetRequestId(); if (clientRequestId != null) { // remove system preserved query strings queryString = "?" + string.Join("&", context.Request.QueryString.Where(s => !PreservedQueryParameters.Contains(s.Key)).Concat( new[] { new KeyValuePair <string, string>( Constants.QueryParameter.ConnectionRequestId, clientRequestId) }) .Select(s => $"{Uri.EscapeDataString(s.Key)}={Uri.EscapeDataString(s.Value)}")); } originalPath = GetOriginalPath(context.Request.LocalPath); } var url = provider.GetClientEndpoint(null, originalPath, queryString); return(GenerateClientAccessTokenAsync(provider, context, url, claims)); }
private Task ProcessNegotiationRequest(IOwinContext owinContext, HostContext context) { string accessToken = null; var claims = BuildClaims(owinContext, context.Request); var dispatcher = new HubDispatcher(_configuration); try { dispatcher.Initialize(_configuration.Resolver); if (!dispatcher.Authorize(context.Request)) { string error = null; if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated) { // If the user is authenticated and authorize failed then 403 error = "Forbidden"; context.Response.StatusCode = 403; } else { // If failed to authorize the request then return 401 error = "Unauthorized"; context.Response.StatusCode = 401; } Log.NegotiateFailed(_logger, error); return(context.Response.End(error)); } } catch (Exception e) { Log.NegotiateFailed(_logger, e.Message); context.Response.StatusCode = 500; return(context.Response.End("")); } IServiceEndpointProvider provider; try { provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(owinContext, _endpointManager.Endpoints)); // When status code changes, we consider the inner router changed the response, then we stop here if (context.Response.StatusCode != 200) { // Inner handler already write to context.Response, no need to continue with error case return(Task.CompletedTask); } // Consider it as internal server error when we don't successfully get negotiate response if (provider == null) { var message = "Unable to get the negotiate endpoint"; Log.NegotiateFailed(_logger, message); context.Response.StatusCode = 500; return(context.Response.End(message)); } } catch (AzureSignalRNotConnectedException e) { Log.NegotiateFailed(_logger, e.Message); context.Response.StatusCode = 500; return(context.Response.End(e.Message)); } // Redirect to Service // TODO: add OriginalPath and QueryString when the clients support it var url = provider.GetClientEndpoint(null, null, null); try { accessToken = provider.GenerateClientAccessToken(null, claims); } catch (AzureSignalRAccessTokenTooLongException ex) { Log.NegotiateFailed(_logger, ex.Message); context.Response.StatusCode = 413; return(context.Response.End(ex.Message)); } return(SendJsonResponse(context, GetRedirectNegotiateResponse(url, accessToken))); }