11

How can I determine if a user, in say Access, is a member of an Active Directory Security Group?

I'd rather not build a whole authentication system into my little Access DB.

Thanks

braX
  • 11,506
  • 5
  • 20
  • 33
Allain Lalonde
  • 91,574
  • 70
  • 187
  • 238

3 Answers3

14

I'm late to the game with this, but the code you need is below. It gets user names and domain names for you.

Note that I'm not using objGroup.Ismember - that's actually the correct method to use - I'm enumerating the list of groups that the user is in, because it's much easier to debug and there's no appreciable performance penalty.

...And I lifted the code from an earlier project, in which I needed to check membership of a 'Read Reports' group, an 'Edit Data' Group, and an 'Edit System Data' group, so that I could choose which controls to enable and which forms to open read-only. Enumerating groups once was faster than three separate checks.

Public Function UserIsInGroup(GroupName As String, _
                              Optional Username As String, _
                              Optional Domain As String) As Boolean
'On Error Resume Next

' Returns TRUE if the user is in the named NT Group.

' If user name is omitted, current logged-in user's login name is assumed.
' If domain is omitted, current logged-in user's domain is assumed.
' User name can be submitted in the form 'myDomain/MyName' 
'                                        (this will run slightly faster)
' Does not raise errors for unknown user.
'
' Sample Usage: UserIsInGroup( "Domain Users")

Dim strUsername As String
Dim objGroup    As Object
Dim objUser     As Object
Dim objNetwork  As Object

UserIsInGroup = False

If Username = "" Then
    Set objNetwork = CreateObject("WScript.Network")
    strUsername = objNetwork.UserDomain & "/" & objNetwork.Username
Else
    strUsername = Username
End If

strUsername = Replace(strUsername, "\", "/")
If InStr(strUsername, "/") Then
    ' No action: Domain has already been supplied in the user name
Else    
    If Domain = "" Then
        Set objNetwork = CreateObject("WScript.Network")
        Domain = objNetwork.UserDomain
    End If        
    strUsername = Domain & "/" & strUsername        
End If

Set objUser = GetObject("WinNT://" & strUsername & ",user")    
If objUser Is Nothing Then    
    ' Insert error-handler here if you want to report an unknown user name
Else
    For Each objGroup In objUser.Groups
        'Debug.Print objGroup.Name
        If GroupName = objGroup.Name Then
            UserIsInGroup = True
            Exit For
        End If
    Next objGroup
End If

Set objNetwork = Nothing
Set objGroup = Nothing
Set objUser = Nothing

End Function

Hopefully this late submission is of use to other developers: when I looked this up for the first time, back in 2003, it was like nobody had ever used AD groups in Excel or MS-Access.

mwolfe02
  • 23,787
  • 9
  • 91
  • 161
Nigel Heffernan
  • 4,636
  • 37
  • 41
  • 3
    For the record, this is still quite useful in 2017. :) – Andre Jul 25 '17 at 12:44
  • One point to note: if your user has group memberships managed by multiple servers in different time zones - I work for clients where this is true for employees with profiles in two or more offices - you'll find that iterating through all the groups will take several seconds. In these cases objGroup.Ismember is the way to go. I would urge you not to use local cacheing of the user's groups list, however tempting it may be when you need to check repeatedly, as this is very poor security practice. – Nigel Heffernan Aug 01 '17 at 16:50
  • 1
    And still useful in 2019 :D Thanks @NigelHeffernan – Gadziu May 17 '19 at 11:02
  • How do I get it to find if the user is included in nested groups? – luis Oct 19 '21 at 20:07
  • @Luis - Nested groups are harder: you would need to enumerate and recursively search the nested groups structure. – Nigel Heffernan Nov 02 '21 at 11:58
14

Allain found this online

Function IsMember(strDomain As String, strGroup _
  As String, strMember As String) As Boolean
  Dim grp As Object
  Dim strPath As String

  strPath = "WinNT://" & strDomain & "/"
  Set grp = GetObject(strPath & strGroup & ",group")
  IsMember = grp.IsMember(strPath & strMember)
End Function

You can get the Windows account info by way of the USERDOMAIN and USERNAME environment vars:

Function GetCurrentUser() As String
    GetCurrentUser = Environ("USERNAME")
End Function

Function GetCurrentDomain() As String
    GetCurrentDomain = Environ("USERDOMAIN")
End Function

Putting it all together:

If IsMember(GetCurrentDomain, "AD Group", GetCurrentUser) Then
   DoStuff()
End If
Patrick Cuff
  • 28,540
  • 12
  • 67
  • 94
  • True. It's mostly for displaying different screens to different users. Not so much security as usability. – Allain Lalonde Jan 06 '09 at 15:54
  • 2
    This answer isn't really AD-related -- it's just plain old NTFS groups. AD has things like Organizational Units that are not a part of NTFS and accessible only via LDAP queries. – David-W-Fenton Jan 06 '09 at 23:03
  • 2
    I would advise against using the Environment variables for user name and user domain: they are local settings and they can be changed. Querying the Windows Network asks Active Directory and the Domain Server who you are and where you are, and that's a bit more reliable. – Nigel Heffernan Sep 11 '15 at 13:42
  • 4
    To elaborate on Nigels comment, GetCurrentUser = CreateObject("WScript.Network").Username GetCurrentDomain = CreateObject("WScript.Network").UserDomain – Sidupac Mar 13 '19 at 00:44
2

Found this online

Function IsMember(strDomain As String, strGroup _
  As String, strMember As String) As Boolean
  Dim grp As Object
  Dim strPath As String

  strPath = "WinNT://" & strDomain & "/"
  Set grp = GetObject(strPath & strGroup & ",group")
  IsMember = grp.IsMember(strPath & strMember)
End Function

Now, I only need the account name of the current user. Too bad Application.CurrentUser doesn't give me their Domain Account name.

Allain Lalonde
  • 91,574
  • 70
  • 187
  • 238
  • Just a word of warning. This code will return the incorrect results for the users primary group (Usually "Domain Users") because that is stored differently in AD. – JohnFx Jan 06 '09 at 15:36
  • No problem. I had been fighting with this problem for a few weeks at the end of December and learned most of this the hard way. I strongly recomend a book for this type of issue: "The .NET Developer's Guide to Directory Services Programming" – JohnFx Jan 06 '09 at 20:53