comparing active directory and db user currently logged in? - c#

How can i check that the current user logged onto the machine is an active directory user and also part of the application?
I am building an extension to a legacy application which authenticates based on AD. The database has ad_user_name and i want to compare the ad_user_name with the username actually held in active directory.
IF the usernames are the same then my edit view is accessible. If the users are different then something went wrong and they cant see anything.
EDIT: there is a possibility that the server only runs .NET 2.0

If your using .net 3.5 use this code instead.
To authenticate a user:
PrincipalContext adContext = new PrincipalContext(ContextType.Domain);
using (adContext)
{
return adContext.ValidateCredentials(UserName, Password);
}
If you need to find the user to R/W attributes to the object do this:
PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal foundUser = UserPrincipal.FindByIdentity(context, "jdoe");
This is using the System.DirectoryServices.AccountManagement namespace so you'll need to add it to your using statements.
If you need to convert a UserPrincipal object to a DirectoryEntry object to work with legacy code you can do this:
DirectoryEntry userDE = (DirectoryEntry)foundUser.GetUnderlyingObject();

Related

how to change the password on an AD user account that is both hidden and expired

If a domain AD user account is hidden * and expired, is there a way to change the password (not reset) in .net / c# ?
The code I have currently is using System.DirectoryServices.AccountManagement and is essentially something like
using (var context = PrincipalContext(ContextType.Domain, server, container)
{
var directoryUser = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
directoryUser.ChangePassword(oldPassword, newPassword);
}
This works OK for users that the application service account can find, but some "hidden" users are in OUs that the application service account does not have read permissions to - and hence this fails with a null user.
I thought I would change it so that the PrincipalContext is established with the username and password of the user themselves (since they will have permissions to find themselves) - but often the account is expired by the time they come to change their password and so the FindByIdentity call fails as invalid credentials since the account is expired..
It's kind of a catch-22 where I can't find the user unless I search as the user, but I can't search as the user since they are expired, and I can only unexpire them by getting them to change their password.
If they have access to a workstation they can change their password using the Windows login controls but how to achieve this same level of functionality in c#?
EDIT1: I'm hoping for a solution that does not involve a service account with read-access to the hidden OUs - that would be difficult to achieve for various organization reasons.

Why might UserPrincipal.GetAuthorizationGroups() fail for one principal but not another?

I am running the following code in an ASP.Net MVC website:
using (var ctx = new PrincipalContext(ContextType.Domain, DOMAIN))
using (var userPrincipal = UserPrincipal.FindByIdentity(ctx, principal.Identity.Name))
using (var groups = userPrincipal.GetAuthorizationGroups())
The code is used a custom RoleProvider and the variable "principal" is HttpContext.Current.User. DOMAIN is my local domain.
This code works fine when I log in to the site, but throws an exception on the last line if I log in as either of a couple of test users.
While trying to retrieve the authorization groups, an error (5) occurred.
The test users have fewer permissions on the domain but are users in active directory. I tried creating the PrincipalContext with an alternative constructor supplying my username and password but it didn't make any difference to the behaviour.
This happens both on my dev machine and also on a separate staging server so I don't think it has anything to do with local permissions. I also don't see how it can be related to the users' permissions as I would expect the active directory request to be made as the IIS App Pool user (impersonation is turned off) or perhaps the user specified in the PrincipalContext constructor.
Any suggestions as to what is going on gratefully received.
It's not enough that they are users in Active Directory. The IIS App Pool user needs to be a member of the Windows Authorization Access Group to execute GetAuthorizationGroups.
Answered here: While trying to retrieve the authorization groups, an error (5) occurred

How to work with ldap in .net C#

I have an application where i can send emails. Now am asked to use ldap in to and from fields of the email.Am very new to this concept. I have been given a ldap link. No idea how to proceed with that. Any aricle or hits will be greatly helpful.
If you're on .NET 3.5 and up and using Microsoft's Active Directory as your LDAP store, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
if(user != null)
{
// do something here, e.g. get the user's e-mail address(es)
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Most of the functionality I've used is in System.DirectoryServices.
Have a look at this link for more info: http://lozanotek.com/blog/articles/149.aspx
The LDAP link is basically a reference to a directory server, such as Active Directory, which will give you email addresses if you have their user name, for example. I'd start off by reading the article above, then experimenting with a small test program

Creating Active Directory of usernames for LDAP access

I am a newbie to LDAP and Active Directories.
I need to build a active directory of users who are eligible to access a particular conputer. When the user enters the username and password in a web interface(created in C#) it is sent to the active directory via LDAP query to the active directory. AD will return users email address if the login is successful.
Is it possible to setup a Active Directory to achieve the above scenario locally? I am using Windows 7 Ultimate. I have installed ADAM for LDAP access.
Regards,
John.
Since you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// validate username/password combo
if (ctx.ValidateCredentials(username, password))
{
// if valid - find user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, username);
if (user != null)
{
return user.EmailAddress;
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
For ADAM (or AD LDS as it's called today), you could use
PrincipalContext ctx = new PrincipalContext(ContextType.ApplicationDirectory);
to establish a context with your ADAM directory - not sure, but you probably have to supply some form of additional information to know what Application directory to use (I've never played with this on ADAM). And also: I'm not sure if you can validate credentials against an ADAM store .... you'll just have to see and try!

Using current user's SharePoint credentials to gain Active Directory access

I'm developing a SharePoint 2010 Web Part (in C#) which needs to pull user data from Active Directory but I'm having trouble using the current SharePoint user's credentials to authenticate with AD. I am using the DirectoryEntry class to get data from AD and it works fine when I hard-code some credentials but I know that's bad practice so I want to avoid it. I've tried a couple of different things like:
new DirectoryEntry("LDAP://" + dc, null, null, AuthenticationTypes.ServerBind | AuthenticationTypes.FastBind);
and
new DirectoryEntry("LDAP://" + dc, null, null, AuthenticationTypes.Secure);
but they all just throw exceptions. I don't really know what these do but it's what I've managed to find online.
Any help that can point me in the right direction would be greatly appreciated.
You're probably running into the infamous 'double hop' problem. The Sharepoint Server can't automatically authenticate as you to another server, even on the same domain. Google 'double hop' for more info on the problem.
There are several options for doing what you want:
You can use the Secure Store Service in Sharepoint 2010 to store the requisite Username / Password for connecting to AD, either a single username/password shared by all Sharepoint Users (similar to #2 below) or a username/password for each Sharepoint user (similar to #3 below).
You could set up an AD account that has read-only permissions to AD, then create some Web Part properties to store the username and password of the user. Set up the properties so that they are shared by all users and set by the administrator. Use the stored username/password when connecting to AD. Set the password property so that it is write-only from the UI side.
If it's important for each user to see a different set of AD data based on the user's permissions in AD, then you could do something similar to the above, but don't make the username/password properties shared.
Set up Kerberos for your Sharepoint environment, thus allowing the sharepoint web server to authenticate as you to AD without having to store your credentials
Setup AD to allow for anonymous read access (probably not the best, due to security considerations)
I'm using this code to connect to AD with the current user:
using (DirectoryEntry entry = new DirectoryEntry())
{
using (DirectorySearcher searcher = new DirectorySearcher(entry))
{
searcher.Filter = "yourSearchQuery";
searcher.PropertiesToLoad.Add("yourProperty1");
searcher.PropertiesToLoad.Add("yourProperty2");
using (SearchResultCollection results = searcher.FindAll())
{
foreach (SearchResult result in results)
{
using (DirectoryEntry resultEntry = result.GetDirectoryEntry())
{
PropertyValueCollection valuesForProperty1 = resultEntry.Properties["yourProperty1"];
PropertyValueCollection valuesForProperty2 = resultEntry.Properties["yourProperty2"];
// ...
}
}
}
}
}

Categories