ASP.NET > SqlServer; trust and delegation - asp.net

we have a system where they client wants integrated Windows authentication.
This is an ASP.NET 3.5 application, connecting to Sql Server 2005.
The web server is Server 2003 R2 SP2.
The db server is Server 2003 SP2 (not R2).
In the db server, I ran the following script
exec sp_grantlogin 'myDomain\myUserGroup'
USE myDbName
exec sp_grantdbaccess 'myDomain\myUserGroup'
I have 3 users in the Windows user group 'myDomain\myUserGroup' right now. All three users' accounts are marked as trusted for delegation. The web server account in ADs is marked trusted for delegation.
The web application is marked as using Windows authentication (all others turned off).
The web.config has the following lines:
<authentication mode="Windows" ></authentication>
<identity impersonate="true" />
<authorization>
<deny users="?"/>
</authorization>
Yet when i try to connect to the web application with a user which is in the user group, i get the error:
System.Data.SqlClient.SqlException:
Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
My connection string is being built from a Sql ConnectionStringBuilder constructed as such:
ConnectionStringBuilder.DataSource = "MYDBSERVER"
ConnectionStringBuilder.InitialCatalog = "MYDBCATALOG"
ConnectionStringBuilder.IntegratedSecurity = True
If i HARD CODE one of the allowed accounts to impersonate on the web.config <identity /> line it works. But if i take off the hard coded account and try to pass the identity from the client's machine. I get the error.
So it seems that i don't have something configured correctly for the multi-hop integrated login scenario, but i can't figure out what.
Thanks in advance!

The ASP machine has authenticated the user connecting to IIS via NTLM/Kerberos. The authentication is guaranteed by the domain controller that has asked the original user process (IE) to present a secret that guarantees his identity: his password he typed when he logged into the box. The authentication is actually not done by the processes involved, but by the Local Security Authority (LSA, aka. lsass.exe) on each machine involved. Because the LSA on the ASP machine knows that the authentication is OK, it will allow an impersonation of the remote user to access anything it has the rights to access under the control of the said LSA (in other words, everything on the local ASP machine).
As soon as the ASP process that impersonates the user makes another hop to a new machine, it has left the realm controlled by the LSA on the ASP machine. The LSA on the SQL machine has no reason to trust the LSA on the ASP machine. So it ask it to present a proof that it is who it claims it is (the impersonated user). The ASP machine unfortunately cannot present such a proof, since it does not has the user secret (its password).
The work around is something called 'constrained delegation'. Through constrained delegation the domain controller intervenes in the negotiation between the SQL's machine LSA and the ASP machine LSA and says 'the ASP machine is OK, I vouch for him'. So the SQL's machine LSA trust the authentication and authenticate the original, impersonated user.
The technical details how to set up constrained delegation are described in How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0
Note that this is true anytime a 'double hop' and impersonation is involved, no matter the type of resources involved (can be a SQL server, can be a file share, can be a new back end ASP service).

If you're using Windows authentication then Impersonation doesn't flow past the ASP.NET process itself. You have two options here - swap to Basic Authentication, where Identity flows or, if you're running on Win2003 or later, you can use Kerberos and some hackery to impersonate when you connect

Related

How to integrate an ASP.Net intranet with Active Directory?

