Getting Active Directory info for the current user in VB.net in 2 lines

Don’t listen to the internet – getting account information from active directory for the current user is simple and easy in Visual Basic .NET – particularly if you are using Framework 3.5 or higher

Note: if you are using ASP.NET, there is a different way to do it – see the update below

You don’t need to do any stinking LDAP queries, or lookups, or credential passings – it’s all made simple using System.DirectoryServices.AccountManagement. Observe.

First, go to the references tab in project properties, click add reference, and find “System.DirectoryServices.AccountManagement” – no need to add “System.DirectoryServices”.

Now, in your application, add the following lines:

Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current

(It’s even simpler if you import the namespace)

Poof. That’s it! You are done.

currentADUser is a strongly typed object containing attributes for most of the active directory properties you need = such as display name, email address, primary group membership, exchange mailbox info, etc, etc.

Say you want to get the current user’s email address. You could do it like so (after the previous code):

Dim userEmail as string = currentADUser.EmailAddress

That’s it. 1 additional line.

How about a concrete example – here is the problem I wanted to solve. Send an email message from the current user for error reporting – Make sure to change the To: email address, and the smtp server name, and this should be a drop-in solution:

  Private Sub report_error(ByVal errorMessage As String)
    Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
    currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current
    Dim mailClient As New System.Net.Mail.SmtpClient("smtpserver.company.local")
    mailClient.Send(currentADUser.DisplayName & " <" & currentADUser.EmailAddress & ">", _
                    "notifications@company.com", _
                    "ERROR REPORT: Application error for " & currentADUser.DisplayName, _
                    errorMessage)
  End Sub

Hope this helps!

Update – ASP.NET
The “better” way to get this info in an ASP page is to take advantage of the “User” object available to the ASP.NET Page class. User.Ientity can be cast to a System.Security.Principal.WindowsIdentity, giving you access to the User attribute (yes, User.Identity.User essentially) which is the domain SID. You use this SID to lookup the user in AD.

You check the User.Identity.IsAuthenticated to make sure that IIS has taken care of verifying the identity of the user.

Imports System.Security.Principal
Imports System.DirectoryServices.AccountManagement

