Setting up persistent forms authentication on multiple servers and subdomains - c#

I'm trying to set up forms authentication across multiple servers and subdomains. I have static machine keys set up for each application like so:
<system.web>
<machineKey validationKey="574...7A7"
decryptionKey="2C3...A0D"
validation="HMACSHA256"
decryption="AES" />
</system.web>
...and my forms authentication is configured the same for each application:
<forms loginUrl="/login" timeout="2880" defaultUrl="/" path="/" name=".SHAREDAUTH" domain="domain.com" protection="All" />
I've also tried prefixing my domain with a period as I've seen some people suggest, but that didn't work either.
This works fine on my local machine with separate sites set up in IIS for each subdomain. It also works fine on our dev server, where all sites still reside on a single machine. When I deploy to our staging environment, however, the cross-domain authentication stops working. In that environment, I have the primary site (where login occurs) running on a single server, and the secondary site (where my authentication should persist) running on two load-balanced servers. All are running under IIS 7 on either Windows 7 (local) or Server 2008 R2 (dev and staging).
I verified that the machine keys are the same by encoding a string on the primary site with MachineKey.Encode and decoding the result on the secondary server with MachineKey.Decode. I also verified that the .SHAREDAUTH cookie is passed to the second application in the request, both by checking the request headers as reported by Firefox and Chrome, and hooking the debugger to Application_BeginRequest and Application_AuthenticateRequest. I can see the cookie during Application_BeginRequest execution, but it's gone when Application_AuthenticateRequest is called. From what I can gather, that seems to mean that the deserialization of the authentication ticket failed, but I can't figure out why that could be happening in the multi-server environment, but not the single server environment, aside from different machine keys, which I already confirmed was not the case.
I also have a custom MembershipProvider and RoleProvider set up, and those work fine independently on each site.
What am I missing?

So, after a long slog I discovered MS security bulletin MS11-100, which patches an elevation of privilege vulnerability in forms authentication. Unfortunately, the patch is not backwards compatible. It was applied to our load balanced servers, but not to the server hosting the application that created the initial log-in, which meant that the balanced servers couldn't deserialize the authentication ticket written by the app server.
Per the MS deployment guidance article, if you find yourself in this situation, you can add
<add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" />
to the appSettings section in the web.config for applications on the machines with the patch installed (or to the machine-level config). Or, better yet, make sure you're hosting management company applies the patch to all of your servers at the same time...

For me it works adding this keys in the appsettings:
<add key="aspnet:UseLegacyEncryption" value="true" />
<add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" />

Related

aspnet mvc system no user when AuthenticateRequest event raised

I have an existing mvc webapi system that uses no authentication or authorization and I am attempting to add Windows authentication in. I approached this by creating a new simplified system with a single controller returning just static data.
The new system is set up to use Windows authentication, and as a result when I hook into the Application_AuthenticateRequest the HttpContext.Current.User is not null and has a populated Identity property with the correct WindowsPrincipal for the user sending the request.
In the existing system, when I amend the web.config to match the new (working) system all incoming requests have a null HttpContext.Current.User in Application_AuthenticateRequest.
I saw a post suggesting that I use the Application_AuthorizeRequest event handler as it is fired later in the pipeline. As expected the HttpContext.Current.User is not null at this point, however the Identity property of this is set as having an impersonation level of Anonymous and importantly is not authenticated.
I assume that my production system that I am trying to add authentication to is somehow configured to not use impersonation, yet my new proof of concept system is. As a result the Authenticate stage of the pipeline is adding an anonymous user to the HttpContext which is what I am seeing in the Authorize stage of the pipeline.
My question is how do I configure my production system to use impersonation so that I can access the user that has sent the request?
Please note that the system is deployed to an intranet so the Windows identity of the user is all I need and gives sufficient security.
my web config contains the following:
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
<authentication mode="Windows" />
<identity impersonate="true" />
<httpModules>
</httpModules>
</system.web>
in both systems (production and POC) and I have tried removing the <identity/> element from both and it appears to have no effect.
At this stage I am hosting only in IISExpress through VS2015
Turns out this was all down to IIS configuration.
When hosting a site within VS2015 using IISExpress, the applicationhost.config file that is used by IISExpress is one stored locally with the soure. Specifically in the $(SolutionDir).vs\config folder.
The config for my production system had windows authentication disabled and anonymous authentication enabled, and the POC system had the reverse. Changing this config file has fixed my problems, now the question is whether this will work on another user's PC or will an incorrect applicationhost.config file be generated??

Get current logged in user IIS returning DefaultAppPool

