Background
I am trying to authenticate a user, and after that fetch it's attributes so I know what user groups have been assigned to it.
After many efforts I have finally managed to authenticate the user, and perform a searchrequest that actually returns an entry.
problem
The entry returned has no attributes in it, even though I requested some. When using Ad explorer I can verify thet there actually are attributes assigbned to it.
Check source below:
public IUserDto Authenticate(string username, string password)
{
if (string.IsNullOrEmpty(username))
return new UserDto() { Username = "Anonymous", Id = 1 };
try
{
NetworkCredential usercredential = new() { UserName = username, Password = password };
var conn = Connection;
var filter = $"(&(objectClass = user)(uid ={username}))";
string[] attributes = new string[] { "cn", "memberOf", "name" };
conn.Bind(usercredential);
SearchRequest searchrequest = new(null, filter, SearchScope.Base, attributes);
var response = conn.SendRequest(searchrequest);
if (response is SearchResponse searchResponse)
{
foreach (SearchResultEntry entry in searchResponse.Entries)
{
entry.ToString(); // gets executed
foreach (string attributename in entry.Attributes.AttributeNames)
{
attributename.ToString(); // is not executed
}
}
}
UserDto user = new()
{
Username = username,
};
return user;
}
catch (Exception e)
{
throw new ArgumentException($"{GetType().Name}.{nameof(Authenticate)} : {e.Message}", e);
}
}
I am aware that using the DirectoryServices dll/assembly may provide an easier way around this, but this makes my program platform dependent (windows), which I am trying to avoid.
What have I tried
Changing the SearchScope to anything else than SearchScope.Base
will generate an exception on the SendRequest
call:
System.DirectoryServices.Protocols.DirectoryOperationException: 'The object does not exist. 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of:
Changing the distinguishedName
parameter from the SearchRequest constructor
to not-null will generate an similar exception.
The question
Obviously I have overlooked something... What could it be? TIA
CodePudding user response:
As usual, the solution turned out to be ever so simple, I just had to change
var filter = $"(&(objectClass = user)(sAMAccountName = {username}))";
into
var filter = $"(&(objectClass=user)(sAMAccountName={username}))";
So... I really didnt expect the filter to be space sensitive. Removing the spaces from the filter clauses did the trick.
Also, I have changed the Scope to SearchScope.Subtree
and change the Searchroot to (in my case) "DC=sng, DC=local"
These parameters are stored in my appsettings files, and the complete (working) source now looks like this:
public IUserDto Authenticate(string username, string password)
{
if (string.IsNullOrEmpty(username))
return new UserDto() { Username = "Anonymous", Id = 1 };
try
{
NetworkCredential usercredential = new() { UserName = username, Password = password };
var conn = Connection;
conn.Bind(usercredential);
string filter= string.Format(_config.SearchFilter, username);
string[] attributes = new string[] { "cn", "memberOf", "name", "sAMAccountName","uid" };
SearchRequest searchrequest = new(_config.SearchBase, filter, SearchScope.Subtree, attributes);
var response = conn.SendRequest(searchrequest);
if (response is SearchResponse searchResponse)
{
foreach (SearchResultEntry entry in searchResponse.Entries)
{
entry.ToString();
foreach (string attributename in entry.Attributes.AttributeNames)
{
attributename.ToString();
}
}
}
UserDto user = new()
{
Username = username,
};
return user;
}
catch (Exception e)
{
throw new ArgumentException($"{GetType().Name}.{nameof(Authenticate)} : {e.Message}", e);
}
}
I hope someone else can take profit of the hours I spent fiddling and messing with this :)