Public Class WebForm1
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not User.Identity.IsAuthenticated Then
            Throw New InvalidOperationException("Specified user is not authenticated")
        End If

        If Not User.Identity.Name.StartsWith("DOMAIN\") Then
            Throw New InvalidOperationException("Specified user is not member of Domain")
        End If

        Dim userSid As String = CType(User.Identity, WindowsIdentity).User.Value

        Dim adContext As PrincipalContext = New PrincipalContext(ContextType.Domain, "Domain.local")

        Dim adUser As UserPrincipal = UserPrincipal.FindByIdentity(adContext, IdentityType.Sid, userSid)

        emaillbl.Text = adUser.EmailAddress



    End Sub

End Class

This example is c# (I switched…) – hopefully you can translate?

using System.Security.Principal;
using System.DirectoryServices.AccountManagement;
 ...
 
if (!User.Identity.IsAuthenticated) throw new InvalidOperationException("Specified user is not authenticated");
 if (!User.Identity.Name.StartsWith("Domain\\")) throw new InvalidOperationException("Specified user is not member of Domain");
 
string userSid = ((WindowsIdentity)User.Identity).User.Value;
 PrincipalContext adContext = new PrincipalContext(ContextType.Domain, "Domain.local");
 UserPrincipal adUser = UserPrincipal.FindByIdentity(adContext, IdentityType.Sid, userSid);
 ...
 

30 thoughts on “Getting Active Directory info for the current user in VB.net in 2 lines

  1. Thank you so much! I had been looking around for some time and here it was. But it seems to be some general properties in AD missing, like streetaddress or “l” for locality (town). Is there an easy way to get those properties too?
    Kind regards, Sambuccus

  2. This is great. I’ve been googling this for the past 3 hours trying to find something usefull. Your example hit the nail square on the head. Thanks!

  3. Best answer I have found. Love the simplicity yet gives everything, and more, than I was looking for.
    Thanks!

    p.s. Using this code with Microsoft Visual Basic 2010 Express

  4. this is really very good example i really appreciate it.
    the only thing if you can help me to get the office details and manager of currect user id. Thanks

    • There’s a couple things that could be going on here:
      1. Are you sure that the clients are pushing credentials? By default this only happens with sites in the Local Intranet Zone – you might need to add your site the the local intranet zone, or access it without using the FQDN.
      2. Have you enabled impersonation in the ASP.NET Web.config?
      I would actually recommend that you do NOT enable impersonation – there is another way to get the UserPrincipal in ASP.NET:

      The “better” way is to take advantage of the “User” object available to the ASP.NET Page class. User.Ientity can be cast to a System.Security.Principal.WindowsIdentity, giving you access to the User attribute (yes, User.Identity.User essentially) which is the domain SID. You use this SID to lookup the user in AD.

      You check the User.Identity.IsAuthenticated to make sure that IIS has taken care of verifying the identity of the user.

      This is c# – hopefully you can translate?

      using System.Security.Principal;
      using System.DirectoryServices.AccountManagement;
      ...

      if (!User.Identity.IsAuthenticated) throw new InvalidOperationException("Specified user is not authenticated");
      if (!User.Identity.Name.StartsWith("Domain\\")) throw new InvalidOperationException("Specified user is not member of Domain");

      string userSid = ((WindowsIdentity)User.Identity).User.Value;
      PrincipalContext adContext = new PrincipalContext(ContextType.Domain, "Domain.local");
      UserPrincipal adUser = UserPrincipal.FindByIdentity(adContext, IdentityType.Sid, userSid);
      ...

      It may need some massaging, but it works for me. (Replace the strrings containing “Domain” with your own domain name.
      Let me know if you need any additional help!

  5. This helped a great deal thank..

    With the example above how do I retrieve a users exchange mailbox onfo?

    Many thanks

    Ken

  6. Hey Ken,
    My apologies for the delay.

    Exchange info isn’t as easy to get as I first thought. You will need to include a reference to System.DirectoryServices, then after getting the UserPrincipal object, call GetUnderlyingObject() and cast the result to System.DirectoryServices.DirectoryEntry. This has a Properties collection containing all the Active Directory properties for the user, including the exchange properties.

    If you need an example, let me know.

  7. Hello,

    I basically have 2 label on my page one for the name and one for the e-mail, its an e-mail form. I wanted my label to display currently logged in user informations from active directory. It does work locally in debug mode but as soon as I try on IIS in my web browser I get System.InvalidCastException: Unable to cast object of type ‘System.DirectoryServices.AccountManagement.GroupPrincipal’ to type ‘System.DirectoryServices.AccountManagement.UserPrincipal’.

    If I put imprtsonate to True I get System.Runtime.InteropServices.COMException: An operations error occurred.
    Line 24: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Line 25: Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
    Line 26: currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current
    Line 27:
    Line 28: Dim userEmail As String = currentADUser.EmailAddress.ToString

    Here is my code:

    Imports System
    Imports System.Data
    Imports System.Configuration
    Imports System.Web
    Imports System.Web.Security
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    Imports System.Web.UI.HtmlControls
    Imports System.Net.Mail
    Imports System.DirectoryServices
    Imports System.DirectoryServices.ActiveDirectory
    Imports System.DirectoryServices.AccountManagement
    Imports System.DirectoryServices.AccountManagement.GroupPrincipal
    Imports System.DirectoryServices.AccountManagement.UserPrincipal
    Imports System.Security
    Imports System.Security.Principal.WindowsIdentity
    Imports System.DirectoryServices.DirectoryEntry
    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.COMException

    Partial Class contact2
    Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
    currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current

    Dim userEmail As String = currentADUser.EmailAddress.ToString
    emaillbl.Text = userEmail

    Dim userFullName As String = currentADUser.Name
    namelbl.Text = userFullName
    End Sub
    Protected Sub btnSend_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSend.Click
    Using message As New MailMessage()
    message.From = New MailAddress(emaillbl.Text.ToString)
    message.[To].Add(New MailAddress(“email”))
    ‘message.CC.Add(New MailAddress(“email”))
    ‘message.CC.Add(New MailAddress(“email”))
    message.Subject = “Knowledge Base New Documentations Form Submission test page”
    message.Body = bodytxtbox.Text.ToString()

    ‘ If FileUpload1.HasFile Then
    ‘message.Attachments.Add(New Attachment(FileUpload1.PostedFile.InputStream, FileUpload1.FileName))
    ‘ End If

    Dim client As New SmtpClient()
    client.Host = “mamailserver”
    client.Send(message)
    System.Web.Security.FormsAuthentication.SignOut()
    Response.Redirect(“http://intradev…”)
    End Using
    End Sub
    End Class

    Mail form works fine just getting that message when I add the codes

    Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
    currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current

    Dim userEmail As String = currentADUser.EmailAddress.ToString
    emaillbl.Text = userEmail

    Dim userFullName As String = currentADUser.Name
    namelbl.Text = userFullName

    Any help would be greatly appreciated.

    Cheers,

    Pierre Breau

  8. Thanks for the quick answer, I am pretty new at coding and only know about vb.net. I can’t really translate the coding you put there. I did try tho ….

    If I could get an example to go from and then I could really understand it.

    lets say I have 1 label call emaillbl and I want it to show the email of the user that is already logged in using windows authentication,

    I can dim usermail as string = system.security.principal.windowsidentity.getcurrent.”there is no option for e-mail”

    Maybe I am missing a part. :\

  9. Alright Pierre, you made me put my Visual Basic pants back on… but here is my example converted to VB just for you 🙂

    You will need to replace DOMAIN and Domain.local with the appropriate information from your domain


    Imports System.Security.Principal
    Imports System.DirectoryServices.AccountManagement

    Public Class WebForm1
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not User.Identity.IsAuthenticated Then
    Throw New InvalidOperationException("Specified user is not authenticated")
    End If

    If Not User.Identity.Name.StartsWith("DOMAIN\") Then
    Throw New InvalidOperationException("Specified user is not member of Domain")
    End If

    Dim userSid As String = CType(User.Identity, WindowsIdentity).User.Value

    Dim adContext As PrincipalContext = New PrincipalContext(ContextType.Domain, "Domain.local")

    Dim adUser As UserPrincipal = UserPrincipal.FindByIdentity(adContext, IdentityType.Sid, userSid)

    emaillbl.Text = adUser.EmailAddress

    End Sub

    End Class

  10. Oh wow it works. Din’t mean to make you put your VB Pants on LOL. Thanks man really appreciated :).

    Cheers,

    Pierre

  11. i am trying to get the username from the active directory,
    i do what you wrote:

    Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal

    currentADUser = System.DirectoryServices.AccountManagement.UserPrincipal.Current

    UserName = currentADUser.SamAccountName.ToString
    and i get this error:
    Unable to cast object of type ‘System.DirectoryServices.AccountManagement.GroupPrincipal’ to type ‘System.DirectoryServices.AccountManagement.UserPrincipal’.

    • Are you using this in ASP? If all you need is the username, there are easier / more efficient ways to get it (eg: Page.User.Identity.Name – no need for AD shennanigans)

      I’m not sure why the UserPrincipal.Current would be a GroupPrincipal, but I’ve seen mention of this when trying to use this under ASP.NET. It’s just a better idea to use Page.User.

  12. thanks!
    I am using asp.net and vb.net 4.0.
    the probleme is that on the dev it’s work fine but on the live site the user name comes empty!

    • Did you try using Page.User, or are you referring to the UserPrincipal.Current issue?

      Assuming you are having issues with Page.User, I would check things in this order:
      1. Is Windows Authentication enabled for the IIS site / application? It should be, and anonymous should be disabled.
      2. Is the Windows Authentication using Kernel-mode authentication? Probably should be, but you could try it both ways.
      3. Is the Application Pool for the site running as NetworkService?
      4. Is the hostname for the site added to the Local Intranet Zone on the client PC? If not, the client will not push credentials
      5. Check the SPNs on the server’s machine account (may need to do some googling for this one – this probably isn’t the issue)

      If you are using Page.User you do not need to enable impersonation.

      IIS on a dev machine tends to be configured to “just work” and I think it runs with the credentials of the debugging user.

      Take a look at those things, and let me know if you are still having trouble

  13. I have another problem!
    The workers on the company have to enter a userName and a password when they load the page.
    I don’t want them to do that.
    What should I do?

  14. Internet Explorer only pushes credentials to websites in the Local Intranet zone by default. If you are accessing an intranet server without a domain name (eg “http:\\intranet”) IE will usually do it automatically. If, however, you usea fully qualified name (eg “http:\\intranet.mydomain.org”) it will not work without some changes on the client.

    You need to add the server to the local intranet zone
    To do this manually, use this:

    (Internet Options -> Security Tab -> Click Local Intranet -> Click Sites -> Click Advanced -> Enter URL, click add)

    This setting can be pushed out via Group Policy, but there are numerous ways to do it and the best option depends on your company policy.

  15. Wow SO simple! Many people around the net have pages and pages of code just for getting an e-mail address, you did it in THREE lines and it works great! Thanks. 🙂

  16. I know this an old post, but I’ve been searching all over for an answer to this.

    In your description you say that you can obtain the “primary group” from currentADUser. Can you explain how you would go about this?

    Thanks.

    • Hey LedHed,

      My apologies, there is no easy way to get the Primary Group for a user with the UserPrincipal object (I wasn’t even aware of the concept of a primary group…)

      I believe what I meant by “primary” is that GetGroups() only returns those groups for which the user is directly listed as a member. Getting groups in the inheritance tree is trickier and more expensive – potentially much more expensive.

      If you just need to know if a user is a member of a group (either explicitly or through inheritance) you can use currentADUser.IsMemberOf(GroupPrincipal)

      (IsMemberOf does take primary group into account, btw)

      Hope this helps!

  17. Unfortunately, your 2-line example doesn’t work for me. I’m using Visual Studio 2012 Pro. After keying the example precisely, I get a “COMException was unhandled. The specified directory service attribute or value does not exist”.

    • WHat property did you attempt to access? The two lines give you access to an object with attributes from the user. If you attempt to access an attribute that doesn’t exist in AD, or that you do not have permissions to see you may have issues.

  18. I attempted to access the email address property. I keyed in the 2 lines from your example, then did a dim userEmail as String = currentADUser.EmailAddress. When I clicked the button on a windows form to fire the code, I got an “LdapException was unhandled. The connection cannot be established.”

Leave a Reply