MVC Core Windows Authentication not working - asp.net-core-mvc

I'm trying to set up an MVC Core Web App with Windows Authentication in Visual Studio 2022 but I can't get it to work.
I create a new project and select the Windows Authentication option. I immediately try to run the app but I get a blank page.
For troubleshooting I then added the following else clause so I can see what the problem is on my development machine.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
else
{
// Development Environment
app.UseStatusCodePages();
}
and I can then see that I have a '401 Unauthorised' status code. And then if I add [AllowAnonymous] to my Index action I can finally see the home page but my windows username is not displayed. I would expect to see 'Hello username' displayed in the top right but I don't seem to be authenticated, let alone authorized.
Apart from the two troubleshooting steps above, this is a brand new project straight out of the box but I've pasted my Program.cs below for reference.
What do I need to do to get Windows Authentication to work?
Thanks
using Microsoft.AspNetCore.Authentication.Negotiate;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
else
{
// Development Environment
app.UseStatusCodePages();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();

You can follow my steps to fix the issue.
Enable IIS features in your develop machine, this just want to enable Windows authentication on Windows.
Tips: Please expand all the fields and tick them, then click Apply.
Delete the .vs folder inside your project, this steps just want to reset the applicationhost.config.
The latest step, we need to double check the settings file in project.
Then the issue should be fixed now.

Related

Does Visual Studio Publish to App Service feature deploys items in appsettings.json to the configuration blade in the Azure portal

I am using Visual Studio 2022 to build an ASP .NET Core (v6) application.
I need to deploy and run my application on an Azure App Services instance.
I have many settings in my application's appsettings.json file. The file is included in the deployment package as shown here:
I use Visual Studio 2022 Publish feature to deploy my asp.net core application to an Azure App Services instance:
After a successful Visual Studio Publish, none of appsettings.json file settings show in the configuration blade:
Questions:
1- Is there any way Visual Studio publish feature deploy appsettings.json settings to the App Services' configuration blade?
2- Even after a successful deployment, my application does not read the settings in the appsettings.json. It seems that all ignored. I checked and on my local visual studio developer environment, my app reads appsettings.json, but not when it is deployed to App Services. Why the deployed app ignores the appsettings.json settings?
Update 1: program.cs and appsettings.json
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Logging.AddAzureWebAppDiagnostics();
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApplicationInsightsTelemetry();
builder.Services.AddScoped<Framework>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
appsettings.json could be anything. Just need to read its content with a ConfigurationManager instance like how I read them when the site is running locally in Visual Studio.
Is there any way Visual Studio publish feature deploy appsettings.json` settings to the App Services' configuration blade?
The deployed appsettings.json file will be available in KUDU Debug Console.
In your Azure App Service => Advanced Tools => Go => Debug Console => cmd => site => wwwroot.
Or even you can open the KUDU with the below URL
https://YourAppServiceName.scm.azurewebsites.net/
Configuration section will not display the setting which are in appsettings.json file. It is used to override the available settings from appsettings.jsonfile.
The values which you want to override and the new values which you want to add after deployment must be set in the Application Settings in portal.
The key name must be same in both appsettings.json and Configuration => Application Settings.
My sample appsettings.json :
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MyVal": "Local Connection"
},
"AppSettings": {
"MySettings": "Local Settings"
}
}
Code to retrieve values from appsettings.json
var MyAppSettings = builder.Configuration.GetSection("AppSettings");
var LocalAppset = MyAppSettings.GetValue<string>("MySettings");
OR
var MyAppSettings1 = builder.Configuration.GetValue<string>("AppSettings:MySettings");
Index.cshtml
#page
#model IndexModel
#using Microsoft.Extensions.Configuration
#inject IConfiguration Configuration
<h2>Configuration value for 'AppSettings': #Configuration["AppSettings:MySettings"]</h2>
I have deployed the app and able to read the values from the deployed code.
Initial Values
Overridden Values

Authentication from Development to Release

I have a small web project to develop for a friend that will be incorporated into a small existing website using Visual Studio 2015.
A user has to be logged in, requiring a secure connection. I cannot use the existing website to authenticate with their SSL/Certificate during development because the URL will not be the same (or at least I don't know how).
Social media logins or traditional email/password logins can get involved to implement (new user, existing user, lost passwords, change passwords). I have only done it once before, so I would rather not have to change all of those settings from the development site to the existing site after it all gets working.
How do experienced people do this?
I would solve it using separate configuration files for each environment.
Each environment has specific configuration in its own file:
Each config file can have different security-concen configuration:
appsettings.Local.json
{
"TokenValidationConfig": {
"ValidAuthority": "https://localhost:8394",
"RequireHttpsMetadata": "false"
},
"HttpsConfig": {
"CertificateIdentifier": "Unnecessary for local env"
}
}
appsettings.Prod.json
{
"TokenValidationConfig": {
"ValidAuthority": "https://xxx.xxx.com"
},
"HttpsConfig": {
"CertificateIdentifier": "https://xxx.xxx.vault.azure.net/secrets/wildcard-xxx-xxx"
}
}
Current environment is specified in environment variable, and then is read on startup:
new WebHostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var envName = hostingContext.HostingEnvironment.EnvironmentName;
config
.AddJsonFile(
path: "appsettings.json",
optional: false,
reloadOnChange: false)
.AddJsonFile(
path: $"appsettings.{envName}.json",
optional: false,
reloadOnChange: false);
Consider official documentation on the matter:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1#json-configuration-provider

How can I deploy a Blazor server-hosted application from Visual Studio 2019

I am using VS2019 Preview.
I have created a "server-hosted" Blazor application using the latest Blazor extension (16.0.19227). This is the variant that contains 3 separate projects...
MyApp.Client
MyApp.Server
MyApp.Shared
I can debug this by making MyApp.Server the active project and all works fine but I'm struggling to publish/deploy this to Azure. I have tried the following...
Right-click on MyApp.Server in Solution-Explorer
Choose "Publish"
Go through the wizard to create a new publish profile
Change the deployment mode to "self-contained"
Hit publish
At this point I get an error during deployment...
CSC(0,0): Error CS0006: Metadata file 'D:\work\Applications\Web\MyApp.Client\bin\Release\netstandard2.0\win-x86\MyApp.Client.dll'
could not be found
This appears to be because the "Target Runtime" in the web-deploy profile is set to win-x86. The client application is actually being built as
"D:\work\Applications\Web\MyApp.Client\bin\Release\netstandard2.0\MyApp.Client.dll"
(without the additional win-x86 subfolder) so the deployment process seems to be making an incorrect assumption about the paths used by the build process. There's no way in the publish dialog to specify a blank/don't care target runtime.
Is there a workaround for this or perhaps I am using the wrong approach for deployment?
There is some official documentation but it's not very helpful.
Update It seems that the deployment is using the output path of the Client project and then just appending netstandard2.0{Target Runtime} to it so changing the output path in the Client project is not enough to work around the issue.
Update 2 Removing the RuntimeIdentifier tag in the publish profile by editing the xml simply results in deploy-time error stating that an empty RuntimeIdentifier is incompatible with a self-contained deployment. Unfortunately the self-contained deployment is necessary because Azure does not yet host .net core 3 directly.
because Azure does not yet host .net core 3 directly.
But it does.
In the Azure Portal, go to your WebApp after deployment (or create one beforehand).
Go to Extensions and click Add [+] and select ASP.NET Core 3 (x86 for the free hosting).
Also go to Settings, General and enable WebSockets, they're Off by default.
Temporary:
Note that Preview-6 is not available as an extension, so either use Preview-5 or deploy as self-contained.
Couldnt put a picture in the comment, so I thought i'd show it here. This is my current publish wizard.
Just did it with a brand new project via new project -> Asp.net core web application -> blazor (Asp.net core hosted) built and published fine to azure app service fine.
My answer is:
Configure the publish profile to "Self-contain" deployment mode.
Edit all .csproj files to change <TargetFramework>...</TargetFramework> node name to <TargetFrameworks>...</TargetFrameworks>. (see also: https://stackoverflow.com/a/42855070 )
Fix the web root folder path string at runtime in Startup class like below.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Serialization;
using System.IO;
using System.Linq;
namespace BlazorHostedOnAzure.Server
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddNewtonsoftJson();
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseResponseCompression();
// ---- APPEND PART.1 BEGIN ----
var clientBlazorWebRootPath = default(string);
// ---- APPEND PART.1 END ----
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBlazorDebugging();
}
// ---- APPEND PART.2 BEGIN ----
else
{
if (env.WebRootPath != null)
{
var pathOfIndex = Path.Combine(env.WebRootPath, "index.html");
var pathOfContent = Path.Combine(env.WebRootPath, "_content");
if (!File.Exists(pathOfIndex) && Directory.Exists(pathOfContent))
{
clientBlazorWebRootPath = Directory.GetDirectories(pathOfContent).FirstOrDefault();
if (clientBlazorWebRootPath != null)
{
env.WebRootPath = clientBlazorWebRootPath;
}
}
}
}
// ---- APPEND PART.2 END ----
app.UseClientSideBlazorFiles<Client.Startup>();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
});
// ---- APPEND PART.3 BEGIN ----
if (clientBlazorWebRootPath != null)
{
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(clientBlazorWebRootPath)
});
}
// ---- APPEND PART.3 BEGIN ----
}
}
}
I published my sample code and README on the GitHub my repository.
https://github.com/sample-by-jsakamoto/BlazorHostedV3Preview6OnAzureWebApp#how-to-configure-client-side-blazor-v300-preview-6-that-is-hosted-on-an-aspnet-core-server-to-deploy-it-to-azure-at-13-jul-2019

How do environment variables and appSettings file(s) get used during publish?

If I have two settings files
appSettings.json and appSettings.Development.json
When I use publish from Visual Studio, are both supposed to be copied to the target folder? I'm not sure, because they both show up in the target folder (on a dev server) when I publish. I was under the impression that they combined at build time and ONLY the appSettings.json file was published. If not, then do I need to consider manually coding for these differences as Ive seen in a few examples ?
eg. This example is loading the settings via code (NOT how Im doing it)
Note - they are using the environment name, ASPNETCORE_ENVIRONMENT setting
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
Some of my Startup class is shown below.
Note: I am not referencing the environment setting.
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
[ Update ]
I found my answer here - the key I was missing was updating the csproj file for the publish settings related to environment.
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/aspnet-core-module?view=aspnetcore-2.2#configuration-with-webconfig
So I assume that if I have several different environments, each with its own settings file, that a publish would result in putting ALL of them out to the target dir?
It's a bit confusing with ASP.NET Core, especially if you're coming from having worked with ASP.NET previously. The build configurations (Debug, Release) really have no bearing on anything that happens with ASP.NET Core. An ASP.NET Core app is technically environment-agnostic. Whereas with an older ASP.NET app, you'd have to publish for a specific environment, you can theoretically take the same ASP.NET Core publish and run it in any of your environments. This is of course aided by the fact that Web.config is not utilized by ASP.NET Core.
This, then, is the reason why all the environment-specific JSON files come along for the ride. Which is ultimately used is based on the value of the ASPNETCORE_ENVIRONMENT environment variable set at runtime, not which build configuration you chose when publishing. Which is actually really nice when you think about it. You can take the same published app, run it in your "staging" environment to ensure everything is working and then deploy it to your "production" environment, simply by ensuring that each environment has the appropriate value for ASPNETCORE_ENVIRONMENT set. This makes release pipelines trivial.
That said, it's still possible to use things like the #if DEBUG compiler directives, and if you do that then there will be differences in your ASP.NET Core app depending on the build configuration chosen, but you should really avoid doing that in the first place. In general, you should rely only on the IHostingEnvironment abstraction in an ASP.NET Core app to determine what happens in what environment.

Silverlight Business Application Windows Authentication

I cannot seem to get Windows Authentication to work in the Silverlight Business Application.
I have made the changes required see below
Changed to Windows authentication in App.xaml
public App()
{
InitializeComponent();
// Create a WebContext and add it to the ApplicationLifetimeObjects
// collection. This will then be available as WebContext.Current.
WebContext webContext = new WebContext();
//webContext.Authentication = new FormsAuthentication();
webContext.Authentication = new WindowsAuthentication();
this.ApplicationLifetimeObjects.Add(webContext);
}
Changed to Windows authentication in web.config
<authentication mode="Windows"/>
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider"/>
I put a breakpoint on the Application_UserLoaded event but nothing happens:-
private void Application_UserLoaded(LoadUserOperation operation)
{
foreach (var r in WebContext.Current.User.Roles)
{
//do something
}
}
Can anyone suggest what is going wrong. I have made no other changes to the project at all.
This happened to me previously as well. It turned out that Silverlight debugging wasn't enabled in the properties of the Web project. Right click on the .Web project and click on properties. Next click on the Web tab and on the bottom ensure the Silverlight checkbox is checked.
You must have this line in the Application_Startup:
WebContext.Current.Authentication.LoadUser(this.Application_UserLoaded, null);
This will automatically authenticate a user when using Windows authentication.

Resources