programming the active directory - active-directory

I've got an asp application running but i want to search the Active Directory.
i am using vb (visual web developer 2008)
how do i search the active directory for a given user?
ie: user enters login name in text box, clicks submit. active directory is searched on-click for this user. when found user information is displayed .
Thanks

What version of the .NET framework can you use? Searching and looking up stuff in AD has become extremely easy in .NET 3.5 - see this great MSDN article by Ethan Wilanski and Joe Kaplan on using the security principals API for that.
If you're not on .NET 3.5 yet, you'll have to use the DirectorySearcher class and set up the search filters as you need. Getting the LDAP filter right is probably the biggest obstacle.
Robbie Allen also has two great intro article on System.DirectoryServices programming:
- Part 1
- Part 2
There are some really good resources at http://www.directoryprogramming.net (Joe Kaplan's site - he's a Microsoft Active Directory MVP), and Richard Mueller has some great reference excel sheets on what properties are available for each of the ADSI providers, and what they mean, and how their LDAP name is - see http://www.rlmueller.net.
Marc
EDIT: Ok- here's the .NET 2.0 / 3.0 approach:
// set the search root - the AD container to search from
DirectoryEntry searchRoot = new DirectoryEntry("LDAP://dc=yourdomain,dc=com");
// create directory searcher
DirectorySearcher ds = new DirectorySearcher(searchRoot);
ds.SearchScope = SearchScope.Subtree;
// set the properties to load in the search results
// the fewer you load, the better your performance
ds.PropertiesToLoad.Add("cn");
ds.PropertiesToLoad.Add("sn");
ds.PropertiesToLoad.Add("givenName");
ds.PropertiesToLoad.Add("mail");
// set the filter - here I'm using objectCategory since this attribute is
// single-valued and indexed --> much better than objectClass in performance
// the "anr" is the "ambiguous name resolution" property which basically
// searches for all normally interesting name properties
ds.Filter = "(&(objectCategory=person)(anr=user-name-here))";
// get the result collection
SearchResultCollection src = ds.FindAll();
// iterate over the results
foreach (SearchResult sr in src)
{
// do whatever you need to do with the search result
// I'm extracting the properties I specified in the PropertiesToLoad
// mind you - a property might not be set in AD and thus would
// be NULL here (e.g. not included in the Properties collection)
// also, all result properties are really multi-valued, so you need
// to do this trickery to get the first of the values returned
string surname = string.Empty;
if (sr.Properties.Contains("sn"))
{
surname = sr.Properties["sn"][0].ToString();
}
string givenName = string.Empty;
if (sr.Properties.Contains("givenName"))
{
givenName = sr.Properties["givenName"][0].ToString();
}
string email = string.Empty;
if (sr.Properties.Contains("mail"))
{
email = sr.Properties["mail"][0].ToString();
}
Console.WriteLine("Name: {0} {1} / Mail: {2}", givenName, surname, email);
}
Hope this helps!
Marc

Related

SamlCredential does not retrieve group attributes from Okta SAML response

I am using Okta as IDP and I have configured the user attribute statements and group attribute statements like this
And by providing a custom samluserdetails I am able to retrieve user attributes but not group attributes.
public class CustomSamlUserDetails implements SAMLUserDetailsService {
#Override
public Object loadUserBySAML(SAMLCredential cred) throws UsernameNotFoundException {
AppUser user = new AppUser();
user.setFirstName(cred.getAttributeAsString("firstName"));
user.setLastName(cred.getAttributeAsString("lastName"));
user.setLoginId(cred.getAttributeAsString("loginId"));
String groupname = cred.getAttributeAsString("role"); // comes null
return user;
}
}
Is there some config I missed or am I retrieving the group info in a wrong way?
EDIT:
If I use contains filter with some characters for example I have 3 groups test1, test2 and other1.
If I use contains filter *, I get null.
However if I use contains filter with test , I get test1 (and test2, if user is path of both groups).
Is wildchar not supported in case of groups?
What if in above case user was part of all 3 groups?
I am not an expert of OKTA but I statred working couple of weeks for one of my clients. I tested with * but it only worked for me for filter Regex. For other filters I never succeeded with *. For example the configuration without * worked perfectly for me.
OKTA CONFIG
I used the code String str = credential.getAttributeAsString("Groups");
But I have one issue that when I have more then one group I still get one group. I want to have list of groups instead.
EDIT - O6 Feb
Finally I restested and I am able to implement wildcard entry with regex I used the regex filter :
In java I got the groups as you suggested :
String[] str = credential.getAttributeAsStringArray("groups");
for(int i = 0; i< str.length; i++){
System.out.println(str[i]);
}
The result is :
Have a great day

How do you check in code if a request matches an EPiServer Visitor Group

We've set up a new "visitor group" in EPiServer 6r2, and we want to add a css class to the <body> tag of the site if the user is in that group, so different groups get different site designs. I'm trying to find out if the current visitor is in a matching group in the code-behind of a masterpage file in order to add this extra class and can't get the below code to return anything but false.
I'm not sure if the role name mentioned is the name you enter in the CMS UI when adding a visitor group.
Paul Smith blogged a proposed solution to this but I haven't been able to get it to return anything but false yet, and judging by the only comment on the blog article I'm not alone. Code sample #1 from this link (which is the one I'm using):
using EPiServer.Personalization.VisitorGroups;
...
bool match = EPiServer.Security.PrincipalInfo.CurrentPrincipal
.IsInRole("My Visitor Group", SecurityEntityType.VisitorGroup);
I found the developer guide to membership and role providers which states that replacePrincipal must be set to true for the correct principal to be in place. I checked and this is already the case for my config.
Documentation
EPiServer 7 doc
IPrincipal.IsInRole() extension
SecurityEntityType enum
Oddly I searched the 6r2 documentation from http://sdk.episerver.com/ and can't find the documentation for IPrincipalExtensions at all, even though I see the class in object browser in 6.2. in my sln. Details: Assembly EPiServer.ApplicationModules - C:\Windows\assembly\GAC_MSIL\EPiServer.ApplicationModules\6.2.267.1__8fe83dea738b45b7\EPiServer.ApplicationModules.dll - public static bool IsInRole(this System.Security.Principal.IPrincipal principal, string role, EPiServer.Security.SecurityEntityType type)
Member of EPiServer.Personalization.VisitorGroups.IPrinicipalExtensions
Please comment if you spot errors or I've missed anything as coding for EPiServer is a bit of a fog-of-war affair and I'm a little battle-weary.
Found it by browsing the object model and guessing. So much for documentation.
using EPiServer.Personalization.VisitorGroups;
using EPiServer.Security;
const string visitorGroupName = "Some users";
var groupHelper = new VisitorGroupHelper();
bool isPrincipalInGroup = groupHelper.IsPrincipalInGroup(
PrincipalInfo.CurrentPrincipal, visitorGroupName);
Tested and working in EPiServer 6r2 (aka 6.1).
String visitorGroupName must match the string entered into the "Name" box on the EPiServer admin interface when creating / editing the visitor group. See screenshot below:

How do I import Active Directory users into JIRA only from specific groups?