I'm currently working on an intranet portal for my company, it will remain internal, only users with accounts on our domain will have access to it. At the moment, I use forms authentication method, and authenticate users against the Active Directory domain with System.DirectoryServices. I also interrogate the AD with System.DirectoryServices.AccountManagement to manage access rights depending on the Active Directory groups the user belongs to and I store some data in user sessions and everything works fine.
I've been asked to study whether Single Sign-On could be implemented in our context, all our users work in RDS without exceptions, so they always are in an authenticated session and the higher-ups would prefer not having to sign in at all. As far as rewritting the code to authentify and authorize users as explained here and here
I'm not too concerned.
I tried everything on a blank ASP.Net MVC5 project, to which I added an ADO.Net model with integrated security. My dev SQL Server is hosted on a remote server (not the dev desktop), the same server also hosts the dev IIS server. In production, both services will be on separate servers. This worked fine as long as I was debugging localy on my desktop, but once I published to the IIS server, I hit the first snag and couldn't get out of it.
When I changed settings in the IIS app to disable anonymous and enable windows authentication, IIS automatically changed <authentication mode="Forms" /> to <authentication mode="Windows" /> in the web.config file (as suggested here), but I couldn't make it work with Integrated Security=True or Integrated Security=SSPI, I get an error page saying [SqlException (0x80131904): Login failed for user 'DOMAIN\MACHINE$'.].
The connection string reads like: <add name="ASPNetProjectEntities" connectionString="metadata=res://*/Models.ModelASPNetProject.csdl|res://*/Models.ModelASPNetProject.ssdl|res://*/Models.ModelASPNetProject.msl;provider=System.Data.SqlClient;provider connection string="data source=MACHINE;initial catalog=DATABASE;persist security info=True;Integrated Security=SSPI;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
I tried to add the machine account DOMAIN\MACHINE$ to SQL logins and grant it rights to the database, but no dice. I tried to authorize delegation in the server AD account and activate identity impersonation, but that didn't work either. I can only make it work on the remote IIS server if I put a SQL user/pass in the connection string.
So I'm at loss what could be missing here to make it work with Integrated Security. Or will I have to put SQL credentials in the connection string and encrypt it on IIS?
You're confusing Integrated Security with the authentication mechanism of your website. If you use Integrated Security, the connection used from your web app to SQL Server will use the account that the application pool your web app is running as is using. To use Integrated Security, have a service account created in AD, set your app pool to run as that account, and grant the necessary permissions to that service account in SQL Server.
Note that whether you're using forms auth or integrated security isn't relevant to how the web app connects to SQL Server, unless you're using impersonation, which you should never use.

WCF, IPC Named Pipes, ASP.NET, and <identity impersonate="true" />

We have a .NET 4.0 Windows Service that is hosting an endpoint over a Named Pipe (using IPC). This service is running under the context of User A.
We have an ASP.NET-hosted client that is requesting the operation that is exposed by the aforementioned service. This client runs under the context of User B (via Anonymous Access ,via <identity impersonate="true" />).
The problem:
If we use <identity impersonate="true" /> in our web.config (this cannot be changed), we get "Failed to connect to an IPC Port: Access is denied." exceptions when the client tries to call the hosted operation. If <identity impersonate... /> does not exist (perhaps by virtue of not using ASP.NET, say a client Console Application), we have no issue.
Does anyone out there know how to get this configuration working so we stop receiving Access Denied errors? It has something to do with authentication but we just can't work it out.
Recalling from 70-503: net.pipes only works with Windows security. It's obvious because the whole process (WCF) is on the current (Windows) machine only. ASP.NET runs under the credentials of a dedicated ASP.NET-user by default who's rights are strictly limited. I don't aspect the ASP.NET user having access to the current machine, accessing local files, net.pipes etc. It only has access to the folder your website runs from. So, by impersonating that very user is like ensuring having only the rights to run a website.
What you can do is impersonate to a specific Windows account who has the appropriate rights. This can be done using programmatic impersonation. Or use delegation. Read about it here to use the solution who fits best.
Not possible due to NetWorkService being restricted from seeing or accessing the pipe.
Answer here

Why does Windows/Integrated Authentication in IIS not pass user credentials to SSRS and SQL?

