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

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.

Related

Use SQL Integrated Security and IIS Windows Authentication

We have an internal asp.net web application which has ASP.NET authentication and Windows Authentication enabled so that users can be logged in as soon as they connect to the website using their domain credentials (this is a requirement that we cannot change).
We are currently looking to upgrade our SQL database and understand that SQL Authentication is less secure than integrated security (e.g. https://msdn.microsoft.com/en-us/library/bb669066(v=vs.110).aspx). Currently we use SQL Authentication.
We could easily change the connection string to run using integrated security, however IIS presents the user as the domain user connected to the website (e.g. domain\greg) instead of the service (domain\WebsiteServiceUser), because IIS impersonates the user. This impersonation is needed to access their Exchange Mailbox, files and other things.
If we were to go down this path, we would have to add logons for every user (using AD groups) to SQL Server. This is possible, but in itself presents a new security issue - users would be able to create a SQL connection outside of our web application and run whatever queries they like against the database. All of our authorization could be bypassed.
Is there a way to connect to SQL using Integrated Authentication using the user that the AppPool runs as (Domain\WebsiteServiceUser) instead of connecting as the currently logged on user (Domain\Greg)?

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.

ASP.NET > SqlServer; trust and delegation

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

Windows Integrated Authentication Conflict With MS-SQL 2000 DB Connection With Integrated Security

We are developing an intranet web application on .NET 2.0 platform.
The application is using Integrated Windows Authentication for Single Sign On. The users are authorized to use diffent modules according to the Active Directory Groups they are in.
Up to the point where authentication and authorization is accomplished everything works fine. But the problem starts when application tries to connect to the database on MSSQL Server.
According to the security policies of our customer, no database user or password data should be kept in connection strings or in registry even if encrypted. So we are forced to use Integrated Security=SSPI in the connection string.
The Application Pool on IIS is configured by them with the Identity User who has access to the database.
When we deactivate Windows Integrated Authentication, we connect to the db with the Application Pool's Identity User. But when Integrated Authentication is on, the application is trying to connect to the database with logon user credentials.
We tried every combination of Integrated Authentication, with or without impersonation, to solve the problem.
Is there any way to solve this conflict?
Normally the way you are doing it should work. Do you have Kerberos with delegation enabled?
Maybe this helps:
How to: Access SQL Server Using Windows Integrated Security
http://blogs.msdn.com/sql_protocols/archive/2006/12/02/understanding-kerberos-and-ntlm-authentication-in-sql-server-connections.aspx
Edit: if both SQL and IIS are on the same machine you need to turn off impersonate:
<authentication mode="Windows" />
<identity impersonate="false" />

Resources