HttpContext is NULL when running web app in IIS - asp.net-core

I have two application, both running on the same Windows machine. One application is IdentityServer4, and the other is my own web application (Server side Blazor app).
Both web apps are build with .NET Core 3.1.
When I navigate to my web app, I first get redirected to my IdentityServer4 app. I login, and after that I get redirected back to my web app.
The login was successful, because there are no errors in the logs of IdentitServer. Also, I see a certain claim value on my Blazor webpage. I display this claim through CascadingAuthenticationState in my Blazor page. Through that path everything works fine.
But, whenever I try to get the logged in user through HttpContext in my "code behind" files, I get a Null reference back. For example:
public UserService(IHttpContextAccessor httpContextAccessor)
{
// HttpClient is NULL...
var httpCtx = _httpContextAccessor.HttpClient;
}
The strange thing is, that it all works fine when I run my application locally in Visual Studio. When I debug in Visual Studio I see that the HttpContext is set with all my user data.
But, for some reason HttpContext is NULL when I run the app from IIS.
How can I solve this issue?

If the HttpContext null-reference exception happens after deployment to Azure App Services or IIS, you might have forgotten to enable WebSockets.
Here is the deal:
If the app runs on Windows with IIS: WebSockets must be enabled.
See the IIS/IIS Express support section.
It seems that this is a prerequisite that you have to follow. I only recently discovered this myself after dealing with the same issue and deciding to publish my app to Azure from within Visual Studio. After I did so, Visual Studio gave me a nice warning telling me to enable WebSockets protocol on the Azure App Service.

To enable websockets in azure app service. Open app service in azure portal -> configuration -> general settings -> websockets on or off. Described here

Related

ASP.NET Core Microsoft authentication callbackpage page not found

I have implemented Microsoft authentication using IIS Express and everything worked as expected (like the one from https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/microsoft-logins?view=aspnetcore-5.0).
However after I publish it to IIS, when a user tries to access the application, instead of the Microsoft login page, I get a page with the message
No webpage was found for the web address: <redirecturl>?code=...
I should mention that there is no other way to login. Only the Microsoft one has to be supported.
After further investigation I found out from where the problem was.
The server was protected and the IIS did not have access to the internet and a proxy was required. Hence the reason on IIS Express was working on the development machine but on the server IIS did not.

SignalR failing to authenticate via cookies

I have a couple of projects:
Chat - SignalR backend (ChatHub)
Web - MVC project that hosts clientside scripts, including those that make calls to the Chat project
I'm in the process of migrating from .NET Framework to .NET Core and am moving to SignalR for Core as part of this work. Cookie authentication is working correctly on the old version, but upon migrating to SignalR for Core, I appear to be having problems.
Cookie authentication is enabled in both projects. The Web project works fine and the Auth cookie is correctly recognised and used for authentication. The Chat project, however, is not correctly authenticated against the cookie, despite the cookie being included at least in the negotiate request:
When I make a call to the ChatHub, Context.User.Identity.Name is empty. The same call returns a populated name when run on the Web project. If I decorate the ChatHub with [Authorize], the call fails with a 401.
Here's a minimalistic repro project showing the issue.
I assume the problem is related to the Authentication I have configured, or perhaps the cross-domain nature of the call?
This documentation is pretty unhelpful, and only says the following:
In a browser-based app, cookie authentication allows your existing user credentials to automatically flow to SignalR connections. When using the browser client, no additional configuration is needed. If the user is logged in to your app, the SignalR connection automatically inherits this authentication.
This appears under some very basic configuration, which basically only calls app.UseAuthentication(). Alas, that configuration does not work for me.
How do I set Cookies authentication in SignalR for Core so it works across two projects?
The issue is that by default, the Data Protection system that ASP.NET Core uses to encrypt the auth ticket isolates apps from one another.
You need to configure data protection on each project you wish to share protected payloads to use the same key ring and app identifier:
services.AddDataProtection()
.SetApplicationName("<appName>")
// as well as the following calls if your projects are to be deployed on different machines
.PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>"))
.ProtectKeysWithAzureKeyVault(new Uri("<keyIdentifier>"), new DefaultAzureCredential());

How can I use Azure AD B2C to authenticate users on the server before serving a hosted Blazor WebAssembly app?

I have a Blazor WebAssembly app. It's self contained and doesn't use any web API calls. I'd like to add authentication using my existing Azure AD B2C tenant so that only registered users can access the app.
Microsoft says that:
In Blazor WebAssembly apps, authorization checks can be bypassed because all client-side code can be modified by users.
So rather than host my Blazor app statically (the standalone model), I'd like to use the ASP.NET Core hosted model (so an ASP.NET Core app serves the Blazor app to clients). That way I can do the authentication/authorization on the server - if the user is registered and is allowed access to the app, the ASP.NET Core app serves them the Blazor app. If they aren't, they can be shown an error page or be redirected.
The issue is that I'm not sure how to implement this.
When I create a new Blazor WebAssembly Hosted app from the template in Visual Studio 2019, it creates three projects. A shared project, the Blazor project, and a Server project. The Server project has a reference to the Blazor project. This line appears at the end of the Configure method of Startup.cs:
endpoints.MapFallbackToFile("index.html");
This seems to be the thing that makes it serve the Blazor app to the client. I'm not sure how I can add authentication/authorization to this. I tried modifying this line to look like this:
endpoints.MapFallbackToFile("index.html").RequireAuthorization();
But the app still loads without redirecting to a login screen first.
There is some Microsoft documentation called "Secure an ASP.NET Core Blazor WebAssembly hosted app with Azure Active Directory B2C" which sounds like it's what I need, but it's actually still doing the authentication in the Client app while also securing API calls to the Server app (which I don't need).
Is there any way to accomplish what I'm trying to do - authenticating the user on the server before serving the Blazor app, rather than doing that authentication in the Blazor app itself?
The answer was really simple. Actually, the RequireAuthorization() call does work. If you're already logged in to B2C you won't be redirected to the login page first (and, in Edge at least, it doesn't even visibly redirect to B2C first before redirecting back to the app, hence the confusion). But if I load the page in a private browser window I am redirected to the B2C login page - so it must be working as intended.
For future reference, the answer to the title question is:
Add auth to the ASP.NET Core Server app if you haven't already.
In the Server app, add a project reference to the Blazor app.
Add the following line to the UseEndpoints call inside the Configure method in Startup.cs:
endpoints.MapFallbackToFile("index.html").RequireAuthorization();

Host Asp.net Core Web Api locally

I am learning Asp.net Core Web Api. I need to access the api from a flutter application but am not ready to host the api on Azure. What are my options if I want to host the api locally on my computer so I can access it from another application like my Flutter app client, and is there any tutorials I can follow to learn how to implement the solution.
There are several ways to go about this, here are some options:
FROM VISUAL STUDIO: You can simply run the ASP.NET Core Web API from Visual Studio in Development Mode by Pressing F5
FROM COMMAND PROMPT: Run the API Project from the command line by opening a command prompt window in the root project folder of the project and use the dotnet run command. See here for more info about the command: dotner run command
HOSTING IN IIS: I am assuming you are running a windows OS. You can turn on IIS and its features. Simply follow the instructions on this page: Host ASP.NET Core in IIS on how to deploy ASP.NET Core to IIS. The advantage of this is that you have the application always running while you work on your flutter application locally.
I hope this helps you resolve your situation.
What are my options if I want to host the api locally on my computer so I can access it from another application like my Flutter app client, and is there any tutorials I can follow to learn how to implement the solution.
If your application is developing now, there is no need to host the application and let the Flutter app client to access. We could build some json file as the right format like web api response to develop the client app.
If your client application and web api has now developed successfully, you want to host the web api to let fluent app or other application to access from internet. You should have a public IP address and host the application on IIS or else. Public IP address you should ask for the IP provider company. Without a public address, the client side app couldn't access your application from internet.
If your web api and the client app are in the same intranet, you could let the client app directly access the web api after the web api hosted on IIS by using hosting server's IP address.
About how to host the asp.net core application on IIS, you could refer to this article.

ClickOnce, Azure, and ASP.NET Core

I have an ASP.NET Core application published to Azure. It contains companion application published using ClickOnce.
When I look at the web server's console, I see all of the necessary ClickOnce files. And I can launch the application using http://mysite.azurewebsites.net/tools/MyApp.application as expected.
But if I click on http://mysite.azurewebsites.net/tools/setup.exe it fails with a 404 error.
I'm assuming that the ASP.NET application is preventing "setup.exe" from being exposed, but I don't know how to alter that configuration.