How do I verify logged in user account against SQL Sever - sql-server

So, I'm trying to incorporate some kind of authentication into my WPF Application.
Currently, the application connects to a SQL Server, retrieves data from the database, inserts data into the database and updating data in the database. It works as intended.
What I would like to do next is when the Application starts up it checks whether the logged in user has permission to connect to and interact with the Server - and then deny access to the application or certain parts of it.
My SQL Server is using Windows Authentication for authentication, and the users will be on the same network and domain that will be connecting to the SQL Server.
I'm not very familiar with Windows Authentication and how it would work in my Application, so any help/examples/point in the right direction would greatly be appreciated.
[EDIT]:
Thanks to Jan W who pointed me in the direction of checking the username against the server in the SQL layer with IS_MEMBER, I stumbled upon HAS_DBACCESS.
With a little bit of playing around, I created this function to check if the current user has access to the Database. If not, I disable what I need to in the application or give the user a message that they have not got permission:
Private Shared Function HasDBAccess(connectionString As String) As Boolean
Dim command As Data.SqlClient.SqlCommand = New Data.SqlClient.SqlCommand
Dim reader As Data.SqlClient.SqlDataReader
Dim conn As Data.SqlClient.SqlConnection = New Data.SqlClient.SqlConnection(connectionString)
command.CommandText = "SELECT HAS_DBACCESS ('yourdatabasenamehere')"
command.CommandType = Data.CommandType.Text
command.Connection = conn
conn.Open()
reader = command.ExecuteReader()
If reader.HasRows Then
Do While reader.Read()
Dim hasAccess As Integer = reader.GetInt32(0)
Select Case hasAccess
Case 1
Return True
Case 0
Return False
End Select
Loop
End If
conn.Close()
End Function
Thanks Jan :)

