Get user photo from Active directory not working at server - asp.net

I am developing an intranent website that take the user name direct from windows authentication then get more data from active directory such as user image and user email and so on at the folowing function
public Boolean userAuth()
{
String myUser = Environment.UserName;
if (myUser == null)
{
return false;
}
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://mydomain.com";
DirectorySearcher search = new DirectorySearcher();
search.Filter = "(SAMAccountName=" + myUser + ")";
search.PropertiesToLoad.Add("cn");
search.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" +myUser + "))";
search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("thumbnailPhoto");
search.PropertiesToLoad.Add("Company");
SearchResult user;
user = search.FindOne();
String userName;
userName = Convert.ToString(user.Properties["sAMAccountName"][0]);
byte[] bb = (byte[])user.Properties["thumbnailPhoto"][0];
string imgString = Convert.ToBase64String(bb);
Session["UserPhoto"] = String.Format("<img width='40' src=\"data:image/Bmp;base64,{0}\">", imgString);
result = search.FindOne();
if (null == result)
{
return false;
}
return true;
}
My pc is connected to the domain when i run the site in my local pc it works fine but when i put it in company application server
the Environment.UserName will not return the username so i use System.Web.HttpContext.Current.User.Identity.Name.Replace("mydomain","") but it will return that user null
I want to get user photo from AD to use it in the intranet site.

I found the answer at iis application pool advance settings set process module identity to a user who is already in the domain

Related

WEB API + Cache all users from AD on application_start

I have a WEB API which perform 2 functions
return current login user details
Also enable asyn search for any user.
In order to save performance hit on first call, i want to get all users and save them in cache on application_start. I have enabled IIS warm up, so everything should be in cache before first request
DirectoryEntry entry = new DirectoryEntry(LdapPath, activeDirectoryUserid, activeDirectoryPassword);
DirectorySearcher search = new DirectorySearcher(entry)
{
Filter = "(&(&(objectClass = user)(objectClass = person)))"
};
search.PropertiesToLoad.Add(AppConstants.AD.Name);
search.PropertiesToLoad.Add(AppConstants.AD.SamAccountName);
search.PropertiesToLoad.Add(AppConstants.AD.ThumbnailPhoto);
search.PropertiesToLoad.Add(AppConstants.AD.FirstName);
search.PropertiesToLoad.Add(AppConstants.AD.Manager);
search.PropertiesToLoad.Add(AppConstants.AD.DistinguishedName);
search.CacheResults = false;
SearchResultCollection resultset = search.FindAll();
Try using System.DirectoryServices.AccountManagement namespace.
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "yourdomain.com"))
{
UserPrincipal allUsers = new UserPrincipal(ctx);
PrincipalSearcher ps = new PrincipalSearcher(allUsers);
foreach (UserPrincipal user in ps.FindAll())
{
//USER will contain the necessary information you need
string name = user.DisplayName;
}
}

Adding Google Calendar entry without using setUserCredentials

I am following the example provided by Google for Market place app at
http://code.google.com/googleapps/marketplace/tutorial_dotnet.html
I got the google authentication working as in the example ,
My next task is to add a entry to Google calendar. I found following code for that, and it is also working fine
CalendarService service = new CalendarService(APPLICATION_NAME);
service.setUserCredentials(vUserName, vPassword);
Google.GData.Calendar.EventEntry entry = new Google.GData.Calendar.EventEntry();
// Set the title and content of the entry.
entry.Title.Text = title;
entry.Content.Content = contents;
// Set a location for the event.
Where eventLocation = new Where();
eventLocation.ValueString = location;
entry.Locations.Add(eventLocation);
When eventTime = new When(startTime, endTime);
entry.Times.Add(eventTime);
Uri postUri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
// Send the request and receive the response:
AtomEntry insertedEntry = service.Insert(postUri, entry);
The problem i have is the following line, If i give my username and password it will work
service.setUserCredentials(vUserName, vPassword);
i have authenticated the user as in google example. So I don’t know the username and password of other users login to my site using their gmail.
How do i add a calender entry with the information i have?
I have seen several examples with RequestFactory authenticating the user. but couldn't find complete example that I can use
you will need to create a .pfx cert file and upload it to google and place it on your server.
create your AuthSubRequest URL
<asp:HyperLink ID="GotoAuthSubLink" runat="server"/>
GotoAuthSubLink.Text = "Login to your Google Account";
GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl("(return url)http://www.example.com/RetrieveToken", "https://www.google.com/calendar/feeds/", false, true);
after the person clicks on your auth link they are returned to your return url. get your session token as follows
String sessionToken = ""; //Save this for making your calls.
String certFile = "D:\\websites\\yourwebsite.com\\google.pfx";
String result = GetAuthSubSessionToken(Request["token"]);
protected AsymmetricAlgorithm GetRsaKey()
{
X509Certificate2 cert = new X509Certificate2(certFile, "");
RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider;
return privateKey;
}
public string GetAuthSubSessionToken(string singleUseToken)
{
string gatStr = "";
try
{
AsymmetricAlgorithm rsaKey = GetRsaKey();
try
{
sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, rsaKey).ToString();
gatStr = "Session Token = " + SessionToken;
}
catch (Exception e)
{
gatStr = "Error: I appears that the Google authentication server is experiencing an error. Try the authorizaton link again in a few minutes. <a href=\""
+ rtnUrl + "\" title=\"" + e.Message + "\">continue</a>";
}
}
catch (Exception E)
{
gatStr = "Error: rsa " + E.Message + E.StackTrace;
}
return gatStr;
}
save the session token and use CreateCalendarService in subsequent calls to create your calendar service.
public CalendarService CreateCalendarService()
{
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "YourName-calendarApp-1");
authFactory.Token = sessionToken;
authFactory.PrivateKey = GetRsaKey();
CalendarService cs = new CalendarService(authFactory.ApplicationName);
cs.RequestFactory = authFactory;
return cs;
}

Active directory authentication

I'm using the code below to authenticate a user in Active Directory, but the password is sending in clear text. How can I hash my password and then send it to Active Directory?
DirectoryEntry entry = new DirectoryEntry(path, username, pwd);
try
{
//Bind to the native AdsObject to force authentication.
object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
//Update the new path to the user in the directory.
_path = result.Path;
_filterAttribute = (string)result.Properties["cn"][0];
}
catch (Exception ex)
{
throw new Exception("Error authenticating user. " + ex.Message);
}
return true;
If you are using .NET 3.5, then I'd strongly recommend switching to using the System.DirectoryServices.AccountManagement namespace (read all about it: Managing Directory Security Principals in the .NET Framework 3.5).
Lots of things are a lot easier in S.DS.AM - like authenticating users:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
ctx.ValidateCredentials("test", "test", ContextOptions.SecureSocketLayer);
The only way to do this securely is by specifying the ContextOptions.SecureSocketLayer option to enforce using an SSL protected connection.
If you cannot move to .NET 3.5 and S.DS.AM, you need to check out the AuthenticationTypes that you can define in the fourth overloaded constructor of DirectoryEntry:
DirectoryEntry entry =
new DirectoryEntry(path, username, pwd,
AuthenticationTypes.SecureSocketsLayer);
There's no other way to do this, I'm afraid - I don't think there's any way for you on the client-side to hash a password the same way Windwos Server / Active Directory do it, and pass in that hashed value...

How to get user details in asp.net Windows Authentication

I am using windows Authentication and accessing user name as.
IIdentity winId = HttpContext.Current.User.Identity;
string name = winId.Name;
but i want to get other details like User full name and EmailID.
Since you're on a windows network, then you need to query the Active directory to search for user and then get it's properties such as the email
Here is an example function DisplayUser that given an IIdentity on a windows authenticated network, finds the user's email:
public static void Main() {
DisplayUser(WindowsIdentity.GetCurrent());
Console.ReadKey();
}
public static void DisplayUser(IIdentity id) {
WindowsIdentity winId = id as WindowsIdentity;
if (id == null) {
Console.WriteLine("Identity is not a windows identity");
return;
}
string userInQuestion = winId.Name.Split('\\')[1];
string myDomain = winId.Name.Split('\\')[0]; // this is the domain that the user is in
// the account that this program runs in should be authenticated in there
DirectoryEntry entry = new DirectoryEntry("LDAP://" + myDomain);
DirectorySearcher adSearcher = new DirectorySearcher(entry);
adSearcher.SearchScope = SearchScope.Subtree;
adSearcher.Filter = "(&(objectClass=user)(samaccountname=" + userInQuestion + "))";
SearchResult userObject = adSearcher.FindOne();
if (userObject != null) {
string[] props = new string[] { "title", "mail" };
foreach (string prop in props) {
Console.WriteLine("{0} : {1}", prop, userObject.Properties[prop][0]);
}
}
}
gives this:
Edit: If you get 'bad user/password errors'
The account that the code runs under must have access the users domain. If you run code in asp.net then the web application must be run under an application pool with credentials with domain access. See here for more information
You can define a MyCustomIdentity by overriding from IIdentity and add your own properties etc.
Cast it to the specific Identity, for example WindowsIdentity

Active Directory Account locking out on first try

I have a website which requires users to enter their corporate network username and password. It then looks for that account in Active Directory and gets a list of any email addresses associated with that account.
The problem I am having is that ONE incorrect password is locking out an account. Our domain policy is that an account will lock out after three incorrect entries, so I am assuming that I am doing something wrong in my code. I am not very knowledgeable about Active Directory or .NET DirectoryServices in general, which may be apparent from my code. Here it is:
public ArrayList AuthenticateActiveDirectory(string Domain, string UserName, string Password)
{
// An error occurs if the username/password combo does not exist.
// That is how we know it is not a valid entry.
try
{
DirectoryEntry entry = new DirectoryEntry("LDAP://" + Domain, UserName, Password);
object nativeObject = entry.NativeObject;
ArrayList emails = new ArrayList();
DirectorySearcher ds = new DirectorySearcher(entry);
ds.Filter = "samaccountname=" + UserName;
ds.PropertiesToLoad.Add("mail");
SearchResult sr = ds.FindOne();
if (sr.Properties["mail"] != null)
{
for (int email = 0; email < sr.Properties["mail"].Count; email++)
{
emails.Add(sr.Properties["mail"][email]);
}
}
return emails;
}
catch (DirectoryServicesCOMException) { throw; }
catch (Exception) { throw; }
}
I did some searching and found some code (thanks to Ayende Rahien for the solution) to use that just authenticates and doesn't search for emails or anything else. I am using this prior to the other function, and it seems to be working fine. I am guessing that my other code is hitting AD more than once - at least 3 times - which is resulting in the lockout. Here is the code I am using now to just authenticate:
private bool Authenticate(string domain, string user, string password)
{
try
{
using (DirectoryEntry de = new DirectoryEntry("LDAP://" + domain,
user, password))
{
return de.NativeObject != null;
}
}
catch
{
return false;
}
}

Resources