A caveat to begin with - I don't actually know if what I want to do is possible, particularly because I'm not well versed with LDAP/Active Directory or JIRA.
I'm trying to integrate my shiny new installation of JIRA with my existing active directory. What I want to do is set up some specific JIRA groups (e.g. in London\Security Groups\JIRA*) and then have JIRA only import the users who have membership of those groups. However, in the directory set up page in JIRA, I don't understand how to do this. It seems to indicate that I can import users and groups, but not users from groups.
What am I missing? (apart from expert level knowledge of AD!)
Update
Under my domain, I have an organisational structure like this:
London\Users
London\Security Groups\JIRA
Under the latter organisational unit, I have a security group called "jira-users". The former contains all users.
So far I've tried the following queries and none of them have worked :
(all prefixed with &(objectCategory=Person)(sAMAccountName=*)")
memberof=CN=jira-users,ou=London,ou=Security Groups,ou=JIRA,dc=mycompany,dc=local
memberof=CN=JIRA,ou=London,ou=Security Groups,dc=mycompany,dc=local
(prefixed with just &(objectCategory=Person)")
memberof=CN=jira-users,ou=London,ou=Security Groups,ou=JIRA,dc=mycompany,dc=local
Completed
The query that works is this :
memberof=CN=jira-users,OU=JIRA,OU=Security Groups,OU=London,DC=mycompany,DC=local
I hadn't realised that for a folder structure that is logically, left to right, London\Security Groups\JIRA, the organisational units need to be listed in reverse order.
Further Update
This only works when using the DirectorySearcher class for some reason, e.g.
DirectoryEntry rootEntry = new DirectoryEntry("LDAP://dc=mycompany,dc=local");
DirectorySearcher srch = new DirectorySearcher(rootEntry);
srch.SearchScope = SearchScope.Subtree;
srch.Filter = "(&(objectCategory=Person)(sAMAccountName=*)(memberof=CN=jira-users,ou=London,ou=Security Groups,ou=JIRA,dc=mycompany,dc=local))";
SearchResultCollection results = srch.FindAll();
This doesn't work in the LDAP explorer tool and subsequently, not in JIRA itself.
Last Update
So...for JIRA, you need to reverse the order AND remove the wildcard. Working query in the end is :
(&(objectCategory=Person)(memberof=CN=jira-users,OU=JIRA,OU=Security Groups,OU=London,DC=mycomapny,DC=local))
When you are setting up the user directory look under the User Schema settings. You should see a "User Object Filter" field. In there you should be able to add something like this:
(memberOf=cn=jira-users,ou=London,dc=mydomain,dc=com)
This will allow you to filter based on a specific LDAP group. Of course you will need to edit the values above to reflect your own environment.

How to get LDAP unboundid AttributeSyntax?

I'm trying to find out the unboundid AttributeSyntax type for a specific attribute name and it's simply not working.
Here's the example test code that I'm using to achieve this:
#Test
public void testLDAPSchema() {
try {
LDAPConnection connection = new LDAPConnection();
connection.connect("hessmain", 389);
connection.bind("CN=Administrator,CN=Users,DC=FISHBOWL,DC=NET", "password");
Schema s = connection.getSchema();
System.out.println(s.toString());
AttributeTypeDefinition atd = s.getAttributeType("directReports");
Set<AttributeTypeDefinition> oat = s.getOperationalAttributeTypes();
Set<AttributeSyntaxDefinition> l = s.getAttributeSyntaxes();
AttributeSyntaxDefinition asd1 = s.getAttributeSyntax(atd.getOID());
AttributeSyntaxDefinition asd2 = s.getAttributeSyntax(atd.getSyntaxOID());
AttributeSyntaxDefinition asd3 = s.getAttributeSyntax(atd.getBaseSyntaxOID());
connection.close();
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
From the above code, all the sets are empty. This also means that no matter which OID I pass to the schema getAttributeSyntax method that I will simply get a null return.
Is there any reason why I can't get the attribute syntaxes from an Active Directory server schema?
Thanks
I don't think that this is specific to the UnboundID LDAP SDK for Java. I'm not sure that Active Directory exposes this information over LDAP. When I perform a general LDAP search to retrieve schema information, I can see the attributeTypes and objectClasses attributes, but ldapSyntaxes isn't returned (and in fact ldapSyntaxes doesn't appear in the list of attribute types).
Similarly, none of the attribute type definitions includes a USAGE element, which is what is used to indicate that the attribute type is operational (e.g., "USAGE directoryOperation").
It may well be that Active Directory simply doesn't report this information at all. It could be that it provides some other non-standard way to get this information (e.g., a control or extended operation, or some other entry that can be retrieved), but if there is then I don't know about it.

Resolve domain address in/for Active Directory [.net]

Is there a simple way to resolve the Active Directory path of a Domain name in Active Directory?
E.g. your user account might be SITE\Username or DEPARTMENT\Username but the actual path of the domain SITE might be site.company.com or DEPARTMENT might be dep.company.com etc
I'm trying to find a way of turning DEPARTMENT into DC=dep,DC=company,DC=com etc for searching correctly in Active Directory...
What you probably have is a company with one forrest (company.com) and a couple of child domains (SITE and DEPARTMENT in your case). The SITE- and DEPARTMENT-bits are the NetBIOS representations of the domains. Is not very common that they differ from the corresponding DNS names but it is possible. Just make sure we're not talking about OU:s and "physical" Active Directory sites.
Assuming the above, here are a couple of options:
The following assumes that your application is running under an account with "forrest-wide read access" (the ability to access your different domains):
using System.DirectoryServices.ActiveDirectory;
// ...
DirectoryContext directoryContext
= new DirectoryContext(DirectoryContextType.Domain, "DEPARTMENT");
Domain domain = Domain.GetDomain(directoryContext);
String domainName = domain.Name;
String domainComponent = "DC=" + domainName.Replace(".", ",DC=");
Console.WriteLine(domainComponent);
(I haven't found a "System.DirectoryServices-built-in" way to transform domain.company.com to DC=domain,DC=company,DC=com but the simple string manipulation above should do the trick.)
If you're using a non-forrest-wide account (or if DEPARTMENT and SITE are not domains in the same forrest but in themselves separate forrests), then you'll have to maintain a list of usernames and passwords to use depending on the "DEPARTMENT" or "SITE"-strings:
// if(domainNetBios == "DEPARMENT")...
DirectoryContext directoryContext
= new DirectoryContext(DirectoryContextType.Domain,
"DEPARTMENT",
"UserInDEPARTMENT",
"PassForUserInDEPARTMENT");
If you're not willing to bind to the different forrests/domains to get the domain name/component you could try something along the lines of:
IPAddress[] addresses = Dns.GetHostAddresses("DEPARTMENT");
IPHostEntry host = Dns.GetHostEntry(addresses[0]);
Int32 dotIndex = host.HostName.IndexOf('.');
String domain =
host.HostName.Substring(dotIndex + 1, host.HostName.Length - dotIndex - 1);
Console.WriteLine(domain);
But the above assumes that the NETBios-name is the same as the first part of the DNS-name and that DNS resolution is working correctly. What we're doing above is to query for a list of domain controllers then removing the hostnames from the DNS-names. Not a particularly clean option...

Resources