First of all I think what you're after is to implement authorization not authentication. Authentication is already done by domain controller in your network.
Authentication versus Authorization
There is a lot of different approaches to the problem you are trying to solve depending on your business needs. I could imagine that you could have different acces roles defined as Domain Groups in your AD. Then you could check against AD if the user interacting with your application is a member of a group or not. It can be done in the application layer (How to check if a user belongs to an AD group?) or in the SQL layer (https://msdn.microsoft.com/en-us/library/ms186271.aspx)
Regards
Jan

Take a look at this:
WPF: Implementing Custom Authentication And Authorization
But I did it in this way:
CodeProject: Implement UI Element Authorization in WPF

Related

Which AD server will an LDAP session connect to?

I have a question regarding the LDAP. In my application (coded with VB6), we are getting all the active directory users for a given domain. There are 3 active directory servers on the domain. My application is having some problem when it tries to retrieve the users from the AD using LDAP. I have an error handler but it never triggers, it just seems to loop when trying to get the users in an Array. It does not Always happens. I noticed today that one of the AD server is in trouble. The server does not seem to work properly (AD Wise). Since the server is a client's property, there is no way i can remove the server for testing purpose.
Dim ObjUserCollection() As String
Dim objAdControler As ADControler.ComControler
Set objAdControler = New ADControler.ComControler
ObjUserCollection = objAdControler.GetUserCollectionFromwithGroup(PersonalSecurity.Security.Site.GroupAccess)
The error handler does never proc.
I should have checked deeper:
https://serverfault.com/questions/762699/load-balancing-ldap-from-a-domain-controller-via-f5
since my application does bind on the domain, it may or may not send the LDAP request on the faulted Active Directory.

Prevent database access outside the application

We have a MVC application running with SQL Server database.
We are using windows authentication, and when we want to give user access to our site we add them in the active directory group SEUser.
We have given login as well as access permission to SEUser group to our database as well.
But the problem is since the AD group has permission to database so the user belonging to that group not only can access website but can also connect to the database from outside the application and can make changes to it as well.
So I am searching a lot to find any way where I can restrict user group to access database only when the request comes through our application and not from outside.
For that the first approach I thought of is to use impersonation/connect as approach, and allow only worker process account to connect to the database,
But the problem is we are accessing current logged in user information within stored procedures also by using methods like SYSTEM_USER and IS_MEMBER which considers current logged in user only and so we cannot use worker process approach.
Is there any way I can achieve this for my particular scenario? Please help
The short answer is there is no capability that would allow an authorized user to connect from one program (i.e. your middle tier), but not another (i.e. an interactive query program such as SSMS).
The best advice I can give you is to design your system under the assumption that the users will find a way to connect directly to the database, and therefore restrict their permissions as much as possible to avoid any problem when they decide to do so.
One strategy to limit what users can do on the system when connecting to the DB directly is to use stored procedures to limit what they should be able to do on the DB (i.e. they have access to run the SPs, and nothing else), granting permissions only through the SP execution via signatures.
I also strongly recommend using auditing to detect any abuse of the users’ privileges. Given that you expect all users to connect via your middle-tier application, it should be relatively easy to detect unusual activity.
One trick you may find interesting as a workaround is to use logon triggers to try to avoid accidental access through non-authorized programs (AKA. avoid the “I didn’t know” excuse). But be warned: This is not a security boundary, and it is easy to bypass, but it will help you keep honest people honest.
For example:
I grant access to a specific group on my system, but I would like to limit this group as much as possible to my app:
CREATE LOGIN [myDomain\myGroup] FROM WINDOWS
So I will create a logon trigger that will check the application name on the session, and block any app I haven’t approved for these users.
CREATE TRIGGER connection_limit_trigger
ON ALL SERVER
FOR LOGON
AS
BEGIN
IF( IS_SRVROLEMEMBER('sysadmin') != 1 )
BEGIN
IF( IS_MEMBER('myDomain\myGroup') = 1 )
BEGIN
DECLARE #appName nvarchar(256)
SELECT #appName = program_name FROM sys.dm_exec_sessions where session_id = ##SPID
IF( #appName != 'My approved app' )
ROLLBACK;
END
END
END;
Notice that this trigger will affect ALL my users, so I added checks to avoid unnecessary restrictions on certain users.
I have a very simple app that I approved (See the ApplicationName property on the connection string):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
namespace SampleAppSql
{
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder cnnstrbldr = new SqlConnectionStringBuilder();
cnnstrbldr.ApplicationName = #"My approved app";
cnnstrbldr.DataSource = #"."; //local machine
cnnstrbldr.IntegratedSecurity = true;
using (SqlConnection conn = new SqlConnection(cnnstrbldr.ConnectionString))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandText = #"SELECT ##version;";
string vers = (string)cmd.ExecuteScalar();
System.Console.WriteLine(#"SQL Server version: {0}", vers);
}
conn.Close();
}
}
}
}
When a user of this group tries to connect to SQL Server, the trigger will check the application name, and if it doesn’t match, the logon trigger will cause the connection to fail:
C:\>g:\temp\SampleAppSql.exe
SQL Server version: Microsoft SQL Server 2016 (RTM) …
C:\>sqlcmd -E -S .
Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Logon failed for login 'myDomain\toto' due to trigger execution..
Please notice that this technique is not a security boundary, as the authorized users can simply manipulate the application name and bypass the trigger; but the offending user will not be able to deny that she/he tried to bypass your policy on purpose.
I hope this information helps.
For more details, I recommend the following articles:
Logon Triggers
(https://msdn.microsoft.com/en-us/library/bb326598.aspx)
Signing Stored Procedures in SQL Server (https://msdn.microsoft.com/en-us/library/bb669102(v=vs.110).aspx )
Customizing Permissions With Impersonation in SQL Server (https://msdn.microsoft.com/en-us/library/bb669087(v=vs.110).aspx )
SQL Server Audit (https://msdn.microsoft.com/en-us/library/cc280386.aspx )
-Raul
I don't think you should focus on verifying the application. I think you should instead verify the user's actions, in the Web Service (the MVC Controller). As this gives you the most fine grained control.
Then the Web Service should be the only component with direct network access to the database. There should be no harm in accessing the Web Service (the MVC Controller) from outside the intended UI (the MVC View)

Web service connection to SQL Server with AD account

I have a WCF web service that should always use a specific AD account, which has been granted access to the database, to execute SQL transactions. I read a couple of articles, but I'm obviously doing/understanding something wrong because I'm not getting it to work the way I want.
I figured that that web service should impersonate the AD user, so I enabled impersonation in the web service web.config:
<identity userName="dmn\wsusr" password="p#55w0rd" impersonate="true"/>
Then, since I'm technically using a Windows user to connect to SQL, I set the connection string as follows ("Integrated security=true;" for Windows authentication, right?):
Data Source=SQLSVR\INSTNC; Failover Partner=SQLSVR\INSTNC2; Initial Catalog=DB; Integrated Security=true;
For testing the connection I insert some values into a table. One of the columns of the table I'm inserting to has the following definition:
[LogUser] VARCHAR(75) NOT NULL DEFAULT USER
So, theoretically, the AD username of the user who opened the connection will automatically be inserted into the column. Unfortunately, however, the column contains my own AD username every time.
I'm testing the web service via a web site that uses Windows authentication, so I'm assuming that this plays a role in the cause of the problem. But the website authentication should be disregarded since this will be an externally accessible web service and SQL transactions should never rely on authentication between the client and the web service.
Thanks!
EDIT
I also tried:
Adding Trusted_connection to the connection string, but it yielded the same result as above.
Using User ID and Password in the connection string, but since the connection string only accepts SQL users, this resulted in a Login failure error
EDIT2
I suggested to my superiors that we should try the approach where you create a separate application pool for the service, set it up to run as the AD user, and allow the AD user to log on as a service (something I read somewhere) but they're not keen on that and reckon it should be a "last resort"

LDAP Authentication using VBA in MS Access

I am creating an Access project linked to a SQL Server. Instead of using Windows authentication for the SQL Server I want to use an application specific username/password and authenticate users myself using a login form. The reason is that other applications may connect to this database from a context where Windows authentication is not an option (FileMaker Server for instance).
I have found myriad discussions that cover this issue from one angle or another, but none that have actually enabled me to implement a solution. I do not have a lot of VBA or LDAP experience but I know this must be possible.
So, what I want to do is:
Ask the user for a username and password when they open the database.
Use that username and password to authenticate them
against our LDAP server.
Proceed if it passes, fail if it does not.
Can someone sketch out how this works or point me to a resource that describes this?
One way to accomplish this is to create a VBA procedure which loops through all of your linked tables and alters the connection string to embed the username and password from a login form.
You can get the syntax for the existing ODBC linked tables by going to the debug window and typing this:
? CurrentDb().TableDefs("My Table Name").Connect
Which should give you something similar to:
ODBC;DRIVER=SQL Server;SERVER=MYSQLSERVER001;UID=JPARKER;PWD=Pizza123;APP=2007 Microsoft Office system;DATABASE=MyDatabaseName
So your login form would capture the user name and password from the user, then store those as variables and use to build a new connection string. Then iterate through the tabledefs collection updating the connect property. Happens pretty quickly.

What's the point of creating a user in order to access the DB located at SQL Server 2008

So far, after creating DB with all the schema, all I have done so for was accessing them (tables) by reference through ConnectionStrings.
Now, twice, I've read that it's better to create a DB user and access the DB trhough that user by including him in the connectionString.
I'd like to know why so?
Thank for helping
Your question isn't that clear. It seems that you're asking if it is better to use windows security ("Integrated Security=SSPI" in the connection string) or a username/password ("User ID=myUsername;Password=myPassword;").
Its always better to use windows security. Having login information within the connection string is a security risk. Its in cleartext (unless you take some complicated steps to secure that section), and is sent across the wire as cleartext unless you set up a trusted connection between application and server.
Is it better to "create a db user and access the db trhough that user by including him in the connection string?" No. Its better to create a sql server login for user's windows identities and let them use those credentials to access the server.
You do this if you wish to connect as a specific user, rather than (for example) just using the context of the current user which your application is running under. However, if you use SQL Server authentication (i.e. username and password), you'd need to provide that password in the connection string, which is something of a security problem.
If the application has a group of anonymous users (or manages users/passwords itself) then its better to use a Windows login and run the application under a service account (which has minimal required access to the database).
If you're running an interactive application on the desktop, you should let those users connect to SQL server in their own context, by adding them to SQL Server with the required rights (e.g. db read/write , remove any higher functions). Obviously you would use groups to make administration simpler rather than adding individual users.

Resources