Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context.User is Null on [Authorized] SignalRHub Task OnDisconnected #2753

Closed
albhardy opened this issue Dec 11, 2013 · 17 comments
Closed

Context.User is Null on [Authorized] SignalRHub Task OnDisconnected #2753

albhardy opened this issue Dec 11, 2013 · 17 comments
Milestone

Comments

@albhardy
Copy link

I'm using SignalR 2.0 on MVC5 application using the new ASP.NET Identity feature.
Context.User.Identity.Name is correctly populated on Task OnConnected but suddenly becomes null after user navigate away/logout.

Code:

  public override Task OnDisconnected() {
            string userName = Context.User.Identity.Name; //results in null exception
            string connectionId = Context.ConnectionId; //not null
           return base.OnDisconnected();
        }

Exception message:

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=SignalRChat
  StackTrace:
       at SignalRChat.Hubs.ChatHub.OnDisconnected() in f:\SignalRChat\SignalRChat\Hubs\ChatHub.cs:line 34
       at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.Disconnect(IHub hub)
       at Microsoft.AspNet.SignalR.Hubs.HubPipelineModule.<>c__DisplayClass13.<BuildDisconnect>b__11(IHub hub)
       at Microsoft.AspNet.SignalR.Hubs.HubPipeline.Disconnect(IHub hub)
       at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.<OnDisconnected>b__21(IHub hub)
       at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.<>c__DisplayClass2a.<ExecuteHubEvent>b__26(IHub instance)
       at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
       at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
       at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
       at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ExecuteHubEvent(IRequest request, String connectionId, Func`2 action)
       at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnDisconnected(IRequest request, String connectionId)
       at Microsoft.AspNet.SignalR.PersistentConnection.<>c__DisplayClassa.<ProcessRequest>b__9()
       at Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func)
  InnerException: 

However, such issue does not happen if I use authentication in https://github.com/tugberkugurlu/SignalRSamples/tree/master/ConnectionMappingSample

 [HttpPost]
        [ActionName("Login")]
        public ActionResult PostLogin(LoginModel loginModel) {
            if (ModelState.IsValid) {
                FormsAuthentication.SetAuthCookie(loginModel.Name, true);
                return RedirectToAction("index", "home");
            }
            return View(loginModel);
        }

Platform: Windows 7, VS2013 Express

@davidfowl
Copy link
Member

You said it becomes null after logout or navigation or both?

@albhardy
Copy link
Author

Both.

@davidfowl
Copy link
Member

So if you navigate away without logging out, it happens? Or do you have to logout then navigate?

@albhardy
Copy link
Author

Yes, I tried navigate away without logging out (and Task OnDisconnected is triggered).
Then I relaunch the app - this time I do log out (Task OnDisconnected is also triggered).
In both Scenario, Context.User value is null.

Basically what I did:

  • Set breakpoint @ Task OnConnected and Task OnDisconnected to verify Context.User value
  • Launch the apps, and Login since I set [authorize] required on both Controller and Hub
  • I get authenticated to the SignalR Chat page
  • Breakpoint @ Task OnConnected Triggered (an therefore I can verify Context.User has value)
  • Navigate to different page (e.g. homepage)
  • Breakpoint @ Task OnDisconnected is triggered after around 30sec. Context User is null
  • Restart / Relaunch the apps
  • I get authenticated directly to the Chat page - then I logout (which gets me redirected to other page).
  • Breakpoint @ Task OnDisconnected is then triggered after around 30sec. Context User is also null.

@ghost ghost assigned Xiaohongt Dec 11, 2013
@davidfowl
Copy link
Member

@Xiaohongt can you take a look at this?

@Xiaohongt
Copy link
Contributor

After navigate away or logout, WebSocketTransport, ServerSentEventsTransport and LongPollingTransport repro, Request.User is null.

Note, ForeverFrameTransport doesn't repro, it doesn't repro when use Self Host.

When debug for WebSocketTransport, after navigate away, for abort request, in TransportDisconnectBase class, at beginning _context.Request.User is not null, somehow in Microsoft.AspNet.SignalR.Transports.ForeverTransport.OnMessageReceived(Microsoft.AspNet.SignalR.Transports.PersistentResponse response, object state) ,
the (MessageContext)state.Transport base class _context.Request.User become null.

Need to look more

@polygit
Copy link

polygit commented Jan 12, 2014

@davidfowl have you been able to look at this? I'm dealing with the same thing. I don't understand anything @Xiaohongt said.

@davidfowl
Copy link
Member

@polygit nope, will put it into 2.0.3.

@davidfowl
Copy link
Member

@gustavo-armenta can you look at this? Does it happen for all transports?

@bytenik
Copy link

bytenik commented Jan 14, 2014

@xueye and I are both experiencing this issue on our application as well.

@gustavo-armenta
Copy link
Contributor

OK guys, I looked into this issue. I can only repro the failure when using websockets, for the other transports is working fine. PLEASE CONFIRM you only see this issue on websockets.

On the case of websockets, I see the body of OnDisconnected method is using a Context.Request from the original request that opened the connection, its not using the "signalr/abort" request.

On the log below, the hashCode is from the AspNetDictionary instance that contains the environment key "server.User". The dictionary entry has a value ClaimsPrincipal but when the disconnection is triggered, there is some piece of code setting the value to null. I have not found yet what is causing it.

SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=20655653 value=System.Security.Claims.ClaimsPrincipal path=/signalr/negotiate
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=20655653 value=System.Security.Claims.ClaimsPrincipal path=/signalr/negotiate
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=20655653 value=System.Security.Claims.ClaimsPrincipal path=/signalr/negotiate
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=20655653 value=System.Security.Claims.ClaimsPrincipal path=/signalr/negotiate
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Information: 0 : Connection 190d2d0d-66dd-4af9-9274-61e87c2ace04 is New.
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value=System.Security.Claims.ClaimsPrincipal path=/signalr/connect
SignalR.Transports.TransportHeartBeat Verbose: 0 : KeepAlive(190d2d0d-66dd-4af9-9274-61e87c2ace04)
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.WebSocketTransport Information: 0 : CloseSocket(190d2d0d-66dd-4af9-9274-61e87c2ace04)
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=60921001 value=System.Security.Claims.ClaimsPrincipal path=/signalr/abort
SignalR.Transports.WebSocketTransport Information: 0 : Abort(190d2d0d-66dd-4af9-9274-61e87c2ace04)
SignalR.Transports.TransportHeartBeat Information: 0 : Removing connection 190d2d0d-66dd-4af9-9274-61e87c2ace04
SignalR.Transports.WebSocketTransport Information: 0 : End(190d2d0d-66dd-4af9-9274-61e87c2ace04)
SignalR.Transports.TransportHeartBeat Information: 0 : hashCode=19715510 value= path=/signalr/connect
SignalR.Transports.WebSocketTransport Error: 0 : Failed to raise disconnect: System.NullReferenceException: Object reference not set to an instance of an object.
   at WebApplication.Features.Authorization.AuthorizationHub.OnDisconnected() in d:\signalr\dev\samples\WebApplication\Features\Authorization\AuthorizationHub.cs:line 21
   at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.Disconnect(IHub hub) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\HubDispatcher.cs:line 301
   at Microsoft.AspNet.SignalR.Hubs.HubPipelineModule.<>c__DisplayClass13.<BuildDisconnect>b__11(IHub hub) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\Pipeline\HubPipelineModule.cs:line 114
   at Microsoft.AspNet.SignalR.Hubs.HubPipeline.Disconnect(IHub hub) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\Pipeline\HubPipeline.cs:line 54
   at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.<OnDisconnected>b__22(IHub hub) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\HubDispatcher.cs:line 391
   at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.<>c__DisplayClass2b.<ExecuteHubEvent>b__27(IHub instance) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\HubDispatcher.cs:line 423
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.ExecuteHubEvent(IRequest request, String connectionId, Func`2 action) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\HubDispatcher.cs:line 423
   at Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnDisconnected(IRequest request, String connectionId) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\Hubs\HubDispatcher.cs:line 391
   at Microsoft.AspNet.SignalR.PersistentConnection.<>c__DisplayClassa.<ProcessRequest>b__9() in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\PersistentConnection.cs:line 274
   at Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) in d:\signalr\dev\src\Microsoft.AspNet.SignalR.Core\TaskAsyncHelper.cs:line 695

@philbarresi
Copy link

I can only reproduce issue using Web Sockets or Server Sent Events. Using Forever Frame or Long Polling makes me have a user on disconnect.

Edit: Actually, the SSE issue appears to have been a fluke. It is now working as expected for me using Server Sent Events. Previously, I would connect with SSE and get a series of disconnects in rapid procession where the user was null. Now it connects and disconnects just fine.

@gustavo-armenta
Copy link
Contributor

OK, confirming issue only repro on websockets

@davidfowl,
The problem is AspNetWebSocket.CloseOutputAsync() modifies several properties on the request, including setting request.User to null. Of course, its executing before Hub.OnDisconnected() body.

@halter73
Copy link
Member

@gustavo-armenta Please include issue numbers in your commit messages, e.g. #2753. You should also include issue numbers in your PRs.

This makes life much easier on those going back through old issues and trying to figure out how the issues were resolved.

8bbec11

@abnanda1
Copy link
Contributor

@gustavo-armenta can you merge this change into dev

@Xiaohongt
Copy link
Contributor

Verified that with fix Context.User is not null OnDisconnected event

@HamedBagheri1992
Copy link

        app.UseCookieAuthentication(option);
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        *** must be in the End or after Create Cookie ***
        app.MapSignalR();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants