Carla Romere
asked on
Verifying User is Part of Active Directory Group aspx page
I am trying to figure out how to test if a user is part of an AD security group and allowing access to specific page content if they are. I found a script online at stackoverflow.com/question s/2188954/ see-if-use r-is-part- of-active- directory- group-in-c -sharp-asp -net, but I'm getting an error and can't figure out how to fix the error. THIS IS THE UNMODIFIED SCRIPT
public bool IsUserInSecurityGroup(string user, string group)
{
return IsUserInGroup(user, group, "tokenGroups");
}
public bool IsUserInAllGroup(string user, string group)
{
return IsUserInGroup(user, group, "tokenGroupsGlobalAndUniversal");
}
private bool IsUserInGroup(string user, string group, string groupType)
{
var userGroups = GetUserGroupIds(user, groupType);
var groupTokens = ParseDomainQualifiedName(group, "group");
using (var groupContext = new PrincipalContext(ContextType.Domain, groupTokens[0]))
{
using (var identity = GroupPrincipal.FindByIdentity(groupContext, IdentityType.SamAccountName, groupTokens[1]))
{
if (identity == null)
return false;
return userGroups.Contains(identity.Sid);
}
}
}
private List<SecurityIdentifier> GetUserGroupIds(string user, string groupType)
{
var userTokens = ParseDomainQualifiedName(user, "user");
using (var userContext = new PrincipalContext(ContextType.Domain, userTokens[0]))
{
using (var identity = UserPrincipal.FindByIdentity(userContext, IdentityType.SamAccountName, userTokens[1]))
{
if (identity == null)
return new List<SecurityIdentifier>();
var userEntry = identity.GetUnderlyingObject() as DirectoryEntry;
userEntry.RefreshCache(new[] { groupType });
return (from byte[] sid in userEntry.Properties[groupType]
select new SecurityIdentifier(sid, 0)).ToList();
}
}
}
private static string[] ParseDomainQualifiedName(string name, string parameterName)
{
var groupTokens = name.Split(new[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);
if (groupTokens.Length < 2)
throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName);
return groupTokens;
}
THIS IS THE SCRIPT WITH THE CHANGES I THINK I NEED TO MAKE:
public bool IsUserInSecurityGroup(string user, string group)
{
return IsUserInGroup(user, group, "tokenGroups");
}
public bool IsUserInAllGroup(string user, string group)
{
return IsUserInGroup(user, group, "tokenGroupsGlobalAndUniversal");
}
private bool IsUserInGroup(string user, string group, string groupType)
{
var userGroups = GetUserGroupIds(user, groupType);
var groupTokens = ParseDomainQualifiedName(group, "msds");
using (var groupContext = new PrincipalContext(ContextType.Domain, groupTokens[0]))
{
using (var identity = GroupPrincipal.FindByIdentity(groupContext, IdentityType.SamAccountName, groupTokens[1]))
{
if (identity == null)
return false;
return userGroups.Contains(identity.Sid);
}
}
}
private List<SecurityIdentifier> GetUserGroupIds(string user, string groupType)
{
var userTokens = ParseDomainQualifiedName(user, "user");
using (var userContext = new PrincipalContext(ContextType.Domain, userTokens[0]))
{
using (var identity = UserPrincipal.FindByIdentity(userContext, IdentityType.SamAccountName, userTokens[1]))
{
if (identity == null)
return new List<SecurityIdentifier>();
var userEntry = identity.GetUnderlyingObject() as DirectoryEntry;
userEntry.RefreshCache(new[] { groupType });
return (from byte[] sid in userEntry.Properties[groupType]
select new SecurityIdentifier(sid, 0)).ToList();
}
}
}
private static string[] ParseDomainQualifiedName(string name, string parameterName)
{
var groupTokens = name.Split(new[] { "\\" }, StringSplitOptions.RemoveEmptyEntries);
if (groupTokens.Length < 2)
throw new ArgumentException(Resources.Exception_NameNotDomainQualified + name, parameterName);
return groupTokens;
}
I changed line 14 and put in the name of the security group to which I'm testing. On line 29, "user" I think is where should be the currently logged in user. The error I see is on line 46 and the word "Resources" has the red squiggly line underneath with the error message: "The name 'Resources' does not exist in the current context." This looks like it should be straightforward, but I don't know if I'm missing a reference call or what. The script we use currently to get the logged in user is this:
string LoggedOnUser; // NT userid
System.Type oType = System.Type.GetTypeFromProgID("Wscript.Network");
object pc = System.Activator.CreateInstance(oType);
//Get NT userid data
LoggedOnUser = Request.ServerVariables["AUTH_USER"];
int pos = LoggedOnUser.IndexOf('\\');
if (pos > 0)
{
LoggedOnUser = LoggedOnUser.Substring(pos + 1);
}
if ( LoggedOnUser == "cromer" || LoggedOnUser == "spore" || LoggedOnUser == "rshields" || LoggedOnUser == "medwar" || LoggedOnUser == "dander" || LoggedOnUser == "bnovil")
{
admin.Visible = true;
}
This works, but I want to control permissions on this page at the AD level instead of having to add specific users to this page to give them permissions.
hi.. this is useful for you.....
''' <summary>
''' Function to return all the groups the user is a member od
''' </summary>
''' <param name="_path">Path to bind to the AD</param>
''' <param name="username">Username of the user</param>
''' <param name="password">password of the user</param>
Private Function GetGroups(ByVal _path As String, ByVal username As String, _
ByVal password As String) As Collection
Dim Groups As New Collection
Dim dirEntry As New _
System.DirectoryServices.D irectoryEn try(_path, username, password)
Dim dirSearcher As New DirectorySearcher(dirEntry )
dirSearcher.Filter = String.Format("(sAMAccount Name={0})) ", username)
dirSearcher.PropertiesToLo ad.Add("me mberOf")
Dim propCount As Integer
Try
Dim dirSearchResults As SearchResult = dirSearcher.FindOne()
propCount = dirSearchResults.Propertie s("memberO f").Count
Dim dn As String
Dim equalsIndex As String
Dim commaIndex As String
For i As Integer = 0 To propCount - 1
dn = dirSearchResults.Propertie s("memberO f")(i)
equalsIndex = dn.IndexOf("=", 1)
commaIndex = dn.IndexOf(",", 1)
If equalsIndex = -1 Then
Return Nothing
End If
If Not Groups.Contains(dn.Substri ng((equals Index + 1), _
(commaIndex - equalsIndex) - 1)) Then
Groups.Add(dn.Substring((e qualsIndex + 1), & _
(commaIndex - equalsIndex) - 1))
End If
Next
Catch ex As Exception
If ex.GetType Is GetType(System.NullReferen ceExceptio n) Then
MessageBox.Show("Selected user isn't a member of any groups " & _
"at this time.", "No groups listed", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
'they are still a good user just does not
'have a "memberOf" attribute so it errors out.
'code to do something else here if you want
Else
MessageBox.Show(ex.Message .ToString, "Search Error", & _
MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Try
Return Groups
End Function
End Class
''' <summary>
''' Function to return all the groups the user is a member od
''' </summary>
''' <param name="_path">Path to bind to the AD</param>
''' <param name="username">Username of the user</param>
''' <param name="password">password of the user</param>
Private Function GetGroups(ByVal _path As String, ByVal username As String, _
ByVal password As String) As Collection
Dim Groups As New Collection
Dim dirEntry As New _
System.DirectoryServices.D
Dim dirSearcher As New DirectorySearcher(dirEntry
dirSearcher.Filter = String.Format("(sAMAccount
dirSearcher.PropertiesToLo
Dim propCount As Integer
Try
Dim dirSearchResults As SearchResult = dirSearcher.FindOne()
propCount = dirSearchResults.Propertie
Dim dn As String
Dim equalsIndex As String
Dim commaIndex As String
For i As Integer = 0 To propCount - 1
dn = dirSearchResults.Propertie
equalsIndex = dn.IndexOf("=", 1)
commaIndex = dn.IndexOf(",", 1)
If equalsIndex = -1 Then
Return Nothing
End If
If Not Groups.Contains(dn.Substri
(commaIndex - equalsIndex) - 1)) Then
Groups.Add(dn.Substring((e
(commaIndex - equalsIndex) - 1))
End If
Next
Catch ex As Exception
If ex.GetType Is GetType(System.NullReferen
MessageBox.Show("Selected user isn't a member of any groups " & _
"at this time.", "No groups listed", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
'they are still a good user just does not
'have a "memberOf" attribute so it errors out.
'code to do something else here if you want
Else
MessageBox.Show(ex.Message
MessageBoxButtons.OK, MessageBoxIcon.Error)
End If
End Try
Return Groups
End Function
End Class
ASKER
I ended up getting this working by expanding on another stored procedure I had to display the users' groups. I will attach the stored procedures and my aspx code here.
GetLdapUserGroups.sql
aer-IsUserInGroup.sql
PageContent.txt
Page-LoadEvent.txt
GetLdapUserGroups.sql
aer-IsUserInGroup.sql
PageContent.txt
Page-LoadEvent.txt
ASKER
Well, I lied. The above script works on some pages, but not others. I'm not sure why yet. I purposefully removed myself from an AD group, but the page still loads admin content for me.
ASKER
Truly bizarre. Using the same script I uploaded, some security groups work with the code to prevent me from accessing what I want to protect. Other security groups do not. I can put in a group I've never been a member of and it stops me from seeing the content. But changing the group to a group I have been a member of, but am not currently, will still allow me to see the content.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I need to cancel this ticket as we've hired a developer to come in and help me get these resolved.
throw new ArgumentException(Resource
to:
throw new ArgumentException("Usernam