Active Directory Authentication - asp.net

I am have made one web application in asp.net.In my project Authentication was done by matching the username and password in database.But now client ask me for the auto login in application with the help Of Active Directory authentication. Client ask suggest me to use the Email Id of user in AD for the authentication.
I tried to fetch the records in the AD, I could fetch the Fullname of user but I couldn't get the Email id,
I tried the code:
System.Security.Principal.WindowsIdentity wi = System.Security.Principal.WindowsIdentity.GetCurrent();
string[] a = Context.User.Identity.Name.Split('\\');
System.DirectoryServices.DirectoryEntry ADEntry = new System.DirectoryServices.DirectoryEntry("WinNT://" + a[0] + "/" + a[1]);
string Name = ADEntry.Properties["FullName"].Value.ToString();
Further more I Use DirectorySearcher but it genterates Error that Coulnot search the record in the client server..

I had the exact same situation while making a portal for a company.
If they dont want you to get into their AD then what you can do is to request for the NTLogins of the people who will be given access to the portal. make a simple table which have their NTLogin and simply authenticate using the system from which the portal is being accessed.
Check out the sample code i used.
// Checking if the user opening this page is listed in the allowed user list against their NT login.
String sUser = Request.ServerVariables["LOGON_USER"].ToLower();
sUser = sUser.Replace("wt\\", "");
//Authentication using a custom auth method.
DatabaseOperations authenticateUser = new DatabaseOperations();
if (!authenticateUser.authenticate(sUser))
{
//unauthorized users will be redirected to access denied page.
Server.Transfer("AccessDenied.aspx", true);
}
And making sure that you have authentication mode to windows in your web.config file
<authentication mode="Windows"></authentication>
Hope this helps.

For reading AD data, i use this class. It is setup for our AD, but basically you can just pass in all the "fields" you want to find, in the params.
But you need to know what field holds the email address. Sysinternals made a pretty good tool for browsing AD, to figure out what you are looking for, called ADExplorer.
But I don't understand why you need to look in the AD? Can you not assume that the user is already authenticated, if they are on the network, and then rely on the windows identity?
public static Hashtable GetAttributes(string initials, params string[] Attribute)
{
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://ADNAME");
DirectorySearcher ADSearcher = new DirectorySearcher(directoryEntry);
ADSearcher.Filter = "(sAMAccountName=" + initials + ")";
foreach (string para in Attribute)
{
ADSearcher.PropertiesToLoad.Add(para);
}
SearchResult adSearchResult = ADSearcher.FindOne();
Hashtable hshReturns = new Hashtable();
foreach (string para in Attribute)
{
string strReturn = "";
if (adSearchResult.Properties[para].Count == 0)
strReturn = "";
else
strReturn = ((ResultPropertyValueCollection)adSearchResult.Properties[para])[0].ToString();
hshReturns.Add(para, strReturn);
}
return hshReturns;
}

Related

CAS SSO for Asp.Net website, attributes not receiving on serviceValidate request

I have successfully integrated CAS for our different clients. But this time 'samlValidate' response is not consistently supplying the required attribute. Login is failing randomly because of the missing attribute in the ticket validation response. Sometimes when I clear browser history, it's receiving the attribute in the response.
Expected response:
<cas:serviceResponse xmlns:cas='http://www.xxxxx.xxx/tp/cas'>
<cas:authenticationSuccess>
<cas:user>xxxxx</cas:user>
<cas:attributes>
<cas:userNumber>1234567</cas:userNumber>
</cas:attributes>
</cas:authenticationSuccess>
</cas:serviceResponse>
Response receiving randomly:
<cas:serviceResponse xmlns:cas='http://www.xxx.xxx/tp/cas'>
<cas:authenticationSuccess>
<cas:user>xxxxxx</cas:user>
</cas:authenticationSuccess>
</cas:serviceResponse>
Please note: We have created a custom code to integrate CAS with our Asp.Net webforms application.
string userId = string.Empty;
// Look for the "ticket=" after the "?" in the URL
string tkt = HttpContext.Current.Request.QueryString["ticket"];
// Service url is the url of the Researcher Portal
string service ="www.xyz.com";
string CASHOST="https://cas.xyz.ca:8443/cas"
// First time through there is no ticket=, so redirect to CAS login
if (tkt == null || tkt.Length == 0)
{
string redir = CASHOST + "login?" +
"service=" + service;
HttpContext.Current.Response.Redirect(redir);
}
// Second time (back from CAS) there is a ticket= to validate
string validateurl = CASHOST + "serviceValidate?" +
"ticket=" + tkt +
"&service=" + service;
StreamReader Reader = new StreamReader(new WebClient().OpenRead(validateurl));
string resp = Reader.ReadToEnd();
if (isDebuggingMode)
sbDebugString.Append("****Response **** \n " + resp);
// Some boilerplate to set up the parse.
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlTextReader reader = new XmlTextReader(resp, XmlNodeType.Element, context);
string userNumber = null;
// A very dumb use of XML. Just scan for the "userNumber". If it isn't there, it will return an empty string.
while (reader.Read())
{
if (reader.IsStartElement())
{
string tag = reader.LocalName;
if (isDebuggingMode)
sbDebugString.Append("tag : " + tag + "\n");
if (tag == "userNumber")
{
userNumber = reader.ReadString();
if (isDebuggingMode)
sbDebugString.Append("userNumber : " + userNumber + "\n");
}
}
}
Where "userNumber" attribute is not receiving always so that login fails randomly.
Please share your thoughts to resolve this issue.
Thank you in advance.
If your client application is not receiving attributes, you will need to make sure:
The client is using a version of CAS protocol that is able to
release attributes.
The client, predicated on #1, is hitting the appropriate endpoint for service ticket validation (i.e. /p3/serviceValidate).
The CAS server itself is resolving and retrieving attributes correctly.
The CAS server is authorized to release attributes to that particular client application inside its service registry.
Starting with CAS Protocol 3:
Among all features, the most noticeable update between versions 2.0 and 3.0 is the ability to return the authentication/user attributes through the new /p3/serviceValidate endpoint.
You may also find this post useful:
https://apereo.github.io/2017/06/23/cas-protocol-compatibility/

Trying to get Facebook Cookie from codebehind, but is getting (OAuthException)

I am using Facebook C# SDK on my site, and is trying to access the cookie made by Facebook when the user has chosen to use Facebook as login, but I am getting the following error:
(OAuthException) An active access token must be used to query
information about the current user.
Here is the code I am using:
var client = new FacebookClient([App ID], [App Secret]);
dynamic me = client.Get("me");
string firstName = me.first_name;
Response.Write(firstName);
What am i doing wrong?
Thanks in advance
You need to authorize first before trying to access the user. This does the necessary redirects and plumbing to have Facebook set the cookie.
var auth = new CanvasAuthorizer { Permissions = new string[] {"user_about_me"} };
if (auth.Authorize()) {
var client = new FacebookClient([App ID], [App Secret]);
dynamic me = client.Get("me");
string firstName = me.first_name;
Response.Write(firstName);
}

Google Gmail API - Auth

I already have code which works fine, but for security reason I want to make other way of Auth.
In this case, user writes his username and password, but I want to make like "Allow demo.com to access your information's" click button.
How to change this code:
//Provide Login Information
Google.GData.Client.RequestSettings rsLoginInfo = new Google.GData.Client
.RequestSettings("", txtEmail.Text, txtPassword.Text);
rsLoginInfo.AutoPaging = true;
// Fetch contacts and dislay them in ListBox
Google.Contacts.ContactsRequest cRequest = new ContactsRequest(rsLoginInfo);
Google.GData.Client.Feed<Google.Contacts.Contact> feedContacts = cRequest
.GetContacts();
foreach (Google.Contacts.Contact gmailAddresses in feedContacts.Entries) {
Console.WriteLine("\t" + gmailAddresses.Title);
lstContacts.Items.Add(gmailAddresses.Title);
foreach (EMail emailId in gmailAddresses.Emails) {
Console.WriteLine("\t" + emailId.Address);
lstContacts.Items.Add(" " + emailId.Address);
}
}
It seems like you're trying to do 3-Legged OAuth. .NET samples for performing 3-Legged OAuth 1.0a are documented here:
http://code.google.com/apis/gdata/docs/auth/oauth.html#Examples

How to connect to an active directory server?

I'm using below code for connecting to an active directory server and retrieving its users.
But my web server is not in sub domain. Can I connect to it?
Or I should include its Ip address or something else?
DirectoryEntry entry = new DirectoryEntry("LDAP://dps.com", "Raymond", "xxxxxxx");
DirectorySearcher mySearcher = new DirectorySearcher(entry);
mySearcher.Filter = ("(&(objectCategory=person)(objectClass=user))");
foreach (SearchResult result in mySearcher.FindAll())
{
ResultPropertyCollection myResultPropColl = result.Properties;
DataRow dr=reader.Tables[0].NewRow();
dr[0]=myResultPropColl["samaccountname"][0].ToString()+"#"+Domain;
reader.Tables[0].Rows.Add(dr);
Response.Write(myResultPropColl["samaccountname"][0].ToString());
}
If 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 - connects to the current default domain
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
// find user by name
UserPrincipal user = UserPrincipal.FindByIdentity("John Doe");
// find all users in your AD directory - set up a "query-by-example"
// template to search for; here: a UserPrincipal, which is not locked out
UserPrincipal userTemplate = new UserPrincipal(ctx);
userTemplate.IsAccountLockedOut = false;
// create a PrincipalSearcher, based on that search template
PrincipalSearcher searcher = new PrincipalSearcher(userTemplate);
// enumerate all users that this searcher finds
foreach(Principal foundPrincipal in searcher.FindAll())
{
UserPrincipal foundUser = (foundPrincipal as UserPrincipal);
// do something with the userTemplate
}
The new S.DS.AM makes it really easy to play around with users and groups in AD:
If you cannot upgrade to S.DS.AM, what you need to do is make sure to use a proper LDAP string to connect to your server. That string should be something like:
LDAP://servername/OU=Users,DC=YourCompany,DC=com
The servername is optional - you can also leave that out. But the LDAP string needs to be made up of at least one DC=xxxxx string, and possibly other LDAP segments.

storing logger information asp.net

i am building site where there are three types of user. Admin,Merchant and Assitant User.
Where to store information so that my application will know which user has logged on( whether it is admin or assitant user or merchant)
Thank you
You want to look at ASP.NET Membership and Roles.
string path = DateTime.Today.ToString("dd-mm-yy") + ".txt";
if (!File.Exists(System.Web.HttpContext.Current.Server.MapPath(path)))
{
File.Create(System.Web.HttpContext.Current.Server.MapPath(path)).Close();
}
using (StreamWriter w = File.AppendText(System.Web.HttpContext.Current.Server.MapPath(path)))
{
w.WriteLine("\r\nLog Entry : ");
w.WriteLine("Membership.GetUser().UserName);
w.Flush();
w.Close();
}

Resources