Validate user in intranet application - c#

I need to use the windows credentials to allow my users to log in an intranet application. I am planning to create a table with usernames and roles and compare the username from Environment.UserName with my table. How safe is to relay on this? Is there a better way to achieve this task?
Thank you in advance.

You can do this using active directory authentication:
Bellow is sample code that you can try in your application.
string domainUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
string[] paramsLogin = domainUser.Split('\\');
string domain = paramsLogin[0].ToString();
string LdapPath = "";
string strDomainPath = DomainPath();
LdapPath = string.Format("LDAP://{0}/{1}", DomainName, strDomainPath);
string username = LoginUser.UserName;
string password = LoginUser.Password;
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (result != null)
{
IsLoginSucess = true;
//Do your stuff here
}
// Update the new path to the user in the directory
LdapPath = result.Path;
string _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
IsLoginSucess = false;
}

If you are developing in a Windows application, take a look at this:
Authenticate user in WinForms (Nothing to do with ASP.Net)
System.Security.Principal.WindowsIdentity.GetCurrent() will give you the current Windows user
If you are developing a Web application, there is built in-support, you would need to have relevant entries in your web.config file
Using windows authentication in asp.net with c#
HttpContext.Current.User.Identity will get you the user identity

Related

How to authenticate users in C# LDAP

I am new to LDAP related coding and today I am asked to develop a code to check the users authentication against LDAP.
The tutorials I have found online are so simple but our company's Directory is so complicated that I don't know how to write a code for that. Here is the info of the LDAP . I have changed the company name to hide the name.
uri = ldaps://ABC.ad.XYZ.com:636
user_filter = memberOf=CN=TENXAIRFLOWPROD,OU=Security Groups,OU=Normal Users and Groups,OU=Account Management Services,OU=AD Master OU,DC=ABC,DC=ad,DC=XYZ,DC=com
user_name_attr = sAMAccountName
superuser_filter = memberOf=CN=TENXAIRFLOWPROD_ADM,OU=Security Groups,OU=Normal Users and Groups,OU=Account Management Services,OU=AD Master OU,DC=ABC,DC=ad,DC=XYZ,DC=com
bind_user = SCGLOBAL\twiki
bind_password_cmd = python /bns/tenx/airflow/ldap_password.py
basedn = DC=ABC,DC=ad,DC=XYZ,DC=com
search_scope = SUBTREE
Here is a code I have developed but it gives me error:
string username = "myUserName";
string domain = "ldaps://ABC.ad.XYZ.com:636";
string pwd = "myPasword";
try
{
DirectoryEntry entry = new DirectoryEntry(domain, username, pwd);
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
lblError.Text=("Login Successful");
//search some info of this user if any
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
SearchResult result = search.FindOne();
}
catch (Exception ex)
{
lblError.Text=("Login failed: " + ex.ToString());
}
Could anybody help plz?
Comment: According to the admin , I have been assigned to the group in AD. But how can I make sure I can access it?
It seems like Active Directory. If so, you could just use PrincipalContext.
public bool ValidateCredentials(string domain, string username, string password)
{
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
return context.ValidateCredentials(username, password);
}
}
public bool IsUserInAdGroup(string domain, string username, string adGroupName)
{
bool result = false;
using (var context = new PrincipalContext(ContextType.Domain, domain))
{
var user = UserPrincipal.FindByIdentity(context, username);
if (user != null)
{
var group = GroupPrincipal.FindByIdentity(context, adGroupName);
if (group != null && user.IsMemberOf(group))
result = true;
}
}
return result;
}
Please make sure to reference System.DirectoryServices.AccountManagement.

Creating LDAP Connection on .NET

