Updating a Web Application in IIS - Best practices - iis

What are the best practices for updating a web application in IIS?
The first page you see when you visit our application is a login page.
What I want to achieve is that visitors be redirected to a page stating that the application is being updated. And for users with an admin role being able to login successfully (to check whether everything is working properly)
In web.config we keep track of wheter the application is being updated (updating = [true|false] and then on the authentication_event:
if (updating)
{
if (User.IsInRole("admin"))
{
redirect to main web app...
}
else
{
redirect to web being updated page....
}
}
else
{
redirect to main web app..
}
Any advise will be appreciated immensely..

I test everything locally, then I use the built in app_offline.html file on production server.
When this file is present it will be served to clients, in meantime I am uploading new content. When done, renaming app_offline.html to something different and the new app starts.

instead of doing it via web.config, you should be saving the updating flag in some other xml file or database, as each time you update your web.config file, your application restarts, thus invalidating current application variables, caches, etc etc
apart from that, you got the other logic right. but avoid touching the web.config as far as possible - i personally only save the connection string in the web.config as that hardly changes
but rest of the key value pairs which change often, i have them saved in sql database table. so that way i never ever have to do an application restart unless my connection string changes :-)

Looks like you pretty much have it figured out.
if (WebConfigurationManager.AppSettings["updating"]=="true")
if (User.IsInRole("admin"))
Response.Redirect("~/Main.aspx");
else
Response.Redirect("~/Updating.aspx");
else
Response.Redirect("~/Main.aspx");

Related

ASP.NET Core 5 MVC web app returning bad request errors in some pages after deployment to IIS

I have tried everything. I configured Windows Server 2019 according to Microsoft documentation and I successfully deployed a .NET 5 web application to the IIS.
I can get to the login page. I can even get to the forgot password page and they show themselves fine. However when I try to do any action (send the forgot password link or login to the page) I get a "Bad Request" from the server. I haven't found a way to explain why.
I have tried several, and I mean several things found Googling around but nothing helps. This include disabling https within the .NET Core application, trying to get a detailed error page using the app.UseDeveloperExceptionPage(); instruction inside Startup, etc etc but nothing works. I always receive this page trying to execute any action:
If someone could help or point me into the right direction, I will really, REALLY appreciate it.
Thank you
PD: In case it has anything to do with the problem, the error, at least the two that I can reproduce (because I can't even log in), happens, I think (maybe don't) when redirecting to another page in Microsoft Identity.
EDIT: code was asked by one of you. Thank you.
As you see, there's nothing specific in the forgot password screen for my application. This is scaffold code from Microsoft Identity. I even edited it and just let one line of code inside it, which is the default return code anyway as follow:
public async Task<IActionResult> OnPostAsync()
{
return RedirectToPage("./ForgotPasswordConfirmation");
}
As you can see, there's nothing special with that code. Here's the html that calls it, again, is a scaffold of Microsoft Identity with little to no changes (by little, I mean, maybe some CSS and a new value of view data):
But then again, forgot password page actually shows and seems well in the front end, but immediately I try to enter my email and click enter in this page, (also, just a scaffold of Microsoft Identity):
Nothing happens. I receive the bad request. There's NO magic nor custom code here. Something silly is going on.
EDIT II: YES, locally it works perfectly. The strange behavior happens only when deployed to IIS.
EDIT III: I coded and enabled logging in my .NET Core APP and wrote that to a file, and I think I finally got, at least the error (not the reason yet):
But why?? Cookies are enabled in the server browser without avail, same issue. Someone has a better idea than disabling anti forgery rules to login and forgot password pages?
Thank you
For some reason, when I deployed the first version of my app into IIS, I thought it was a good idea to just browse it from the IIS link. Of course, in a new mounted Windows Server 2019, IE is still the default browser. I connected directly to the IP of my web app via VPN, but used Chrome this time. Guess what? All problems disappeared. Yes, it's a bad idea to try to use a modern framework like .NET Core Identity with IE.

How to avoid running entire client-side process in Blazor WebAssembly before Azure AD authentication?