Issue:
In ASP.NET 4.0, I use my SSRS 2005 server's ReportService2005.asmx web service to get a list of reports. Also in .NET, I use Entity Framework to communicate with my MS-SQL 2005 database. When I use Visual Studio Development Server as my web server, calls to SSRS and SQL work fine. But when I switch to IIS 5.1, both SSRS and Entity code produce errors. I use only Windows/Integrated Authentication in IIS.
Errors:
For SSRS, I get The request failed with HTTP status 401: Unauthorized.
For Entity Framework, I get Login failed for user ''. The user is not associated with a trusted SQL Server connection.
Attempted Solutions:
In the Web.Config I added <identity impersonate="true" /> and that fixed Entity Framework errors but not SSRS errors. I expanded the identity reference to include my username and password, and that fixed all errors.
Question:
Why does specifying my username and password fix the errors, and why does SQL say I am not specifying a username ('')? I thought Windows Authentication automatically impersonated the current user. How can I fix this without hardcoding a "service" account into the web.config?
Windows or Integrated authentication means that user is identified using windows credentials (or token) but it does not means that the request in running under that user. ASP.NET run-time will execute the request under worker process (App Pool) identity unless you configure it to impersonate some other identity.
So when you are accessing the site using development server, the server is running under your identity and so access to SSRS and Sql Server is done under your identity and it works.
When you loaded your site under IIS, ASP.NET request would be run under whatever identity is configured for the application pool. Typically this identity is local user and hence access to network resources such as SSRS or Sql Server would be denied. Adding <identity impersonate="true" username="your name" ../>, ASP.NET will run requests under your identity and that should work for both SSRS and Sql Server.
The curious case here is <identity impersonate="true" /> - under this setting, ASP.NET will impersonate currently authenticated windows identity. However, for this to work correctly, you have configure both IIS and ASP.NET on integrated authentication and deny anonymous access (in ASP.NET as well as IIS). Failing to do so may result in not authenticating current user's identity and the request would be run under anonymous user's identity (as configured in IIS). If you marked integrated authentication in IIS but not in ASP.NET then identity would not be passed to the ASP.NET request. You need to check your environment to see what exact scenario you had faced but ultimate result was your ASP.NET request was running under credential that has access to SQL Server but not to SSRS.
You also need to be aware of the 'double hop' issue - this means that your credentials can only be used twice.
If you are accessing a website using Windows Authentication and impersonation, that website can call another service as you. If that other service is another website (i.e. Reporting Services) which in turn calls another service (e.g. database) it cannot pass your credentials on again. This means that the database will throw an error if it expects credentials from the user.

How do I allow anonymous access to my IIS site, but use Windows Authentication to connect to SQL Server?

