I have an MVC application that connects to SQL Server (I used a database first setup with ADO.NET Entity Framework 6.0). When I debug on my laptop it connects to the SQL Server correctly and renders the page without issue. But when I publish and connect to the remote server (which also is hosting the SQL Server instance) I get an error: Select permission was denied. Of note is that this is set up to only work when connected to the corporate network (or with a VPN), and the server is intranet only.
I have been looking at potential solutions, and the user account on the database has db_datareader and db_datawriter permissions. My connection string calls for integrated security=True.
I access this same database from desktop applications using those settings with no issues, so I am thinking that there is a difference with the way IIS is evaluating the user.
The server is set up to assign everyone into a single account for the purposes of database access, so all of the DOMAIN\USERS are mapped into a single account called DOMAIN\MyDatabaseUser.
This user has the correct permissions in the database/security/users property window.
I took a look at an answer for a similar issue that referred to the IIS Application Pool, but that issue was getting login failure, which I am not seeing.
Here is my connection string:
<connectionStrings>
<add name="PMToolsEntities" connectionString="metadata=res://*/Models.PMToolsModel.csdl|res://*/Models.PMToolsModel.ssdl|res://*/Models.PMToolsModel.msl;
provider=System.Data.SqlClient;
provider connection string="
data source=SERVER\MySQLExpressInstance;initial catalog=MyDatabase;
integrated security=True;
MultipleActiveResultSets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
I have tried setting integrated security to SSPI but I get the same result. I also, for grins, removed the integrated security setting entirely and then I get a login failure (login failed for user '') as expected.
Here is what the permissions look like for MyDatabaseUser:
I basically added everything except the deny items to be sure, but I'm not getting in still.
Here is a link to what ultimately helped me (along with a patient IT guy who let me browse around on the server that I wouldn't normally have access to).
On Windows Server 2012, in the IIS MMC snap in I could see that my web site had an Application Pool added specifically for the site called MySite. Windows automatically creates a virtual user that needs to be added to the SQL Server Logins (not the database users) called IIS APPPOOL\MySite. The trick is that you must not use the search function in SSMS as it will replace IIS APPPOOL with the ServerName and therefore fail to resolve the account.
Related
I have a .net core application which hosts on Window Server 2012 IIS in production. One of screen is to display the result from a select statement.
But I got the error
`The SELECT permission was denied on the object 'aaa', database 'bbb', schema 'dbo'.
The thing is that I can run the select query from Microsoft SQL Server Management Studio successfully.
The connection string in my code is
"Server=MyServer, Database=MyDatabase;Integrated Security=True"
I don't have an user account on the connection string, so please don't advise me to right click security\Users node on the database to grant the user read and write permission etc.
I think is it some set up in Windows Server?
Update:
In our test QA site, we have another Windows Server 2012. The same code, however the test web site just runs fine. So I think that there is a difference but I couldn't figure it out. The application folder security setting are same.
When testing on your local machine, the app runs in the context of your user account. This is the account used for connecting to the database with Integrated Security.
When deployed in IIS, the app runs in the context of a web site or virtual directory that maps to an IIS Application Pool. You can see these Application Pools in IIS Manager. The Application Pool runs in the context of a specific user account, and this is the account used for Integrated Security:
You need to find this account and give it access to your database. Certain common account types, such as Network Service and ApplicationPoolIdentity, will not work well with Integrated Security out of the box. You may need to take extra steps, or even create or request a special service account in Active Directory you can use instead.
When I deploy my app to a server, I'm getting the Login failed message. My DB and app are located on two separate physical machines. However this has not posed a problem when developing and testing locally and connecting out to the DB server; only after publishing.
Steps I've taken To attempt to resolve
In my Web.Config I've set Integrated security to false. When integrated security was true, it was giving the same error but with the machine name in place of the user name.
I placed valid credentials in the User ID: and Password: fields of the Web.Config. The credentials placed in Web.Config are also used to log into Sql Server Management Studio directly.
Within SSMS I've also verified those credentials will work under Windows Authentication and SQL Server Authentication.
Those credentials I've set in the app work when I log into the SSMS using Windows Authentication. Advice on how to resolve this would be greatly appreciated. Thanks!
By default, IIS runs your application under a local machine account. This account does not have any permissions to access your SQL Server. In order to achieve integrated security, you need grant it access. There are a few ways to do it, the thread Add IIS 7 AppPool Identities as SQL Server Logons will get you started.
Another way, which is preferred over adding the IIS account, is to create a service account in Active Directory and setting the App Pool Identity in IIS to the service account. Depending on your environment, you should work with your network admin and or DBA to set this up.
Your last option would be to simply use SQL Authentication.
Basic Problem:
I have a web application that accesses a SQL Server database on the same machine. The web app runs under its own app pool - let us call it MyAppPool. If I goto advanced settings in IIS Manager, I can see that MyAppPool runs under ApplicationPoolIdentity. When I make requests to the web app, I can open task manager and verify that the username of w3wp.exe is MyAppPool. In SQL Server, I have added a Windows User IIS AppPool\MyAppPool and given it necessary permissions to read from db. The problem is that I am getting a login failed for DOMAIN\MACHINE$ when a logon is attempted to SQL Server. Its beyond me. Why is the app not logging on as IIS AppPool\MyAppPool?
Details:
I know variants of this question have been asked elsewhere, but I am really stuck without a solution. I experimented adding a <identity impersonate="true" /> to the web.config. If I do this, I get a login failed for NT AUTHORITY\IUSR. I have tried accessing the web app from the machine on which it is hosted and get same login error. I am running IIS8, Windows Server 2012, and SQL Server 2012.
Closest question I could find is Why is my MVC app trying to log into my DB as my machine, and not as the App Pool identity?, and the solutions provided do not work. I cannot change Integrated Security to be false (I had this thing running in the past). Quoting https://stackoverflow.com/a/15145488/147530:
ApplicationPoolIdentity uses IIS AppPool\ApplicationPool for local
access, but DOMAIN\MACHINE-NAME$ for remote access
sounds reasonable. Question is why is ApplicationPoolIdentity not using IIS AppPool\MyAppPool identity when db is hosted on same machine??
Quoting another SO post, IIS application using application pool identity loses primary token?:
This application also connects to a SQL Server database using
Integrated Security=true in the connection string. If the database is
local, then we see that IIS APPPOOL\OurAppPoolName is used to connect
to the database; if the database is remote, then the machine account
OURDOMAIN\ourwebserver$ is used.
This is the behavior I want, but not getting it, and that is what I am asking in this question - I don't want to give permissions to DOMAIN\MACHINE-NAME$ to log onto SQL Server. Quoting https://stackoverflow.com/a/15445280/147530:
I think that's a bad idea, however, because it authorizes any program
running as NetworkService to access the database - not just your web
applications.
I tried one more thing, which was to enable Windows Authentication on IIS8 using this link http://www.iis.net/learn/install/installing-iis-85/installing-iis-85-on-windows-server-2012-r2#ModulesinIIS85 but this has also not solved the problem.
Fixed this problem. In SSMS, there is a path machine -> security -> logins which contains users who can log onto the machine. I had not added the apppool to this list. I had only added the apppool to machine -> databases -> my database -> security -> users
I have developer MVC4 + EF Code First + SQL Server 2008 web app. Uploaded it to prod server with IIS7. Created new credentials PC. Added empty database PCDB to SQL Server and assigned user PC to it with owner permission. When I run web app I get error
Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations
My connection string is
data source=174.xx.x.x;initial catalog=pcdb;user id=pc;password=xxxxx;
The exception is understandable, I can delete PCDB database and let EFCode First create it by itself. But how about credentials PC? I do not want to make PC user as administrator but without it EF Code First will not be able to create new database in SQL Server.
How to solve the problem?
The overall design starts with Forms or Windows authentication at the WebsiteASP.NET/ IIS.
and ends with Application and DB authentication you want/need. Application authorization is another topic. I will not discuss that here.
You dont actually state the authentication model desired.
So I will start with a disclaimer. This a suggestion that I WOULD use in a production site. But it is not the ultimate end game nor is it the ONLY short term solution you might consider.
This is a solution that a one man show can get working. And is secure and without excessive admin effort to keep running.
Use SQL server logon via Windows Auth
BUT you do not need to add every user to SQL server.
There is also the option of impersonation. But that can get tricky and this explanation is not NOT impersonation. That is another another approach.
first make sure Website is using Windows Authentication
set IIS to use Windows Authentication:
Now the APP Pool behind the website on IIS you have configured. .
Im going to suggest a Psuedo-service user in the APP pool as a good way to start.
ie WEBAPPLICATION_X_USER. You can have a separate user per APP pool. Each user can access only its DB. So you get application separation. Your enter a user and password here. IIS will encrypt and decrypt as required. (better than plan text in Web.config)
This user should have reduced auth on the server itself. NOT AN ADMIN user on domain or even local admin. Just enough so it can use Sql server to create a DB. So create a regular windows user
Let ASP.Net logon to DB. Let ASP.net encrypt and decrypt the password.
So now the situation is Windows AUTH on IIS. IIS has an App pool with a special windows user that can logon to SQL server. You have added this user to SQL server instance and Allocated this service user the ability create DBs. Dont give the user access to ALL Dbs :-) Just the one it will create. Plus public access (via EF).
Verify the user credential situation in your WEB APP.
See [System.Security.Principal.WindowsIdentity]
This should show your windows authenticated end user.
System.Environment.UserName should have the service user ID you placed in the IIS APP POOL.
Now when EF goes to create or access data on the SQL server instance, it will connect with
System.Environment.UserName if the WEB.CONFIG entry is set to use windows integrated security
<connectionStrings>
<add name="DbContextName" connectionString="Data Source=Your SQL server Instance;Initial Catalog=The DBNAME;Integrated Security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
And you KNOW the authenticated user.
httpContext will give it to you as does thread current principal.
HttpContext.User is by default mapped to {System.Security.Principal.WindowsPrincipal}
So you can perform application level checking.
The same approach should also work with Forms Authentication.
WARNING: If you have windows WPF approach (ie you are not using IIS and therefore no APP pool), then this approach MUST be changed and is more complex and no longer the best place to start.
I hope this helps you get started
I have a classic ASP app that I am trying to connect to a SQL Server 2008 database on a different server. The ASP app is being served from IIS7 on Windows Server 2008.
I have changed the web site's application pool to run under a specific windows account, that I have verified has access to the database on the remote server.
However, when I run the app in the browser, I get this error:
Application Error
Number: -2147217843 (0x80040E4D)
Source: Microsoft OLE DB Provider for SQL Server
Description: Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
Why is it trying to connect using NT AUTHORITY\ANONYMOUS LOGON?
Does the App pool identity not apply to classic ASP code?
How can I make this connect as a specific user?
EDIT
Here is the connection string I am using:
Provider=SQLOLEDB.1;Data Source=myDbServer;Initial Catalog=myDatabase;Integrated Security=SSPI
For a site to use the application pool identity for classic ASP, you need to change the credentials used for Anonymous Authentication. By default, the site will be set to use a specific user, namely IUSR.
Select Authentication from the IIS area of your site, then select Anonymous Authentication followed by Edit. Change from Specific user to Application pool identity.
It's advisable to use Windows authentication (integrated security) over SQL authentication so that you don't have credentials in your config files so that if those files are compromised, you don't lose control of the credentials.
Does your app impersonate the caller? You need to enable constrained delegation: Configuring Servers for Delegation.
you should specify a username and password for the connection string www.connectionstrings.com or set the IIS application to run as a specific user however that would then render a lot of the security settings in IIS obsolete.
Provider=SQLNCLI10;Server=myServerAddress;Database=myDataBase;Uid=myUsername; Pwd=myPassword;
And have a look here: aspfaq
Lastly, make sure anonymous access is disabled on the IIS site so that it actually impersonates the user you selected instead of passing the anonymous tokens through.