sql connection string windows authentication c# winforms (not integrated) - c#

I am making a simple c#.net winform application which will connect to sql server.
I wnat it to have 2 ways to connect- Windows Authentication and SQL server Authentication.
From what I found online I came up so far with:
public static void SetConnectionStringParams(string dbAddress, bool isWinAuth, string user, string password)
{
if (isWinAuth)
{
_connectionString =
string.Format(
"Data Source={0};Database = {1};Integrated Security=True;Max Pool Size=1000;MultipleActiveResultSets=True;Connection Timeout=60",
dbAddress, DefaultDBname);
}
else
{
_connectionString =
string.Format(
"Data Source={0};Database = {1};User ID={2};Password={3};Max Pool Size=1000;MultipleActiveResultSets=True;Connection Timeout=60",
dbAddress, DefaultDBname, user, password);
}
}
which works great, but I couldn't found how in case of Windows Auth I force require user and password instead of using the Integrated Security=True...
Is there an API that do that? if not, would appreciate guidance how to do it.
Thank you,

Give this a shot
Ask user to enter windows username and password
Impersonate this user manually as by Microsoft and fetch users Principal & Identity
Now fork new thread with this Principal/Identity to talk with database with integrated security
Flush user, identity and principal on job completion or on exception

Related

Force user re-authentication after they change their Login Password

I 'm having a problem with my windows form project. I have a function for user change password of their login in SQL Server. User will do login on windows form with old password. After navigating to the change password function, they will be asked to provide new password and old password. New and old password are received, using this SQL command to change password
ALTER LOGIN [LOGIN_NAME]
WITH PASSWORD = 'NEW_PASS', OLD_PASSWORD = 'OLD_PASS';
But the problem is user also use old password and new password login to SQL Server in this session. After I stop and start project again, the old password had expired. I want when user submit new password, the application has to force their login again with it. Could anyone give me solution?
Thanks a lot!
P/S: I think I should talk more about the way user connect to database.
I'm using a connection string like this:
Program.connstr = "Data Source=" + Program.servername + ";Initial Catalog=" + Program.database + ";User ID=" + Program.mlogin + ";password=" + Program.password;
A user connects to a database with a authorized account in that database, and performs the tasks necessary. And the change of password will update the password of connection string.
Thank again!
Assuming that you create a new connection for every request to SQL database (that's how you should actually do), you can create some sort of SQL connection factory, which will create connections for your users. When this factory catches an SQL exception like login failed for user, switch to Your password is expired window, and ask for credentials again.
public class SqlConnectionFactory
{
public static SqlConnection CreateConnection()
{
try
{
string connectionString = $"Data Source={Program.servername};Initial Catalog={Program.database};User ID={Program.mlogin};password={Program.password};";
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
} catch (SqlException se) when (se.Number == 18456)
{
MessageBox.Show("Your password is invalid. Try to login again.");
Environment.Exit(0);
}
}
}
// Everywhere in your code
SqlConnectionFactory.CreateConnection().
Probably, you need a more beautiful approach than closing the application, but this is just a demo.
You may also want to create some methods for your SqlConnectionFactory like ExecuteAndReturnReader, which will create a connection, create a command, and return its reader after execution.

How to change password for login in SQL Server that was created with MUST_CHANGE option

I'm writing a Windows Forms application in C# in which users have to connect
to a SQL Server database. The potential users receive randomly built
passwords from the customer and the customers policy enforces that users are required to change the password (SQL Server - option MUST_CHANGE).
I'm having difficulties in providing a function which allows the users
to change the given password on their first attempt to login: every attempt
to connect to SQL Server with the provided credentials leads to
a SqlException with error number 18488 stating that the user has to change
the password - which is exactly what I'm trying to do.
I've tried to use:
an ALTER LOGIN statement as a SqlCommand
ALTER LOGIN 'someLogin' WITH PASSWORD = 'newPassword', OLD_PASSWORD = 'oldPassword'
a ServerConnection with a Server and Login object issuing a
ChangePassword(oldPassword, newPassword) request
var serverConnection = new ServerConnection(someSQlConnection);
serverConnection.Connect();
var server = new Server(serverConnection);
var login = new Login(server, 'someLogin') { LoginType =
LoginType.SqlLogin };
login.ChangePassword(oldPassword, newPassword);
The Problem is that already the attempt to connect to the SQL Server
fails, the password changing query doesn't even get executed.Anybody can provide a hint how to solve this issue ?
Use the static ChangePassword method to set the new password:
System.Data.SqlClient.SqlConnection.ChangePassword(someSQlConnection,
"new_password");
As per documentation:
This method opens its own connection to the server, requests the
password change, and closes the connection as soon as it has
completed.

Connection to SQL Server fails if executed from a Windows Service

I've got a little C# app that drops and re-created a database for my tests to run. This app is executed in TeamCity that runs under NT AUTHORITY\SYSTEM user.
Here is my application:
public void SetupDatabase()
{
var childConnectionString = "Server=.\sqlexpress;Database=MyDatabase;Uid=Tester;Pwd=Tester;Trusted_Connection=True;MultipleActiveResultSets=True;";
var masterConnectionString = "Server=.\sqlexpress;Database=master;Uid=Tester;Pwd=Tester;Trusted_Connection=True;MultipleActiveResultSets=True;";
Console.WriteLine("Using child connectionString: {0}", childConnectionString);
Console.WriteLine("Using Master connectionString: {0}", masterConnectionString);
Console.WriteLine("Connection for master using this user: {0}", GetUser(masterConnectionString)); // <- this one shows NT AUTHORITY\SYSTEM
Console.WriteLine("Connection for child using this user: {0}", GetUser(childConnectionString)); // <- this one fails saying
// Cannot open database "MyDatabase" requested by the login. The login failed.
// Login failed for user 'NT AUTHORITY\SYSTEM'.
}
private string GetUser(string connectionString)
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
var command = new SqlCommand("select SYSTEM_USER", connection);
var reader = command.ExecuteReader();
while (reader.Read())
{
var user = reader.GetString(0);
return user;
}
}
return "";
}
I'm specifying SQL Server username/password in the connection string, why is Login failed for user 'NT AUTHORITY\SYSTEM'?? I'm not using Windows Authentication.
Fair enough, System account will fail to login to MyDatabase because it is not set up on that database.
Funny thing - when I execute the same application myself I get no exceptions and my username is printed
Connection for master using this user: MACHINENAME\trailmax
Connection for child using this user: MACHINENAME\trailmax
Why-oh-why is username/password from the connection string are ignored and trying to login as Windows-Auth.
p.s. the user Tester is set up on MyDatabase and when I go to SSMS and use credentials from the connection string, I can login and can execute all the commands I need. The problem appears when I run the same executable from TeamCity.
You set Trusted_Connection=True, which means use windows authentication. If you want SQL authentication, then set Trusted_Connection=False.
Get rid of trusted_connection=true from the connection string
Take Trusted_Connection=True; out of your connection string. This overrides any user name or password.
Then have a think about your security architecture - do you really want to be hard coding and compiling logins and passwords into your windows servce?
Remove trusted_connection=true from your connection string as that is gonna override the user name you have configured. In the case of Windows Services, it's gonna use NT AUTHORITY\SYSTEM.

