I'm attempting to share .ASPXAUTH cookies between an ASP.NET MVC 4 application (in IIS 7.5) and a service using HttpListener on the same host.
The browser presents the cookies to both correctly, but my service receives System.Web.HttpException: Unable to validate data. at FormsAuthentication.Decrypt, which I would expect if the two applications were using different machine keys.
So: how do I find out if my machine is configured to use different machine keys?
the default setting of IIS is autogenerate machine-key and isolate per application
you can change this setting globaly in your machine.config or localy (per application) in your web.config
for details please see
http://technet.microsoft.com/en-us/library/cc772287(v=ws.10).aspx
http://technet.microsoft.com/en-us/library/cc754909(v=ws.10).aspx
You can see the current setting for machine-key in IIS manager. For details, see http://blogs.msdn.com/b/amb/archive/2012/07/31/easiest-way-to-generate-machinekey.aspx
Related
I have asp.net core 3.1 web api. When I run the project locally in Visual studio, it works fine. But when I publish it to IIS and run it, I get the error.
500 Internal Server Error","error": "A connection was successfully established with the server, but then an error occurred during the pre-login handshake. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)"}
Or Login failed for user domain_name\machine_name.
connection string looks like this
"ConnectionStrings": {
"ABCDB": "Server=xxx-test,80;Database=abc;Integrated Security=true;MultipleActiveResultSets=true;"
},
I have the hosting bundle installed for .net core 3.
my app runs under ApplicationPoolIdentity which is added to the database and has the permissions. My application pool is set to No Managed Code with ApplicationPoolIdentity.
The endpoints for the api which are not connecting to the database work just fine on published version but anything that is connecting to the database gives the error.
I referred to couple of links but hard luck.
https://www.loganfranken.com/blog/1345/why-your-web-application-cant-connect-to-sql-server/
IIS fails to pass windows credentials through to SQL Server for ASP.NET Core app
Why asp.net core app uses different user than AppPool identity for Windows Authentication when connecting to SQL Server?
Any help is appreciated.
Edit: The only things that works for me running the appPool under custom account(my credentialis) but does not work under appPoolIdentity on IIS
It seem that your environment needs a reset.
1- Manually check your app folder under IIS to see if any cached files or similar ones could be deleted.
2- Ideally, install it in a new folder under IIS
3- Reset the IIS
4- Make a hard refresh of the web browser
your connection string should be like this:
"ABCDB": "Data Source=xxx-test;Initial Catalog=abc;Integrated Security=SSPI;Persist Security Info=True;"
and add application pool name of your published application of security/users folder of your DB:
IIS APPPOOL\<apppool name>
Or add a new user account to you DB with user name and password. In this case you will also have to change the connection string.
I was having the same issue.
Other .NET Core 3.1 web apps are running just fine with the same authentication method (anonymous authentication) on the same IIS instance on the same server using the same connection string to the same MS SQL DB.
With this one particular .NET Core 3.1 web app, IIS is causing the app to try to authenticate to MSSQL DB with the username {DOMAIN}\{Computer Name}
The issue for me was that the connection string for the one app with the issue had "Trusted_Connection=True".
I knew that I would get this authentication interception from IIS with Integrated_Security but did not realize that Integrated_Security is synonymous with Trusted_Connection.
So the fix is to remove Trusted_Connection = True or Integrated_Security = True from the DB connection string in the app. If you need either of these two for your code to work (but are providing a username and password in the DB connection string), you should probably re-evaluate your code. Otherwise, the behavior OP and I observed should be what you want to happen and this isn't a problem.
I have differing behavior between a test server and a dev server - on my dev server everything works fine but on the test server the ASP.NET_SessionId cookie disappears after a flow of events and hence so does the servers session. Testing was done in the same browser on the same machine & the code bases are virtually identical. The only significant difference is that the pages are being served from two different pcs.
The flow of pages (all https) that causes this is such:
Load page from domain A that contains an iframe (session cookie exists at this point).
Domain B is loaded into the iframe.
A second page from domain B is loaded into the iframe triggered from the first page.
The second page does a form post to back to domain A where the session cookie is now absent.
EDIT
Forgot to say - we're using SqlInMemoryProvider as our session state.
You could share the session state between two servers using the below ways:
1)Using SQLServer Session:
In this mode of session state, the session objects are stored into SQL Server.
The benefit of using this technique is that all the data in the session will be stored together in a different location or you can say a centralized location in SQL Server, to get it working we just need to configure the SQLServer to store session data.
2)Using the StateServer Session:
In this mode of session state, the session objects are stored in a separate server handled by a Windows Service running on that server.
The benefit of using this technique is that all the data in the session will be stored together in a different location. In this case, the server to be handled by the Windows Service is named "aspnet_state"; this will become the centralized location for session data. To get it working we just need to configure the StateServer to store Session data.
when you share the session state between two servers make sure ASP.NET state service is installed on all the servers and the settings are as below:
Also, the service cannot be accessed remotely by default. To enable that option you need to set the value of the following registry key to 1: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection. Don’t forget to restart the asp.net state service after the registry key change.
You need to declare the session management options within the system.web node. Example:
<sessionState mode="StateServer" stateConnectionString="tcpip=machinename:42424">
</sessionState>
If you want to use the SQL Server type then this section may look like the following:
<sessionState mode="SQLServer" allowCustomSqlDatabase="true"sqlConnectionString="the connection string name to the server">
</sessionState>
Where SQL connection string refers to the name of the connection string in the connectionStrings section of web.config which holds the details of the state table. The connection string itself may take up the following format:
<add name="ASPStateConnectionString" connectionString="Data Source=[DB machine name where state DB is stored];Initial Catalog=ASPState;User ID=[db admin user name];Password=[db admin password]"providerName="System.Data.SqlClient" />
we also need to add a machine and a validation key within the system.web node, that may look something like this:
<machineKey
validationKey="some long hashed value"
decryptionKey="another long hashed value"
validation="SHA1"/>
The default setting for the validation key is AutoGenerate which does exactly what the name applies: the key will be generated automatically by IIS. The default generation mode for the decryption key is IsolateApps. It generates a unique key for each application by using the application ID.
We need this common machine key as we want to run this on several machines so we don’t want the machine key to be automatically generated.
For more information you could refer this below links:
https://dotnetcodr.com/2013/07/01/web-farms-in-net-and-iis-part-5-session-state-management/
https://www.c-sharpcorner.com/UploadFile/25c78a/load-balancing-session-state-configuration/
It's because cookies are not stored if domains are different.
It's treated as 3rd party cookies.
You need to use same domain as parent site to iframe site.
Or else you need to use cookieless session.
I have recently gone through this problem and come across the concept of cross-site cookies. If you want to share and use the cookie across the different domains then you have to set your cookie samesite attribute to None (SameSite=None). It must be secure otherwise it will be ignored and not send back to the server by browser (Chrome). To use a secure tag for your cookie you have to enable the HTTPS for your website.
For more detail you visit: https://web.dev/samesite-cookies-explained/
I have the following setup:
IIS 8.0
a web handler call it test.ashx
Impersonation & Windows Authentication are both configured. Kerberos is showing as the authentication type.
test.ashx uses the unmanaged API: CreateProcessAsUser() method to run "cmd.exe /c myScript.cmd"
I put statements in myScript.cmd and see that it is running as the requesting user as I need it to. The problem I am experiencing is that the script cannot reference network files (either mapped drives or UNC path)
I need myScript.cmd to run as the requesting user and to be able to access network file resources. How do I get this to work?
I found one item that made a big difference on getting kerberos authentication to work, which is required to do impersonation and delegation. In IIS Manager I had to choose the web site, then run the Configuration Editor. Once it opened I had to choose the as from: DefaultWebSiteWeb.Config, and as the section: system.webServer/security/authentication/windowsAuthentication. Then set: useAppPoolCredentials = True. Note: useKernelMode was already set to true.
Additionally, for the web site I have the following set for Authentication:
ASP.NET: Enabled
Windows Authentication: Enabled, Provider: Negotiate, Kernel mode enabled.
Now my ASHX web handler (in C#) can start a process as the user, run a .cmd file that accesses network resources.
I have four different server and a load balancer. I want to use captcha control. I did something with it this way:
I created a handler.ashx to create the captcha image. This handler is used in the Main page. I keep the captcha control password in session while creating the captcha control. Then I compared password typed by the user with the password in the session. It works very well, but only on one server.
It doesn't run correctly with four servers. Although the user enters the correct password every time, it sometimes matches with the session password and sometimes doesn't match. I think the problem reason is this:
For Example :
A,B,C and D are the four servers. The load balancer routes the first request to A server. Which opens the main page from A server and creates password '123456'. This is stored in session on A server. Then user typed in the password and clicked button. Now the load balancer routes this request to the B server. Because session in B Sever is null, the passwords don't match.
My web.config has this,
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424"/>
But It still doesnt work.
What should I do ?
So first thing (just to make sure) - I believe that this connection string is just an example because 127.0.0.1 is localhost and it wouldn't have chance to work ;).
Now I will assume that you have chosen server A for you state server. Please check following things:
"ASP.NET State Service" is up and running on the server A (it's disabled by default, you can check that in Administrative Tools --> Services)
the stateConnectionString in servers B, C and D is "tcpip=[Server A IP Address or Network Name]:42424" (it can be 127.0.0.1 only on server A)
servers can communicate between each other using TCP/IP via port 42424 (firewalls etc.)
Please remember that if you have changed configuration of "ASP.NET State Service" on server A to not use default port (42424), you must reflect that in your connection strings.
Sometimes it's easier to configure "SQL Server Mode" instead of "State Server Mode" so you might want to consider that. You can find more details here.
You need to use StateServer or SqlServer for managing the session state and they should be out of your firewall network that is used to balance the load.
http://www.hanselman.com/blog/LoadBalancingAndASPNET.aspx
When using Session State Server, there are few things which need to setup.
Setup ASP.Net State Service on the machine which you want as a StateServer.
net start aspstate
Change Session Mode in Web.Config File for all web applications and point to a StateServer
<system.web>
<!-- ... -->
<sessionState
mode="StateServer"
stateConnectionString="tcpip=your_server_ip:42424"
cookieless="false"
timeout="20" />
<!-- ... -->
</system.web>
3 . All Web Server the use same <machinekey> configuration
<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>
(Note:To maintain session state across different Web servers in the Web farm, the application path of the Web site (for example, \LM\W3SVC\2) in the Microsoft Internet Information Services (IIS) metabase must be the same for all of the Web servers in the Web farm. The case also needs to be the same because the application path is case-sensitive.
[http://support.microsoft.com/kb/325056])
(See question below for more context):
Are there any situations in which
<machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"/>
in web.config would fail to AutoGenerate a new machineKey on App Pool recycle? This is the behavior I'm seeing...
I'm using standard ASP.NET FormsAuthentication in an MVC app. If I log a user in using FormsAuthentication.GetAuthCookie and don't use a persistent cookie (relying on the browser's session to remember my authorized state), I would expect recycling the IIS App Pool to invalidate the session's knowledge of this cookie...and thus logout all users who don't have persistent cookies.
This DOES happen on one of my IIS installs (XP), but on a different IIS configuration (Server 2K3) the FormsAuthentication cookie (under the standard name ".ASPXAUTH") remains valid and continues to authorize the user.
Does anyone know why this is happening or what configuration controls this behavior?
Obviously recycling the app pool has no control over whether or not the browser still sends the .ASPXAUTH cookie (as long as I haven't closed my browser and the cookie hasn't expired).
In the case of the IIS install that properly denies authentication after a recycle, I can see the incoming cookie in Request.Cookies during the Application_BeginRequest event...but once control moves to the next event available in Global.asax.cs (Application_AuthenticateRequest), the cookie has been removed from the Request.Cookies collection.
Why does this not happen for both IIS/ASP.NET configurations?
In case this isn't clear, a simpler way of forming the question is:
Why does HttpContext.Current.Request.Cookies[".ASPXAUTH"] change from {System.Web.HttpCookie} to null when I step, in a single request, from Application_BeginRequest to Application_AuthenticateRequest?
More debugging information:
If I attach the following code to Global.asax.cs's FormsAuthentication_OnAuthenticate event...
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
var val = cookie.Value;
try
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(val);
}
catch (Exception)
{
}
}
...then during a request before I recycle the IIS App Pool, no exception will be caught. After recycling the IIS App Pool, when the exact same .ASPXAUTH cookie is sent from the browser, a Cryptographic exception is caught ("Padding is invalid and cannot be removed.")
Why is this?
Our application is stateless (no session required), yet we had a situation where an app pool recycle caused invalidation of all machinekey-encrypted cookies on a server environment (above described issue). This was caused because the machinekey changes with every recycle, which should not be the case.
The AutoGenerate modifier specifies that ASP.NET generates a random key and stores it in the Local Security Authority (LSA)
https://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
"Local Security Authority (LSA)" means the user assigned to app pool, see below for more details as this turned out to be the problem.
The issue lied in the fact that we are using a dedicated user account for running the application pool, and simply creating the user and then assigning it to the app pool did not seem to trigger the creation of the registry section where the machine key is then stored. You can verify this yourself by checking registry
HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/ProfileList (for getting the SID of the user you just created; if the user is not there, then this is already a bad sign)
HKU/[UserSIDFromBefore]/Software/Microsoft/ASP.NET/... (a machine key should be stored there)
The solution was to logon as that user once on the computer (normal Windows logon screen) so that the relevant registry sections are created. There might be quicker or more subtle ways to establish the registry sections though.
Internet Information Services (IIS) 7.0 (Windows Vista, Windows Server 2008) introduced application pool identity, a new isolation mechanism that helps provide increased security for servers that run ASP.NET applications. However, sites that are running under the application pool identity do not have access to the HKCU registry. This is where the ASP.NET runtime stores its auto-generated keys. The result is that ASP.NET cannot persist the auto-generated key when the application pool is reset. Therefore, every time w3wp.exe is reset, a new temporary key is generated.
Note This is not an issue in IIS 7.5 (Windows 7, Windows Server 2008 R2) and later versions. On these versions of IIS, ASP.NET can persist its auto-generated keys in a different location that survives application pool resets.
https://support.microsoft.com/en-us/help/2915218/resolving-view-state-message-authentication-code-mac-errors
Forms Authentication cookies have nothing to do with Session state.