I have an asp.net application on my server that uses WindowsAuthentication to log in. The scenario is simple: users logged in, will use the same credentials to login the application.
Certainly, on IISExpress on my machine works great, but when I try to login the application on server, the current user returned is DefaultAppPool.
I guess it's a missing impersonate config on IIS. I tried to get the current user with:
string username = HttpContext.Current.Request.LogonUserIdentity.Name;
string username = WindowsIdentity.GetCurrent().Name;
... and all of above returns the current user loggedin but only works on IISExpress, but not on server IIS.
IIS Express config
DefaultAppPool
- Framework Version 4.0
- Application Pool Identity
Application Authentication Config
Server Info
Windows 2008 R2 Enterprise
IIS 7.5
PD: Is not my best English
I had a similar issues; as far as I can tell it is because the web.config file needs to have the following entries:
<authentication mode="Windows" />
<identity impersonate="true" />
Also in your IIS/Authentication section in Internet Information Services (IIS) Manager, make sure only Anonymous Authentication and Windows Authentication is Enabled. I had ASP.NET Impersonation checked by mistake and it was giving me the same error you described in this post. Once I disabled that (along with the other modifications), it seems to be working fine.

Getting account errors on remote server only - Antiforgery and AppData write permissions ASP.NET MVC

I guess I'm not understanding how the account (login/register) works in MVC. On the dev server everything works fine. When I deploy my application I get a couple errors:
Access denied creating App_Data subdirectory
and
The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.
I can fix the first error by enabling write permissions on the remote server, but everytime I publish it reverts permissions. I didn't think I was using an sqlexpress anywhere in my app because my connection strings are for SQL server 2012 databases, but I'm not sure if MVC will create one just for the account controls, see connection strings below:
<add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=MANDRAKE.arvixe.com;Initial Catalog=DB1Name;Integrated Security=False;User Id=Username;Password=***;MultipleActiveResultSets=True" />
<add name="BudgetingEntities" connectionString="metadata=res://*/Models.BudgetModel.csdl|res://*/Models.BudgetModel.ssdl|res://*/Models.BudgetModel.msl;provider=System.Data.SqlClient;provider connection string="data source=MANDRAKE.arvixe.com;initial catalog=DB2Name;user id=Username;password=***;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Another thing to note is I originally had this set up on my arvixe server as one website, and then I added a domain and published to that domain. That is when the problems happened, but I don't see how that would be correlated. I also added a captcha control to the user registration page, but when I remove that code, the errors persist.
Any ideas would be helpful, I don't know if I need to explicitly set the machinekey configuration (I didn't have to do that before, so I don't think I need to).
Just for anyone's information it had to do with my user account on the arvixe server I have. I don't know exactly what they did, but they told me that the permissions got messed up somehow. I'm still unsure exactly what is going on. I was trying to implement a captcha function but it seemed to mess everything up, possibly because the tutorials were outdated on how to add captcha to an ASP.NET MVC project.

ASP.NET_SessionID Missing on Production only

I have written an ASP.net webservice using C#. Everything works just fine with the service itself and deployment to stage and production. However after running an Acunetix scan there is an issue with cross site scripting. Our entire network is behind a WAF which is able to add some cookie stuff to provide protection for this. For the WAF to work it needs another cookie to attach to, we are trying to use the ASP.Net_SessionID cookie.
This cookie wasn't showing up so we added the line below to the web config and the cookie started showing up on the stage system only. When we deployed this update to production the cookie is not showing up.
<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="20"/>
As far as we can tell both servers are functionally identical, iis 6, OS, dlls ect. Yet we can't get this cookie to populate. Any ideas?
Are you putting anything in session?
If you don't then the cookie will not be sent to the client browser.
Have you tried the aspxanonymous cookie?
http://msdn.microsoft.com/en-us/library/91ka2e6a(v=vs.100).aspx

application pool identity change

I've got a web method set up on SERVER A and need to connect to the file system on SERVER B.
Currently I have a wide array of web services that already run on SERVER A where the identity on the application pool is set to NETWORK SERVICE. The issue is that I cannot seem to give the NETWORK SERVICE on A access to the file system on B. Changing the user on the app pool isn't really an option as there are too many possible train wrecks that could materialize on the outgoing web service calls.
So the solution I am trying to come up with is temporarily changing the Web Method identity user from NETWORK SERVICE to DOMAIN/SOMEUSER when the web method is called.
The property I need to change is System.Web.HttpContext.Current.User.Identity.Name
Can anyone tell me how I can go about doing this? Many of the solutions online seem to refer to Windows Azure - which I'm not using, so the approaches outlined don't work.
Thanks!
Try using impersonate in your service.
<system.web> ....
<identity impersonate="true" userName="accountname" password="password" />
You might have to play with the tag in the web.config. Our is normally set to <identity impersonate="false" /> and the application pool uses a domain user for permissions.

Categories