using windows authentication to log in to a sql server - c#

I have a web application set up on our intranet that uses windows authentication (successfully) that I am trying to link to a database running on a separate server.
The problem that I am having however, is that when I try to use a trusted connection to log in to the sql server, instead of passing the domain/username of the person using the website the application is passing NT AUTHORITY\ANONYMOUS LOGON.
I checked that the authentication was working by having the website display a greeting that does identify my username correctly when I log on to the site, so it isn't an anonymous access issue. I think it is an impersonation issue somehow despite the fact that set in the web.config file for the application.
Curiously, the web application works fine when I run it on either my dev machine or even locally through remote desktop on the production server. I'm not sure what's going on here.
Finally, I'm running iis 7.5, windows server 2008 r2 and sql server 2008

This is called Constrained Delegation. Basically what that means is that an impersonated context by default cannot be delegated to authenticate with a resource on the network. If constrained delegation would not be in place anyone could create a web site in the enterprise and expose some benign application. But underneath, once the user authenticated with the site, it could impersonate that user to do anything, like read his mail, sale stock on his behalf, give raises to site developer, *anything. This is why impersonated contexts are not trusted outside the machine that impersonated the user.
To allow an impersonated context to connect to a remote resource (like a file share, or a database server) the domain administrator has to explicitly set up Constrained Delegation, which allows the impersonated context to authenticate with one specific resource.
There are numerous articles describing the problem and the solution:
How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0
Protocol Transition with Constrained Delegation Technical Supplement
How To: Connect to SQL Server Using Windows Authentication in ASP.NET 2.0
Configuring Servers for Delegation (IIS 6.0)
How to: Use Protocol Transition for Impersonating and Delegating the Original Caller in WCF

it is a known behavior called double-hop issue. See http://weblogs.asp.net/owscott/archive/2008/08/22/iis-windows-authentication-and-the-double-hop-issue.aspx

If your web application tries to access your database it does it with the account under which the IIS w3wp.exe process is running (networkservice by default).
If you want to change this, you will need to use impersonation.
This document explains it pretty good.
As the document also explains depending on your application, you might want to use trusted subsystem instead of impersonation.

Related

Entity Framework Core and Windows authentication on IIS Server

I'm trying to use, for the first time, Windows authentication on my ASP.NET Core 3.1 MVC site to connect to SQL Server using EF Core.
Locally everything is ok (using IIS Express), but on the server, something goes wrong.
My site has "hi,<myDomain/myAccount>!" on the top right of the page, and it is correct, but when I request a page with database query, I get this error:
SqlException: Login failed for user 'MyDomain\MyServerName$'
Why? How do I configure EF Core connection string?
Update:
I can't use form authentication
I don't have a user list table
I can use impersonation (WinAuth? active dir?)
Every user(more can login to site has the access to the sql database
I can change some IIS Server settings
This is the first time i use the winAuth (auto configured by visual studio create project tool => with windows authentication)
"what kind of user is the app pool running under?" i don't know, the default one i think
This is likely an issue having to do with the credentials running the app pool in IIS, and the access rights those particular credentials have. You say you are NOT using impersonation, in which case the request to SQL Server from your app running on IIS needs to be made using a system account that has proper database access. A system account being a singleton account that only exists to run as the "Application Pool Identity" for the app in IIS.
On IIS on your server, what kind of user is the app pool running under? In most cases with Windows Authentication, you want to use a system account of some kind to run the app pool and then give that system account access to the database. If you don't want to use a system account, you would have to use impersonation, and then use an AD Group to give the impersonated users access to the SQL Server Database.
Since you're saying the request to SQL server is coming across as DOMAIN\SERVERNAME, you likely need to change that setting in IIS to set the request to come from a system account, and then give that system account explicit access to the SQL Server database.
You can change this by adjusting your Advanced Settings in IIS and inputting the information (Username/PW) of the account you want to run the app under or "as" in IIS.
Then, add this same DOMAIN\USERNAME account to the Database as a user who can Read/Write/Delete etc. You could also simply add the DOMAIN\SERVERNAME that is being denied in it's request to the database here, if you don't want to use a custom system account.
As for "How to configure EFCore connection string?", this is usually done in the Startup.cs file. There you can input a connection string from your appsettings.json directly with the .UseSqlServer(connectionstring) method.
You access the connection string using Configuration.GetConnectionString("KEY").
Once configured there, you don't need to configure it again (unless perhaps to change from dev/qa/prod environments).

Windows Identity Impersonation not persisting into Sql Trusted Connection

I've inherited a WCF web service that uses impersonation to connect to the database, while trying to get the automated tests running I noticed that any of these hitting the test instance of the service were failing with a 401 response.
Using Fiddler to capture the response I was able to see that it was trying to open the database connection using NT AUTHORITY\ANONYMOUS LOGON.
I eventually got remote debugging setup and break pointed immediately before the connection was opened and I used the immediate window to check the current principal, here are the results:
?System.Security.Principal.WindowsIdentity.GetCurrent().Name
"myDomain\myUser"
This is exactly as I was expecting to see. Following this I checked the content of our connection string and it was:
Data Source=myDbServer;Initial Catalog=devDb;Integrated Security=True;User ID=;Password=;Asynchronous Processing=False;Connect Timeout=300;Application Name=myApp
Which again is what was expected.
My next step was to disable the impersonation and see what user was trying to connect at that point:
?System.Security.Principal.WindowsIdentity.GetCurrent().Name
"NT AUTHORITY\NETWORK SERVICE"
However this time the 401 error reported that the user myDomain\myDevServer did not have permissions.
The service is running under Network Service on IIS 7, and this is as intended. Though I did try having it run under a domain user, but saw the exact same results: SQL attempting login with NT AUTHORITY\ANONYMOUS LOGON
My issue is closely related to the one experienced on this question.
However using the same immediate window technique I verified my impersonation level, which was indeed delegation:
?System.Security.Principal.WindowsIdentity.GetCurrent().ImpersonationLevel
Delegation {4}
So what would cause the trusted sql connection to be getting a completely different user than what is shown in the current principal?
Update:
I have verified the settings on the DC, the machine account is configured for unconstrained delegation, and my user account is not marked sensitive.
I also stepped through this article I did note that under the double hop section he says that the ASP.NET Impersonation authentication provider should be enabled, however doing so causes the server to immediately return a 500, it never makes it into managed code.
Additional information:
The services all have the [OperationBehavior(Impersonation = ImpersonationOption.Allowed)] attribute applied to them and the web.config file has <serviceAuthorization impersonateCallerForAllOperations="true" />
The services have both a webHttpBinding for restful calls and a basicHttpBinding for soap calls, both endpoints experience the same issue.
Attempting to authenticate to a remote resource under an impersonated context requires delegation. Follow the Delegation guidelines from Delegation and Impersonation with WCF (these steps require a domain administrator):
On the domain controller, clear the Account is sensitive and cannot be delegated check box for the account under which the client application is running.
On the domain controller, select the Account is trusted for delegation check box for the account under which the client application is running.
On the domain controller, configure the middle tier computer so that it is trusted for delegation, by clicking the Trust computer for delegation option.
On the domain controller, configure the middle tier computer to use constrained delegation, by clicking the Trust this computer for delegation to specified services only option.
If you're under a Windows Server 2012 environment is somehow easier, see How Windows Server 2012 Eases the Pain of Kerberos Constrained Delegation.
If you want to learn more about this problem, google for "Kerberos double hop" and you'll find a tonne of resources, including many answers here on SO.
The most likely cause is a misconfigured SQL Service Principal Name (SPN). When connecting directly to SQL (eg. from Management Studio) a misconfigured SPN causes a fallback to NTLM (ie. it won't be noticed). But in delegation case fallback is not allowed and this causes authentication to fail, so the authorization is done against the anonymous logon, exactly as seen in the OP. SQL Server Kerberos and SPN Quick Reference is a good resource.

Send User Identity to SQL for login

We have developed a product which is a web application. While configuring it in IIS, we disable all the authentication modes except Windows authentication (app works on Windows authentication only).
We create a service account and provide admin access to that account on all the servers, and on database servers.
We configure the connection string in web.config with username and password of that service account. Everything was working fine till now.
We received a new requirement which says, no service account will be created and individual users will be granted database access. We have to configure our application in such a way that Windows credentials are used to access the app gets passed to SQL Server. Reason for this change: we can log the user accessing the database.
I set Integrated Security=SSPI in the connection string and tried with different App Pool Identity but to no avail.
We are even ready to change the code if same is required to achieve the functionality.
Can someone please help me what am I missing, or how it can be achieved? Please let me know if more information is required and I will be happy to provide the same.
App server and database server are on the same domain and network but different machines. Users accessing the application will be on the same domain and network. This is a intranet based application.
You need to enable and configure constrained delegation. Follow this document: How to Implement Kerberos Constrained Delegation with SQL Server. Your app pool need to be configured to impersonate, see Using IIS Authentication with ASP.NET Impersonation.
Also this will be a hop scenario so you will have to enable delegation for the IIS server and if you intend to pass user credentials then you need to enable delegation for the user accounts too. You can use the tool delegconfig to troubleshoot this.

Trouble with window authentication on IIS 7

I am trying to set up a Test server to try out asp.net (3.5) web applications before they're moved to Production. I want to mirror the settings in IIS from Production server. On my web app, application pool is set as Classic .NET AppPool with identity NetworkService and Windows Authentication is enabled. When I attempt to access app on Test server I get error "The EXECUTE permission was denied on the object 'GetTable', database 'DatabaseName', schema 'xxx'. I realize I can add the network account to that stored procedures security but I shouldn't have to - it works in production without it.
I am using a restored copy of the production database thus the permissions are identical between the two. I did have to add the querying Test server name (i.e. xxx\Test$) to the database security in SQL server to gain access to the database, but I shouldn't have to add other local network permissions as they are included in the Security Logins of SQL (public).
In Windows Event Log* on Test server this piece of the error detail bothers me because the "Thread account name is NT AUTHORITY\NETWORK SERVICE compared to when a permission error is thrown on production server the Thread account name is the name of the user.
I think I need to get the Test server to recognize the real user. I (obviously) do not understand security to the fullest for web apps yet. Can someone suggest other areas for me to investigate? I did research this but I'm only finding things like how to change the apppool account, or identity, not the piece that troubleshoots permissions between client to web server to database server. BTW the production and test databases are on the same server. The product and test applications are on different servers (both Server 2008/IIS 7).
There is one difference: ASP.NET 1.1 application pool is not installed on IIS on Test server. Could that be the issue?
*Windows Event Log snippet:
Request information:
Request URL: http://server/appname/default.aspx
Request path: /appname/default.aspx
User host address: xx.xxx.xx.xx
User: xxx\username
Is authenticated: True
Authentication Type: Negotiate
**Thread account name: NT AUTHORITY\NETWORK SERVICE**
BTW if I move my test app to production server in a new folder, it works fine. Problem is with the test server configuration.
ANSWER: Set Active Directory for IIS server to say "trust this computer for delegation". I found my answer from a 2007 entry posted by plq in this: Microsoft ASP.NET forum
ANSWER: Set Active Directory for IIS server to say "trust this computer for delegation". I found my answer from a 2007 entry posted by 'plq' in this forum: Microsoft ASP.NET forum

Use a Web Service to Run SQL queries for a Windows Forms Client

I need to use a Windows application running on remote clients that will connect to a web service. The web service will access an SQL database to verify users, and roles, and perform other tasks. I am using ASP.NET Membership to manage the users and roles. I have ASP.NET Membership, and the web service working on the development machine. I have a windows client with a service reference that works when I access methods that do not access the database, but when I try to access a service method that access a database method I get The user is not associated with a trusted SQL Server connection. I get various permissions errors depending on what I am try to fix this, but this is the gist. I don't want the Windows client to need DB permissions. I want it to send a user name, and password to the web service, then the web service wraps Membership.ValidateUser(userName, password)
Can someone tell me how to set this up?
You should consider setting up SQL Server to use SQL and Windows Authentication (mixed mode). It's most likely running in Windows Authentication mode only. You can take a look at this link to get started.
It sounds like, by the way you have it designed, is that you would have to set up an account for each user. In my experience it's best to just create a specific SQL account with the necessary permissions, and have each client use that account. You could specify this in the connection string.
Assuming you have named pipes authentication enabled in SQL, your SQL connection string in your ASP.NET application could be configured to use integrated security (Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI;). Then in SSMS, give the appropriate ASP.NET user privileges to the database. The user that IIS uses depends on what version of IIS you're running, and can be seen in the App Pool configuration for the server in question.

Categories

Resources