-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Security implications of using IHttpContextAccessor in Blazor Server #45699
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
Comments
Thanks, @Bouke. I just found the following open issue to work further on this subject in SignalR docs. It wasn't apparent to me at first because it's labeled for the SignalR docs, not the Blazor docs and not tracked by the Blazor project. It might provide some helpful info to you while you wait for a response here ... Javier ... when you see this ... let me know if you'd like any additional guidance added to that bit in the Blazor doc. 👂 Also, the issue ☝️ has been languishing since 2019 without an assignee (but it is on Brady's master list of things to do). What I think will happen is that this will get covered in the SignalR docs. I'll cross-link to the new coverage from relevant Blazor-node docs. If that's not the plan, let me know what you'd like to do. 👂 |
I believe the issue is that Blazor server circuits survive across multiple SignalR connections. This is the same reason why you have to get the HttpContext within SignalR using The IHttpContextAccessor can be made to "work" somewhat by either:
|
So the security implication being referred to in the documentation would be the following:
So coming back to the circuit being the source of truth, I would still expect
Can you clarify what you mean by this, is this the scenario that I described above? For some background: I have a design where my business layer receives an |
Right, this is the same reason why it's unsafe to do use the IHttpContextAccessor in SignalR. The user attached to the Blazor circuit is updated but the IHttpContextAccessor never gets updated again.
Right, the async local captured by the initial SignalR connection is what will flow to the blazor circuit and subsequent requests, or connections will not update the async local you captured previously. PS: I wrote a things that can go bad with async locals article.
Try the scenario you listen above. If it's "working", it's definitely by chance and not intended 😄 (which means it's not really working). The HttpContext pointed to by the accessor gets disposed/reset after the request is over. There are many
To make it safe, it needs to be updated with the "right" instance of the HttpContext at the appropriate time (I haven't spent much time trying to understand what that is). Maybe you can update it in a circuit handler or in a hub filter. BTW if you just need the user an not the HttpContext, its cleaner to set |
I'm going to expand what we have in the Blazor Threat Mitigation doc and probably add a bit on this in the Blazor-SignalR Fundamentals doc. There's a bit on this in the |
All that @davidfowl mentions here is correct.
Use a |
Hi @Bouke. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time. |
@javiercn I think we should write a full example. |
@davidfowl do you mean for what I suggested? |
yep |
@davidfowl @Bouke here is a sample. |
@javiercn to make it a bit more realistic. The current user service needs to work for both MVC and Blazor server in the same application and the user service can't be coupled to ASP.NET Core at all (if I understand correctly). |
@davidfowl that would be no problem, you could set the user inside an action filter in MVC and it will work there too. There is no coupling to ASP.NET Core at all. |
@Bouke does this example help? Can you show an example of your user service definition? |
Thank you all so far for your investigation and feedback. The suggested solution doesn't cover ASP.NET Core, so further work would be needed in order to implement the
During the holiday season I might not be able to respond in a timely matter. Happ 🎄 ☃️! |
You might end up with a User for a different circuit if you use
Using a middleware will work for anything that is based on request/response. However, note that Blazor Server apps are not tied to a single websocket connection or HTTP request, so this won't work there.
For clarity, Blazor Server creates its own scope, so do not expect that you are able to get the same service on a regular HTTP request and inside of a circuit. You would need a different solution for that. As with regards to SimpleInjector, I don't know about it, so we can't help there. |
I don't think I follow. The
However the provided example doesn't work in ASP.NET Core, as In the end I want a I think integrating into ASP.NET Core like this is a rather common scenario, it is even documented here:
As we've established, the
|
This should work in both cases since there are 2 different scopes, so you'll get 2 different instances of the service. If you need to access the current user from a singleton service, then this won't work. |
I leave that as an exercise to you. In the end it comes down to registering a scoped service and setting the Value for it to the current user in the appropriate context before your application logic runs. That happens as described:
If you do not need to update the user after the app has started, the only code you need is inside OnConnectionUpAsync: public override async Task OnConnectionUpAsync(Circuit circuit, CancellationToken cancellationToken)
{
// This gets called every time the circuit reconnects, setting the user for the lifetime of the connection.
// Unless you implement updates.
var state = await _authenticationStateProvider.GetAuthenticationStateAsync();
_userService.SetUser(state.User);
} |
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes. See our Issue Management Policies for more information. |
I'd like @Bouke to confirm this works (so we can document it). Let's leave this open until after the holidays. |
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes. See our Issue Management Policies for more information. |
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes. See our Issue Management Policies for more information. |
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes. See our Issue Management Policies for more information. |
Hi @Bouke. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time. |
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate. See our Issue Management Policies for more information. |
(I originally posted this question on the Docs repository, but I was told to post it here instead.)
The documentation note the following on
IHttpContextAccessor
:The default
HttpContextAccessor
is implemented usingAsyncLocal
:https://github.com/dotnet/aspnetcore/blob/589aa11b5c631ce719e0530d66be8324a6d79169/src/Http/Http/src/HttpContextAccessor.cs#LL11C108-L11C108
I fail to understand the security implications of using
IHttpContextAccessor
in Blazor Server.AsyncLocal
in general must flow with the user's SignalR connection†. So that would also be the case for theHttpContext
stored in thisAsyncLocal
. This is also what we're seeing in our tests.IHttpContextAccessor
return a differentHttpContext
than the one that started the Blazor app? (i.e. another user)AsyncLocal
any different from other uses ofAsyncLocal
and (apparently) a security consideration?HttpContext
from the "context of the ASP.NET Core pipeline" safely to the Blazor Server app?† If that isn't the case, then all bets are off.
cc: @guardrex dotnet/AspNetCore.Docs#27944
The text was updated successfully, but these errors were encountered: