Aspnetcore: Add support to SignalR for Session

Created on 17 Aug 2018  路  24Comments  路  Source: dotnet/aspnetcore

Design area-signalr enhancement triaged

Most helpful comment

Yes, we'd like a way to maintain state across connections for the same user.

All 24 comments

What's the context here? SignalR doesn't really have a way of clearly tracking the Session since it involves multiple requests, this is why Context.Items exists, for storing per-Connection metadata.

@davidfowl In server-side Blazor projects we run Blazor on the server and then use SignalR to send UI updates to the browser and to send event notifications back to the server. We'd like to have a way for app developers to maintain state across connections.

Is Context.Items not sufficient for this? That's a dictionary that is maintained across the entire life of the connection. Or do you need direct access to the existing Session data?

maintain state across connections

Across multiple connections by the same user?

Yes, we'd like a way to maintain state across connections for the same user.

We've had some discussions about this, but all of them require fairly significant work we don't have resources for in 2.2, so I'm putting this in 3.0 for now.

Any updates? @danroth27 @anurse
This is really waaanted! ^_^

No concrete updates, and nothing planned for 3.0 (as most of the major feature work is winding down for that release), but this is still on our mind. One option we are considering is a mechanism to allow connection state to survive across reconnection (right now when you reconnect, it appears as a completely different connection). You would be required to use sticky sessions (which we already require anyway). The connection ID would be the same, and you'd have the exact same ConnectionContext (including the Items dictionary) across this gap. There is no committed release for this functionality but we're doing some exploration here.

Does this help with your scenario? Perhaps you can provide more information on what you need for your application.

@anurse Thanks for giving me a reply back.

That could possibly be a solution yes. In short, what I just want is some functionality where I can store a UserID after validating a User's Username and Password for my Administration App. Sessions is the obvious first-choice for me since it doesn't _dissappear_ when you refresh.

I'm using Blazor, which is why there's limited things I can try. I'm open to other things than Sessions, but I just need something where I can store "User Information" like a UserID so I know that a user has logged in and you can show their information accordingly.

I tried using IDistributedCache which in short does work, however there's no identifier of the connection I can use as everytime you refresh a Blazor App, it treats the whole thing as a completely new "session"/"Connection", as you pointed out.

Would you know of any other way of achieving what I want, that is not dependent on Sessions?

I tried using IDistributedCache which in short does work, however there's no identifier of the connection I can use as everytime you refresh a Blazor App, it treats the whole thing as a completely new "session"/"Connection", as you pointed out.

Why can't you use the current user id?

I'm using Blazor

Also, I believe Blazor does have a persistent ID (the "circuit ID") across multiple connections. I don't know what, if any, access you have to store data associated with that ID though. (cc @rynowak)

@davidfowl I tried, but it seems like that ID changes every time I refresh the browser.

The Context.UserIdentifier value wouldn't change if the user was authenticated. That's derived from the HttpContext.User value. The Context.ConnectionId value will change.

@anurse I see.. how do you authenticate with Context.UserIdentifier?

Well, it's up to you to handle authentication. Once authenticated you have two values to go on:

  • Context.User - The full ClaimsPrincipal provided by authentication. You can use whatever value your auth system provides to key user-specific data
  • Context.UserIdentifier - This is a single claim from Context.User that SignalR picks to use as the ID used to "select" this user in Clients.User(userId). It's determined by the IUserIdProvider component (there is a default one that selects the ClaimTypes.NameIdentifier claim, but you can override it)

For both of these though, you are dealing with a user-level attribute, so if a user has two tabs/windows open, both will have the same value for this property. A "session-level" (i.e. per browser tab/window) attribute doesn't exist in SignalR right now.

@anurse That makes alot of sense, and is probably what I want, but what I was asking is how to handle the authentication itself. Is there a Class/Function in Blazor Components I can call to "Log In/Authenticate" ?

Ah I see, ASP.NET Core has a common authentication model and I believe Blazor will tie in to that (but I'm not positive, cc @rynowak). There are docs for that on our Documentation site (that link starts with ASP.NET Core Identity, which is a full identity management system but there's a whole tree-view of articles on the left, including 'Use cookie authentication without Identity' which go into more detail).

@kevinjpetersen We have implemented integrated authentication and authorization support in Blazor for our up coming .NET Core Preview6 release. You can read about it here: https://github.com/aspnet/AspNetCore/issues/4048

@danroth27 Very nice! Does this make it so you can have user states across refreshes / close/open of tabs? So when authenticating, you have the user be logged in, not dependent on the Blazor SignalR connection (in case it disconnects etc)?

@kevinjpetersen The authentication support we are adding for Preview6 is based on ASP.NET Core Identity. When the user logins in, their identity is established using a cookie, which will survive browser refreshes and closing/opening tabs.

@danroth27 Amazing! Can鈥檛 wait for Preview 6 馃槉 Thanks for taking the time to answer my questions! :)

@danroth27 I don't think Blazor needs this any more, correct? If it's still something you'd want, we can chat some more about it.

In general, ConnectionContext.Items is the expected storage for long-running data related to a single connection. We are investigating the ability to reconnect a SignalR connection (maintaining the same ConnectionContext structure) which would solve the long-running issues described above.

I'm interested in hearing from people outside of Blazor to see what the scenarios are for this.

@anurse You are correct, ConnectionContext.Items could in theory be used IF it acts the same as Sessions, meaning that even if the SignalR connection drops/disconnects.

If this can't be the same (due to SignalR restrictions), Sessions would still be very much needed.
I'm currently using Sessions in a Blazor Application. I haven't had any issues so far, but I'm assuming that it's obviously not optimized.

Personally, I would still prefer sessions, unless the above could be done.

The problem is that for Session to work across connections you need a unique ID that survives across multiple connections. Then you get in to the same set of problems you have with Auth Tokens since that ID needs to be protected as it could be used to impersonate another user and get access to their session. That's why it's very hard to put it on our radar right now because it's got a lot of complexity.

It's definitely very unlikely that we'd be able to align a Session from a standard HTTP requests with one for SignalR, since correlating those isn't trivial.

I'd expect we're more likely to do transparent reconnect (which would make ConnectionContext.Items just work) than actually support Session natively.

What it comes down to is this: We are aware of the desire to maintain state across reconnects, and we're tracking that in our feature planning for future versions (possibly 5.0, but not confirmed yet). I'm trying to understand if there are specific needs for Session to work so we can decide how to deal with this issue.

Since we don't have any pending plans for this, I think we can close this issue.

Was this page helpful?
0 / 5 - 0 ratings