Active Directory and Roles

K

Kenneth Keeley

Hi,

I have seen and used an example of a login page that uses ASP.Net 1.1 and
Active Directory. I have recently updated the code to work with ASP.Net 2.0
and all is working. I have now been trying to ad roles to my Web site. I
would like to see a sample where a user could be authenicated against Active
Directory and the Users Roles would be based on the Active Directory group
membership.Can this be done? If so could somebody show me some sample code.

Thanks
Kenneth
 
D

Dominick Baier [DevelopMentor]

you are looking for a ActiveDirectory Role provider - somehting that is much
needed - but does not exist.

you have to do that manually using the usual LDAP techniques.
 
R

Robert Ginsburg

If you are using windows impersonation then WindowsPrincipal.IsInRole(...)
will check group membership. If you are using LDAP to check the
authentication but are not impersonating the user then you will have to
construct the group membership manually.
 
J

Joe Kaplan \(MVP - ADSI\)

Ryan wrote one a little while ago using the tokenGroups sample from our
book. I'll ask him to post it to our website.

Joe K.
 
D

Dominick Baier [DevelopMentor]

Ryan and I worked on that - it is not 100% working - but for most scenarios
it is fine.
 
J

Joe Kaplan \(MVP - ADSI\)

Ah, are there some config problems or something? I'll ask him about it
later. We should post what we have in any event.

Joe K.
 
K

Kenneth Keeley

Hi,

Robert Ginsburg said:
If you are using windows impersonation then WindowsPrincipal.IsInRole(...)
will check group membership. If you are using LDAP to check the
authentication but are not impersonating the user then you will have to
construct the group membership manually.

What did you mean by windows impersonation? could you show me a sample code
of how to authenicate a user and obtain the roles using this method.

Thanks
Kenneth
 
R

Robert Ginsburg

On the IIS security settings for your virtual directory, disable anonymous
access, enable any or all of the other authentication providers (basic,
windows integrated, digest, ...). In your web.config file, locate the
system.web section and make sure these entries are there
<authentication mode="Windows" />

<identity impersonate="true" />

Once you have done that your site is now setup for impersonation, depending
on the .NET version you must either get the identity from the My namespace
(for 2.X) or from the Context.User object (for 1.X). Cast the identity as a
WindowsPrincipal and simply call IsInRole. It will check domain groups for
you. Here is the MSDN reference for .NET 2.X

ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/dv_vbcn/html/f7e734bd-33d4-402e-8eed-ffc905f94fa0.htm
 
J

Joe Kaplan \(MVP - ADSI\)

I think he is using the Active Directory membership provider in ASP.NET 2.0
though, so he doesn't get a WindowsPrincipal. It uses LDAP, so he needs a
corresponding LDAP method to build roles as well (unless he can use protocol
transition).

Joe K.
 
R

Robert Ginsburg

Ok so if you are using the ActiveDirectoryMembershipProvider then you will
indeed have to code something. MSDN implies (see exceprt below) that you
dont need . Since this probably means that IIS is running as a local
anonymous account, you will probably have to wrap up the sample code in a
COM+ (whoop call that enterprise services) class and give it an AD identity
that has enough permissions to enumerate groups on other user objects

// from
http://msdn.microsoft.com/library/d...s/dnpag2/html/WSS_Ch3_ImpDirectAuth_WSE30.asp
If you use an LDAP-enabled directory service other than Active Directory or
ADAM to validate credentials, you may need to create a custom membership
provider. For more details on how to build custom ASP.NET 2.0 providers, see
Building Custom Providers for ASP.NET 2.0 Membership. Also, depending how
you store and retrieve account roles in your directory service, you may need
to implement a custom RoleProvider. For example, if you use an LDAP schema
for user roles that is not supported through
ActiveDirectoryMembershipProvider, you will need to implement a custom
RoleProvider to retrieve roles for your users.

In a custom RoleProvider class, you need to retrieve the user roles from the
directory service by overriding the GetRolesForUser() method. The code to
retrieve user roles from the directory service would look like the following
example.