I am trying to Create LDAP Cnnection using c# .
I found this server which gives LDAP Server to Test
http://www.forumsys.com/en/tutorials/integration-how-to/ldap/online-ldap-test-server/
I have googled many post and Tried to create a consolidated Code
string domain = "ldap://ldap.forumsys.com/ou=mathematicians";
string username = "cn=read-only-admin,dc=example,dc=com";
string password = "password";
string LdapPath = "Ldap://ldap.forumsys.com:389/ou=scientists,dc=example,dc=com";
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
// Update the new path to the user in the directory
LdapPath = result.Path;
string _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user." + ex.Message);
}
This code is not connecting it is giving unexpected error ..
I also Tried some other Credentials , But they are not helping either ...
AUTH_LDAP_SERVER_URI = “ldap://ldap.forumsys.com”
AUTH_LDAP_BIND_DN = “cn=read-only-admin,dc=example,dc=com”
AUTH_LDAP_BIND_PASSWORD = “password”
AUTH_LDAP_USER_SEARCH = LDAPSearch(“ou=mathematicians,dc=example,dc=com”,
ldap.SCOPE_SUBTREE, “(uid=%(user)s)”)
--------------------
$config[‘LDAP’][‘server’] = ‘ldap://ldap.forumsys.com';
$config[‘LDAP’][‘port’] = ‘389’;
$config[‘LDAP’][‘user’] = ‘cn=read-only-admin,dc=example,dc=com';
$config[‘LDAP’][‘password’] = ‘password';
-------------------------
$config[‘LDAP’][‘server’] = ‘ldap://ldap.forumsys.com/ou=mathematicians';
$config[‘LDAP’][‘port’] = ‘389’;
$config[‘LDAP’][‘user’] = ‘gauss';
$config[‘LDAP’][‘password’] = ‘password';
--------------------------
OpenDSObject/GetObject functions, but don’t see a way to run a query with the ASDI objects.
Set LDAP = GetObject(“LDAP:”)
Set root = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389″, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
Set ou = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389/ou=mathematicians,dc=example,dc=com””, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
Set user = LDAP.OpenDSObject(“LDAP://ldap.forumsys.com:389/uid=riemann,dc=example,dc=com”, “cn=read-only-admin,dc=example,dc=com”, “password”, 0)
I need some suggestion what I am missing . any resource will be helpful
I had a somewhat similar issue with this server and google sent me here.
One issue I see is that case sensitive issue in LDAP path. Also we should specify the AuthenticationType as well.
Please check following code block which should work.
string ldapServer = "LDAP://ldap.forumsys.com:389/ou=scientists,dc=example,dc=com";
string userName = "cn=read-only-admin,dc=example,dc=com";
string password = "password";
var dirctoryEntry = new DirectoryEntry(ldapServer, userName, password, AuthenticationTypes.ServerBind);
try {
object nativeObject = dirctoryEntry.NativeObject;
//Rest of the logic
} catch (Exception ex) {
//Handle error
}
Trying using PrincipalContext to connect to the LDAP server. Here is a good how-to article I referenced when I was getting started: http://ianatkinson.net/computing/adcsharp.htm
ctx = new PrincipalContext(
ContextType.Domain,
"contoso.local",
"OU=Security Groups,OU=Contoso Inc,DC=contoso,DC=local",
"contoso\sysadmin",
"P#ssword1");
Namespace - using System.DirectoryServices.Protocols;
methode -
private bool ldapValidateUser(string fullname, string password)
{
try
{
LdapDirectoryIdentifier ldap = new LdapDirectoryIdentifier("Directory Host", true, false);
LdapConnection connection = new LdapConnection(ldap);
connection.AuthType = AuthType.Basic;
string ldapuser = "cn=" + fullname + ",ou=Org Unit,dc=Value,dc=local";
connection.Credential = new System.Net.NetworkCredential(ldapuser, password);
connection.Bind();
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return false;
}

Unable to get the user name and role of the user accessing the website

I am trying to get the name and role of the user who is currently accessing the web application but the code I have written fetches the server user name.
Could you please review the below code that I have written and tell a solution to this problem.
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
string[] stringSeparators = new string[] { "\\" };
string[] uname = userName.Split(stringSeparators, StringSplitOptions.None);
userName = uname[1];
List<string> userRoles = new List<string>();
userRoles = getUserRole(userName);
public List<string> getUserRole(string userName)
{
List<string> userNestedMembership = new List<string>();
DirectoryEntry domainConnection = new DirectoryEntry(); // Use this to query the default domain
DirectorySearcher samSearcher = new DirectorySearcher();
samSearcher.SearchRoot = domainConnection;
samSearcher.Filter = "(samAccountName=" + userName + ")";
samSearcher.PropertiesToLoad.Add("displayName");
SearchResult samResult = samSearcher.FindOne();
if (samResult != null)
{
DirectoryEntry theUser = samResult.GetDirectoryEntry();
theUser.RefreshCache(new string[] { "tokenGroups" });
foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])
{
System.Security.Principal.SecurityIdentifier mySID = new System.Security.Principal.SecurityIdentifier(resultBytes, 0);
DirectorySearcher sidSearcher = new DirectorySearcher();
sidSearcher.SearchRoot = domainConnection;
sidSearcher.Filter = "(objectSid=" + mySID.Value + ")";
sidSearcher.PropertiesToLoad.Add("distinguishedName");
SearchResult sidResult = sidSearcher.FindOne();
if (sidResult != null)
{
string role = (string)sidResult.Properties["distinguishedName"][0];
role = role.Substring(3, role.Length - 3);
string[] roles = role.Split(',');
userNestedMembership.Add(roles[0]);
}
}
}
}
I have not done any changes in web config.
userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
That is getting you the wndows user name, which is likely the apppool name.
Have you set thr web config and IIS to know thet you want to use windows auth?
(or if you are not, try using the HTTP Context
HttpContext.Current.User.Identity.Name
Hope this helps, or at least gives you a steer in the right direction
The issue probably doesn't lie in the code, but in environment configuration. There are specific requirements to be met, to make System.Security.Principal.WindowsIdentity.GetCurrent().Name work as you want, as it gets the user on the server side. Here is nice post describing what could be done to make IIS work under user account (with Windows Authentication).

Active Directory Performance issue in Asp.net

I have using active directory login
I got some performance issue
This is my code
public bool IsAuthenticated(String domain, String username, String pwd)
{
String domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry("LDAP://" + _path, domainAndUsername, pwd);
try
{ //Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
//Update the new path to the user in the directory.
_path = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user. " + ex.Message);
}
return true;
}
When i enter correct user name and password, it's work well and fast.
But when i enter wrong username and password ,then it's loading very slow.
This two line coding
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
taking long time to return the result while login inputs are wrong.
So My question is
Why those line taking long time to load, whenever i put wrong login details?
Why those line taking quick time to load, whenever i put correct logindetails?
Already a person asked this question in SO
Is using DirectoryServices.NativeObject slow/bad?
But no one answering for that. Please tell me the solution :)
It takes a long time because it has to check every object to compare with the input as it never find the correct one.
However, this is a unnecessarily complicated way to authenticate users on active directory.
This is much easier:
public bool ValidateCredentials(string domain, string username, string password)
{
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain))
{
return context.ValidateCredentials(username, password);
}
}
Then update the values afterwards.

Using C# to authenticate user against LDAP

I'm using DirectorySearcher to search for a user entry in LDAP server.
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://myserver/OU=People,O=mycompany";
de.AuthenticationType = AuthenticationTypes.None;
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(uid=" + model.UserName + ")";
SearchResult result = deSearch.FindOne();
I'm able to get th intended output in result variable.
However If I try to authenticate the same user by providing password in directory entry, I always get following error.
"The user name or password is incorrect."
DirectoryEntry entry = new DirectoryEntry("LDAP://myserver/OU=People,O=mycompany", username, password);
DirectorySearcher search = new DirectorySearcher(
entry,
"(uid=" + username + ")",
new string[] { "uid" }
);
search.SearchScope = System.DirectoryServices.SearchScope.Subtree;
SearchResult found = search.FindOne(); ->>>>>this is where I get wrong credential error.
The username and password are for the user I want to authenticate.
Can anyone tell me what I'm doing wrong here or how to debug this.
This username, password within this line:
DirectoryEntry("LDAP://myserver/OU=People,O=mycompany", username, password);
should be for an account that has permission for directory lookup. It could be a service account or testing purpose try with your own. This shouldn't be the user/pass of someone who you are trying to authenticate.
If you want to authenticate, you can use following steps using PrincipalContext:
using(var context = new PrincipalContext(ContextType.Domain, "mydomain", "mydomain\serviceAcct", "serviceAcctPass")) {
//Username and password for authentication.
return context.ValidateCredentials(username, password);
}
"serviceAcct" = an account within domain users that has permission for directory lookup.
"serviceAcctPass" = password for that service account.
As I said, for testing you can try with your own user/pass context.
Also, make sure supplied username has either "domain\username" or "username#domain" formatting.
Here we are getting the active directory user details and we can use DomainName and UserRole from web.config file
bool isAdmin = false;
RegisterInput model = new RegisterInput();
NewUserInput usr = new NewUserInput();
SearchResultCollection results;
string mobileNumber = string.Empty;
using (DirectoryEntry domainEntry = new DirectoryEntry("LDAP://" + AppSettings.DomainName))
{
using (DirectorySearcher searcher = new DirectorySearcher(domainEntry, "userPrincipalName=" + userName + "#" + AppSettings.DomainName) { Filter = string.Format("(&(objectClass=user)(samaccountname={0}))", userName) })
{
results = searcher.FindAll();
if (results.Count > 0)
{
usr.FirstName = results[0].GetDirectoryEntry().Properties["givenName"].Value.ToString();
usr.LastName = results[0].GetDirectoryEntry().Properties["sn"].Value?.ToString();
usr.EmailAddress = results[0].GetDirectoryEntry().Properties["mail"].Value?.ToString();
mobileNumber = results[0].GetDirectoryEntry().Properties["mobile"]?.Value?.ToString();
dynamic userRoleList = results[0].GetDirectoryEntry().Properties["memberOf"];
if (userRoleList != null)
{
foreach (var role in userRoleList)
{
string[] split = role.ToString().Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
bool result = split.Any(x => x.ToLowerInvariant() == AppSettings.UserRole.ToLowerInvariant());
if (result)
{
isAdmin = true;
break;
}
}
}
}
}
}
model.NewUser = usr;

Categories