I'm building a Blazor WASM app with Azure AD, and I'm struggling with what appears to be an inefficiency in the way it's designed. The entire application, including the home page, needs to be secured by [Authorize]. It works (with one exception noted below), but the initial load is painfully slow. Basically, on reaching the home page, Blazor loads the entire application -- running Program.Main in it's entirety, loading JS files from CDN or webpack bundles, loading all the .NET dlls, and THEN decides that it needs to redirect to Azure to authenticate. Once it returns, it does all that again. Loading the various files is not too much of a problem, since it gets them from the browser cache the second time. The problem is that is also needs to run Program.Main again.
In my rather large client app, it takes a few seconds to configure all the services (I'm using a lot of gRPC). The biggest culprit though is a call to the server API to get certain app settings that I don't want to expose to the client (basically doing this). Moreover, that API call doesn't even succeed, since the API endpoint is secured, and the user hasn't authenticated yet, but I don't know how to get the user info from within Program.Main. The log messages show that the user identity is not even created until sometime after Program.Main completes. (One of the settings is the roles-to-permissions mapping, so I can't even draw the app's menu without it. I've resorted to removing the auth requirement from the API controller for now, obviously not a permanent fix)
To replicate the behavior, just create a brand new Blazor WebAssembly app, selecting Auth Type = Microsoft identity platform, and checking the ASP.NET Core hosted box. Then just edit both appsettings.json files to provide your Azure login info; change the requested scope in Client.Program.Main (and change the one in WeatherForecastController to match); and add [Authorize] to the _imports.razor file, and [AllowAnonymous] to Authentication.razor. Finally add some logging Console.WriteLine("Running in Client.Program.Main"); near the end of that method.
In the basic Blazor app template as described above, this all runs pretty fast. Once there's a significant amount of startup code in Program.Main, though, it becomes quite noticeable, it can be several seconds both before and after the login redirect. And I can't make an authenticated API call.
Specifying endpoints.MapFallbackToFile("index.html").RequireAuthorization(); in the server side Startup doesn't seem to make any difference. Neither does adding options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); to the AddAuthorization call.
So basically, I'm looking to:
Identify the user in Client.Program.Main, so I can make a secure call to the settings API
Identify the user in Client.Program.Main, so I can bypass all the time-consuming stuff myself on the first pass
Get Blazor (server?) to somehow recognize that a request for a protected page will fail for an unauthenticated user, and go directly to the Azure login page without all the usual ceremony
Any suggestions?

UseLegacyUI Setting Not Working

I have ran a SQL script to update the UserPreferences.UseLegacyUI to 0 for all of the users in our 2018 R1 system but, the users are still getting the classic UI when they log into the system. Any thoughts on why this might be? We're trying to avoid every user having to change their setting in their profile.
EDIT: Users are having to switch to the modern UI every time they log in. Is there a cookie involved?
Try using the UserPreference graph to change that value, that's how it's used in 'Main.aspx.cs'. Sometimes there's code in event handlers that needs to be executed too:
PX.SM.SMAccessPersonalMaint prefGraph = PX.Data.PXGraph.CreateInstance<PX.SM.SMAccessPersonalMaint>();
PX.SM.UserPreferences prefs = prefGraph.UserPrefs.SelectSingle() ?? prefGraph.UserPrefs.Insert();
prefs.UseLegacyUI = false;
prefGraph.UserPrefs.Update(prefs);
prefGraph.Persist();
There was an HTTP redirect set in IIS on both the web site and the web application that was causing this. I suspect this was a hold over from the 5.3 installation but, not sure. Removing the redirect from the web application and removing the "/main.aspx" from the web site redirect cured this issue.

uCommerce Secure Ticket Transaction with Loggin

I'm working on a webshop in which it should be possible to subscribe to a service for a monthly 20$ fee in return.
I've made a script in a c# usercontrol which will be called monthly by umbraco scheduled task command:
<task log="true" alias="test60" interval="60" url="http://mysite/umbraco/subscriptionPayment.aspx"/>
For that I have two questions.
1) Where should I put the usercontrol in order to make it unaccessible for the public but accessible for the umbraco task command? It is very important that the script can only be accessed by local server commands.
2) I would like the script to log a file each time a transaction is made. I'm using the following script:
File.AppendAllText("paymentlog.txt",
"Transaction "+transactionNumber.ToString() +" sucessfully executed at "+DateTime.Now.ToString() + Environment.NewLine);
I just don't know which path I should give to the paymentlog.txt file since handling real paths in umbraco seems kind of obscure to me. I would like the paymentlog.txt file to be placed in the root umbraco folder. How do I do that?
Thanks in advance (I'm running umbraco 4.8 and uCommerce 2.6.1).
Best regards,
Brinck10
The task scheduler in umbraco isn't very reliable and this sounds like a crucial to your businness so i would probably try to use the build in scheduler in Windows on your server to do the processing.
That being said. In regards to marking the tasks scheduler approach a little more secure you could make the URL you are calling only accessible on localhost/127.0.0.1 and use localhost address in your task configuration.
You can make a call to the user service to verify that the caller is logged in. Following code will achieve that:
using UCommerce.Infrastructure;
using UCommerce.Security;
var authService = ObjectFactory.Instance.Resolve<IAuthenticationService>();
if (authService.IsAuthenticated())
{
// do secure code here
}

Kentico Forcing New Website

I have backed up the Kentico Database and website from one of our Live servers and placed it within our Dev server and configured the website in IIS.
When I navigate to the website, it currently asks for New installation.. Whereas it should just show me the current website.
How do I get it to show the website?
EDIT
The following error occurs when going ahead and creating a new instance with the restored Database:
Restore the backed up database and add database connection string to the web.config of the application. Simple as that :)
Who or what is set as the DB objects owner/schema in the DB? Does this match the setting in Site Manager (or, CMS_SettingsKey table)? I would make sure these two match.
Another option is that the connection string was not initialized by .Net - I would do a dummy change in the web.config file to force the app restart and/or also clearing the .Net cache.

Resources