Validate User via remote active directory

I have a strange scenario that I hope you guys can help with, I need to validate the current logged in user with active directory, this isn't a problem if they are on the network but in some instances they will be on another network (visiting clients) and in order for them to use the software they need to validate against AD.
At present I am using the following code am I correct in saying this will work locally and remotely? If not how can I get it to validate credentials?
DomainServer = new ActiveDirectory(Microsoft.Exchange.WebServices.Data.ExchangeVersion.Exchange2010, "LDAP://DOMAIN.NAME", "https://exchange.domain.name/ews/exchange.asmx");
DomainServer.connect();
if (!DomainServer.isConnected())
{
domain_errors = "Unable to connect to Active Directory.";
}
class ActiveDirectory
{
private ExchangeService _ExchangeServer;
private DirectoryEntry _searchRoot;
private DirectorySearcher _search;
private SearchResult _searchresult;
private ExchangeVersion _ExchangeVer;
private string _ActiveDirectoryAddress;
private string _ActiveDirectoryURL;
public ActiveDirectory(ExchangeVersion Ver, string ActiveDirectoryAddress, string ActiveDirectoryURL)
{
_ActiveDirectoryURL = ActiveDirectoryURL;
_ActiveDirectoryAddress = ActiveDirectoryAddress;
_ExchangeVer = Ver;
}
public void connect()
{
_ExchangeServer = new ExchangeService(_ExchangeVer);
_ExchangeServer.UseDefaultCredentials = true;
_ExchangeServer.Url = new Uri(_ActiveDirectoryURL);
_ExchangeServer.Timeout = 60;
}
public bool isConnected()
{
if (_searchRoot.Properties.Count > 0){
return true;
} else {
return false;
}
}
}
Windows caches usernames and passwords on local machines so that a domain user can login even if the machine, such as a laptop, is not connected to the domain. Since Windows is essentially handling the authentication for you, all you really need to do is authorize who can use the software. I can think of a few possibilities.
First, in the database, you could maintain a user table with the SIDs and usernames of those users with access to the software. When a user executes the program, check that the SID of the currently logged in user is in that table. This way, you can restrict what users can actually execute the software without connecting to Active Directory. This would also allow you to revoke access at the database level.
Secondly, does the database server have access to the Active Directory? If so, create a group in AD for users with access to this system, then grant that group access in the database. Set the database connection to use Windows authentication. Therefore, if the person is in that group, they have access to the database. Otherwise, they do not. Then, you can control access just by adding or removing them from that group and security will be controlled at the database level.
Third (and I'm not a fan of this one), if you have a web server, run a web service (using HTTPS of course) that accepts a username and password and then use that web service to connect through your firewall and authenticate against AD. Then, just return a result to your application. This presents some security concerns with passing credentials to a web service and opening connections through the firewall.

getting domain\username for web app on intranet without logging in

I have a web app on our intranet (VS 2005). There are a couple pages that don't require the user to be logged into the app (feedback and the default page). I am trying to get the domain and username to display and/or send with the feedback. Is there a way to do this without requiring the user to log in? I've tried this.Request.ServerVariables["LOGON_USER"] and this.User.Identity.Name, but neither of them worked.
Edit:
I should have mentioned most of the users have Windows 2000 on their machines. It works on my development machine (XP), but not on the production network (where I have 2000).
Theresa, I think this is what you're looking for...
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal principal = (WindowsPrincipal)Thread.CurrentPrincipal;
WindowsIdentity identity = (WindowsIdentity)principal.Identity;
String userName= principal.Identity.Name;
Assuming you have turned Windows Authentication on in IIS for your site:
public string user_Name
{
get
{
string x = Page.User.Identity.Name;
x = x.Replace("YOURDOMAIN\\", "");
return x;
}
}
The x = x.Replace("DOMAIN\", ""); strips out the DOMAIN sectionof the user acccount e.g NISSAN\rmcdonough

Categories

Resources