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); ...
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
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!
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
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
I tried this is my application and it seems to work locally, but remote users get the generic asp error page. Any ideas?
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!
Hey thanks this is just what I needed !
Brilliant, but how do I implement this on a ‘send button’ ?
This helped a great deal thank..
With the example above how do I retrieve a users exchange mailbox onfo?
Many thanks
Ken
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.
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
Hey Pierre,
Have a look at comment #6: http://www.shulerent.com/2010/02/03/getting-active-directory-info-for-the-current-user-in-vb-net-in-2-lines/#comment-168
When using asp.net it is better to use the Page User object to get the identity of the person accessing the page (and then not use impersonation)
I will update the post accordingly.
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. :\
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
Oh wow it works. Din’t mean to make you put your VB Pants on LOL. Thanks man really appreciated :).
Cheers,
Pierre
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.
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
the dev site is sitting on windows server 2003,
and the live site is sitting on windows server 2008.
t-h-a-n-k-s!!
i did what you wrote in response #1.
and it works!!
thank you!!!!
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?
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.
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. 🙂
GREAT!!! I was looking for this all over the web. Thank you so much!!!
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!
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.
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.”
Superb, Works like charm, such a sweet code 🙂
Please how do get the list of group a member belong to
When using VS 2017 and VB.net, this line, gives this error:
Dim currentADUser As System.DirectoryServices.AccountManagement.UserPrincipal
‘ Type System.DirectoryServices.AccountManagement.UserPrincipal is not defined