ASP .NET MVC Forms authorization with Active Directory groups
I'm attempting to authenticate using users and groups in ASP.NET MVC against Active Directory.
I have put the following attribute on all my classes (except the account class):
[Authorize (Roles="SubcontractDB Users")]
This group is found under OU=Area->OU=Groups->OU=Company->CN=SubcontractDB in active directory. I'm assuming I also need to setup a RoleManager in web.config which I've attempted to do as follows:
<roleManager defaultProvider="ADRoleProvider">
<providers>
<clear />
<add name="ADMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="ADConnectionString"
attributeMapUsername="sAMAccountName" />
</providers>
</roleManager>
My connection string is:
<add name="ADConnectionString"
connectionString="LDAP://blah.com:389/DC=blah,DC=wateva,DC=com"/>
Obviously I'm doing it wrong as this doesn't work. All I want to do is allow access to users that are a member of a certain group in AD.
So I ended up implementing my own authorize attribute and using that:
namespace Application.Filters
{
public class AuthorizeADAttribute : AuthorizeAttribute
{
public string Groups { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (base.AuthorizeCore(httpContext))
{
/* Return true immediately if the authorization is not
locked down to any particular AD group */
if (String.IsNullOrEmpty(Groups))
return true;
// Get the AD groups
var groups = Groups.Split(',').ToList<string>();
// Verify that the user is in the given AD group (if any)
var context = new PrincipalContext(ContextType.Domain, "server");
var userPrincipal = UserPrincipal.FindByIdentity(context,
IdentityType.SamAccountName,
httpContext.User.Identity.Name);
foreach (var group in groups)
if (userPrincipal.IsMemberOf(context, IdentityType.Name, group))
return true;
}
return false;
}
}
}
And then I can simply use the following above controllers or functions
Using Application.Filters;
...
[AuthorizeAD(Groups = "groupname")]
NB: You could simply use new PrincipalContext(ContextType.Domain);
however there is a bug in .NET 4.0 that throws a (0x80005000)
error at userPrincpal.IsMemberOf(...)
. See here for details.
If you would like to know how to redirect to another page based on failed authorization, check my answer here: Adding an error message to the view model based on controller attribute in ASP.NET MVC
It's no longer necessary to implement your own attribute for this functionality in ASP.NET MVC 3. The AspNetWindowsTokenRoleProvider
works with Active Directory users and groups. To use this with AuthorizeAttribute
you need to add the following to your web.config:
<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
<providers>
<clear />
<add
name="AspNetWindowsTokenRoleProvider"
type="System.Web.Security.WindowsTokenRoleProvider"
applicationName="/" />
</providers>
</roleManager>
Then, on your controllers or action methods, you can refer to Active Directory Groups like so:
[Authorize(Roles = "YOURDOMAIN\\Group1, YOURDOMAIN\\Group2")]