What I want to do is:
Allow anonymous users to access my ASP .NET site.
Use Windows Authentication for the site to access Sql Server. It will log in to Sql Server with a domain account set aside especially for the site (and preferably do everything under the same account).
Every article on the Web tells you to do this:
<authentication mode="Windows"/>
<identity impersonate="true"/>
in Web.config. However, I gather that this is only if you want users to log in with Windows Authentication. It has nothing to do with the server logging in to SQL Server (except that the combination of the above 2 implies that users' authentication will also be used to connect to the database). Is this correct? Given that my Windows account has access to files on the server and the database which the site is connecting to, this seems hard to test....
It seems that if I:
set the App Pool Identity to the domain account
enable Anonymous Access on the site using the domain account
use a connect string with Windows Authentication
then the site will connect to SQL Server via Windows Authentication. Also, it will use the domain account as long as impersonation is off. Is this correct?
in Web.config. However, I gather that
this is only if you want users to log
in with Windows Authentication. It has
nothing to do with the server logging
in to SQL Server
This is partially true. The impersonated account will be used to logon SQL server if delegation is setup properly. You didn't see this because in most of the environment, delegation needs to be explicitly setup. Delegation is a more powerful form of impersonation and makes it possible for the server process (in your case, IIS process) to access remote resources (in your case, SQL server) while acting as the client. For more information, you can google ASP.NET Delegation. I said it's partially true because in some simple environment, you don't even need any special configuration. The delegation is just working. For example, if you have SQL server running on the same machine as the IIS server. Another case is that you have your IIS server running on an Active Directory domain controller (very rare). In these two cases or on a machine with delegation configured properly, your above statements will be wrong.
It seems that if I:
set the App Pool Identity to the
domain account
enable Anonymous
Access on the site using the domain
account
use a connect string with
Windows Authentication
then the site
will connect to SQL Server via Windows
Authentication. Also, it will use the
domain account as long as
impersonation is off. Is this correct?
Yes, this is correct.
Given that my Windows account has
access to files on the server and the
database which the site is connecting
to, this seems hard to test....
It's easy to test if you have two domain accounts (or one domain account and one local account). Set the App Pool identity to use your DomainAccount1. Grant only DomainAccount1 to have permission to access your database. Access your web app on another machine using another accound (either domain account or local account). Test if the web app can properly access your database.
If I'm following you correctly, you are right; You do not want to use impersonation/authentication to do what you want to do. Set the App Pool identity appropriately, and assure that user account has appropriate access to SQL Server.
Instead of using a Windows Account you can create a separate Sql Login i.e. a username/pwd and use that in the connection string instead.

The error "Login failed for user 'NT AUTHORITY\IUSR'" in ASP.NET and SQL Server 2008

My ASP.NET v3.5 web application is throwing the following exception when it attempts to open a connection to a SQL Server 2008 database:
System.Data.SqlClient.SqlException:
Cannot open database "MyDbName"
requested by the login. The login
failed. Login failed for user 'NT
AUTHORITY\IUSR'.
The thing is, I've added NT AUTHORITY\IUSR to the server's list of logins, and to the database's list of users. For the server, I've granted the user the Public role, and for the database I've granted db_datareader permissions.
I've also granted the same for NT AUTHORITY\NETWORK SERVICE, which is the identity that the application pool is running under.
The web application is hosted by IIS7, if that makes a difference. The problem repros when the DB and IIS are on the same physical machine as well.
The trick here is that NT AUTHORITY\NETWORK SERVICE actually appears to the database as DOMAINNAME\MACHINENAME$ (note the $ sign!). That is, when you cross the machine boundary from your web server to the SQL Server, SQL Server sees the machine account if you use the NETWORK SERVICE or LOCAL SYSTEM accounts. If you use any other non-domain account, SQL Server will not receive your credentials.
I'm a bit puzzled by your error message. Truth be told, I don't think that when the DB is on another box, you'll see anything other than Login Failed for NT AUTHORITY\ANONYMOUS LOGON.
IUSR is used for anonymous websites, and can't pass over the wire to SQL Server. You may find a way for it to work if you're doing everything on the same machine, but I'd never know because I'd never do it that way... ;-)
In case it helps someone, in web.config I added <identity impersonate="false" /> for this error to go away (under <system.web>)
It's important to note that you'll get this error, as I just did, if you don't have IIS configured to allow impersonation, but you do have your web.config attempting to do impersonation.
I just came across this exact error, and all of the following steps are required:
Ensure ASP.NET impersonation is enabled on your IIS web server:
Combine that with configuring your site to use impersonation (web.config):
<system.web>
<identity impersonate="true" userName="your_service_acct" password="***" />
</system.web>
The above steps presume that you have a SQL Login setup on your MSSQL for 'your_service_acct' with permissions
When running on localhost, against a localdb, or even a remote db that you personally have permissions on, the development IIS runs as if it were YOU - and everything just magically works. So, in debug mode, you don't need to create a special web.config..
As soon as you deploy your site onto some kind of server (in my case, our TEST environment) you'll likely need to have done the above steps I just detailed, because IIS will try to connect as the application pool user, which is not usually what you want administratively speaking. So, that's when you want to start using web.config transformations, so Visual Studio will insert the appropriate identity impersonate="true" during your 'Publish...' deployment step.
I would suggest to create a separate (preferably domain) account and specify it in the connection string (usually in web.config)
Then you can limit permissions on the web server what this account can and cannot do.
Then you can grant this account required permissions in SQL server.
I had had the same problem and solved this by changing application pool.
Instead of using Integrated Security=True; in connection string, just use username and password authentication user=sa; pwd=mypassword;
The simple solution is to check your web.config file and make sure one of these is part of the db connection string:
Trusted Connection=false
OR
Integrated Security=True
This problem is shown when you restore a new database on your last database.
To resolve this you must go to sqlserver, then security and then set your apppool again.
this worked for me:
Open the IIS Manager (inetmgr)
In the "Connections" panel, drill down to your site's node and select it
In the right-hand panel, under the "IIS" group, double click the "Authentication" icon.
Right-click on "Anonymous Authentication" and choose "Edit..." from the context menu.
In the popup dialog, select the "Application pool identity" radio button.
Click OK.

Resources