public override string[] GetRolesForUser(string username)
{
using (DirectoryEntry rootEntry = new
DirectoryEntry(this.connectionString))
{
rootEntry.Username = this.username;
rootEntry.Password = this.password;

rootEntry.AuthenticationType = AuthenticationTypes.None;
rootEntry.RefreshCache();

//Search the user in the directory service
using (DirectorySearcher searcher = new
DirectorySearcher(rootEntry))
{
searcher.PropertiesToLoad.Add("memberOf");
searcher.PropertiesToLoad.Add(this.usernameAttribute);

searcher.Filter = String.Format("(&(objectClass=user)({0}={1}))",
this.usernameAttribute, username);
SearchResult result = searcher.FindOne();
DirectoryEntry userEntry = result.GetDirectoryEntry();

string[] roles = null;

PropertyValueCollection property =
userEntry.Properties["memberOf"];
if (property.Value is Array)
{
Array values = (Array)property.Value;
roles = new string[values.Length];
values.CopyTo(roles, 0);
}
else if (property.Value is string)
{
roles = new string[1];
roles[0] = (string)property.Value;
}
return roles;
}
}
}
 
J

Joe Kaplan \(MVP - ADSI\)

Right, and that is the kind of code we don't like as we don't like using
memberOf for enumerating group membership. It doesn't do full transitive
group membership expansion, includes both security and non-security groups
and doesn't include the primary group. The tokenGroups approach that I
referred to earlier addresses all of those problems. This approach is
generally very effective for AD and ADAM, although it is an AD-specific
feature, so it obviously won't work with 3rd party directories.

The credentials issue for access the directory can be solved a variety of
ways. Configuring the process account to access the directory is probably
the easiest, but you can also configure the app to impersonate a specific
account. You can also supply credentials to the LDAP server and store them
securely in configuration. With a third party directory, this is probably
the only viable option as they don't tend to support Windows auth. :) COM+
is also an option, but it is my least favorite as it is the hardest to
deploy. We actually cover a lot of this stuff in chapter 8 of our book. :)

Joe K.

--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services Programming"
http://www.directoryprogramming.net
--
Robert Ginsburg said:
Ok so if you are using the ActiveDirectoryMembershipProvider then you will
indeed have to code something. MSDN implies (see exceprt below) that you
dont need . Since this probably means that IIS is running as a local
anonymous account, you will probably have to wrap up the sample code in a
COM+ (whoop call that enterprise services) class and give it an AD
identity that has enough permissions to enumerate groups on other user
objects

// from
http://msdn.microsoft.com/library/d...s/dnpag2/html/WSS_Ch3_ImpDirectAuth_WSE30.asp
If you use an LDAP-enabled directory service other than Active Directory
or ADAM to validate credentials, you may need to create a custom
membership provider. For more details on how to build custom ASP.NET 2.0
providers, see Building Custom Providers for ASP.NET 2.0 Membership. Also,
depending how you store and retrieve account roles in your directory
service, you may need to implement a custom RoleProvider. For example, if
you use an LDAP schema for user roles that is not supported through
ActiveDirectoryMembershipProvider, you will need to implement a custom
RoleProvider to retrieve roles for your users.

In a custom RoleProvider class, you need to retrieve the user roles from
the directory service by overriding the GetRolesForUser() method. The code
to retrieve user roles from the directory service would look like the
following example.

public override string[] GetRolesForUser(string username)
{
using (DirectoryEntry rootEntry = new
DirectoryEntry(this.connectionString))
{
rootEntry.Username = this.username;
rootEntry.Password = this.password;

rootEntry.AuthenticationType = AuthenticationTypes.None;
rootEntry.RefreshCache();

//Search the user in the directory service
using (DirectorySearcher searcher = new
DirectorySearcher(rootEntry))
{
searcher.PropertiesToLoad.Add("memberOf");
searcher.PropertiesToLoad.Add(this.usernameAttribute);

searcher.Filter = String.Format("(&(objectClass=user)({0}={1}))",
this.usernameAttribute, username);
SearchResult result = searcher.FindOne();
DirectoryEntry userEntry = result.GetDirectoryEntry();

string[] roles = null;

PropertyValueCollection property =
userEntry.Properties["memberOf"];
if (property.Value is Array)
{
Array values = (Array)property.Value;
roles = new string[values.Length];
values.CopyTo(roles, 0);
}
else if (property.Value is string)
{
roles = new string[1];
roles[0] = (string)property.Value;
}
return roles;
}
}
}
Joe Kaplan (MVP - ADSI) said:
I think he is using the Active Directory membership provider in ASP.NET
2.0 though, so he doesn't get a WindowsPrincipal. It uses LDAP, so he
needs a corresponding LDAP method to build roles as well (unless he can
use protocol transition).

Joe K.

--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services
Programming"
http://www.directoryprogramming.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top