Hello all,
My first post to the board and it's going to be a "I'm having trouble with my authentication code..." *lol* I was so determined to work it out myself too.
Ok, Through reading various posts & sites I've cobbled together a couple of pages to perform forms based authentication.
It all seems to work and I authenticate fine, however it doesn't seem to be passing the roles so that I can use User.IsInRole().
I'm writing the ticket and setting up the General Principal and there are no errors, but the bit of code I put in my index page to test if I could read the roles is coming back false.
Anyway, here's the code, please excuse the cludgyness, but my copy of VS.NET isn't here yet so this is all done using good old fashioned notepad.
web.config:
<CODE>
<configuration>
<system.web>
<customErrors mode="Off"/>
<authentication mode="Forms">
<forms name="./IMOECookie" loginUrl="login.aspx" protection="All" timeout="1" path="/"/>
</authentication>
<authorization>
<deny users="?" />
</authorization>
<identity impersonate="true" />
</system.web>
</configuration>
</CODE>
Login.aspx
<CODE>
<%... Import Namespace="System.DirectoryServices" %>
<%... Import Namespace="System.Security.Principal" %>
<html>
<script language="C#" runat=server>
string LDAPPATH = "LDAP://hundredacrewood.local/DC=hundredacrewood,DC=local";
string _filterAttribute = "";
int CookieTimeOut = 1;
public bool AuthenticateUser(string domain, string username, string password)
{
string domainAndUsername = domain + ..."\" + username;
DirectoryEntry entry = new DirectoryEntry( LDAPPATH, domainAndUsername, password);
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
LDAPPATH = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
lblResults.Text = "Error: " + ex.Message;
return false;
}
lblResults.Text = "";
return true;
}
void LoadUser(string username)
{
DirectorySearcher search = new DirectorySearcher(LDAPPATH);
search.Filter = "(cn=" + _filterAttribute + ")";
search.PropertiesToLoad.Add("memberOf");
StringBuilder groupNames = new StringBuilder();
try
{
SearchResult result = search.FindOne();
int propertyCount = result.Properties["memberOf"].Count;
String dn;
int equalsIndex, commaIndex;
for(int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
{
dn = (String)result.Properties["memberOf"][propertyCounter];
equalsIndex = dn.IndexOf("=", 1);
commaIndex = dn.IndexOf(",", 1);
groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
groupNames.Append("|");
}
}
catch(Exception ex)
{
lblResults.Text = "Error: " + ex.Message;
}
lblResults.Text = "";
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(CookieTimeOut), false,groupNames.ToString(), "/");
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie authCookie = new HttpCookie( FormsAuthentication.FormsCookieName , encryptedTicket);
Response.Cookies.Add(authCookie);
}
void Login_Click(Object sender, EventArgs E)
{
if(AuthenticateUser(UserDomain.Value, UserName.Value, UserPass.Value))
{
LoadUser(UserName.Value);
Response.Redirect(FormsAuthentication.GetRedirectUrl(UserDomain.Value,false));
}
}
</script>
<body>
<form runat="server" ID="Form1">
<h3>Login Page</h3>
<hr>
UserName:<input id="UserName" type="text" runat="server"/>
<asp:RequiredFieldValidator ControlToValidate="UserName" Display="Static" ErrorMessage="*" runat="server"/>
<P>
Password:<input id="UserPass" type="password" runat="server"/>
<asp:RequiredFieldValidator ControlToValidate="UserPass" Display="Static" ErrorMessage="*" runat="server"/>
</P>
<P>
Domain:<input id="UserDomain" type="text" runat="server"/>
<asp:RequiredFieldValidator ControlToValidate="UserDomain" Display="Static" ErrorMessage="*" runat="server"/>
</P>
<P>
<asp:button id="cmdLogin" text="Login" OnClick="Login_Click" runat="server"/>
</P>
<P>
<asp:Label id="lblResults" ForeColor="red" Font-Size="10" runat="server" />
</P>
</form>
</body>
</html>
</CODE>
Global.axas
<CODE>
<%... Application Codebehind="Global.asax.cs"%>
</CODE>
Snippet from Global.axas.cs
<CODE>
void Application_AuthenticateRequest(Object sender, EventArgs e)
{
String cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if(null == authCookie)
{//There is no authentication cookie.
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch(Exception ex)
{
//Write the exception to the Event Log.
return;
}
if(null == authTicket)
{//Cookie failed to decrypt.
return;
}
//When the ticket was created, the UserData property was assigned a
//pipe-delimited string of group names.
String[] groups = authTicket.UserData.Split(new char[]{'|'});
//Create an Identity.
GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");
//This principal flows throughout the request.
GenericPrincipal principal = new GenericPrincipal(id, groups);
Context.User = principal;
}
</CODE>
index.aspx (Yes I know I switched to VB.NET :) )
<CODE>
<script runat="server">
sub Page_Load
if Not Page.IsPostBack then
dim mycountries=New Hashtable
mycountries.Add("N","Norway")
mycountries.Add("S","Sweden")
mycountries.Add("F","France")
mycountries.Add("I","Italy")
rb.DataSource=mycountries
rb.DataValueField="Key"
rb.DataTextField="Value"
rb.DataBind()
end if
end sub
sub displayMessage(s as Object,e As EventArgs)
lbl1.text="Your favorite country is: " & rb.SelectedItem.Text
if User.IsInRole("Test") then
lbl2.text = "Test"
else
lbl2.text = "Not Test"
end if
end sub
</script><html>
<body><form runat="server">
<asp:RadioButtonList id="rb" runat="server"
AutoPostBack="True" onSelectedIndexChanged="displayMessage" />
<p><asp:label id="lbl1" runat="server" /></p>
<p><asp:label id="lbl2" runat="server" /></p>
</form></body>
</html>
</CODE>
A fair bit of cut and paste code, and the global.asax.cs was taken piecemeal from this site. But still not bad considering that I've never touched .NET or C# before and I've no books, or dev tools here (unless you count Notepad) :)
So, if anyone can help me crack the roles issue I'd be very grateful.
Dear all,i have a problem in editing security.config file of client using windows user component.I a...
By nbkhubani
Hello ASP.NET Gurus,Has anyone come accross this? It seems that an authenticated user accessing a pa...
By webdog3003
Hello,I have used sucesfully the GetFullResponseProperty to get theFR_PROP_FULLRESPONSE and install ...
By brianspiteri
I have a Smart Application that is run via IEExec.exe.I have a custom configurationSectionHandler wh...
By mortenlyhr
When I attempt to use any of the Membership class functions (eg getAllUsers()) to access my db, I've...
By acsher, 3 Comments
Hi,Thanks to you both of you for the valuble feedback.I've implemented your work-around Henning ...
By chaz, 2 Comments
When using the PasswordRecovery control I've got the message: "Your answer could not be verified. Pl...
By javierh, 5 Comments
Hi, all,I heard a lot that we should locate connection string in the web.config file. Well, for secu...
By dluzhu, 4 Comments
Hello all,I've looked through this newsgroup and saw lots of questions about runningan applicati...
By mattbudd, 1 Comments
Jenni
Can you try doing 2 things
1. Put this Code at the end of the Application_AuthenticateRequest(..)To See the List of Groups the Authenticated User is a Member Of
Response.Write ( "Groups: " + authTicket.UserData + "<br>");
2. make sure that the DomainName is a Valid One ( means tha the"Test" is a Valid Role or it exists in the groups array)
see how it works
luvdotnet | Tues, 01 Jan 2008 02:29:00 GMT |
Ok, I added the line with no success, so at the begining of AuthenticateRequest I put a simple Response.Write ("Got Here") to see if the section of code ran at all, but nothing.
So, I double checked the Security Group, and it was fine and added a line of code to display the contents of the variable before it's loaded into the cookie and it's as I expected A list of Groups separated by vertical bars and Test was one of them.
The problem has to either be:
A) The value isn'r being correctly loaded into the Cookie
Or my personal belief,
B) The AuthenticateRequest code isn't running at all or is running incorrectly.
jennih | Tues, 01 Jan 2008 02:30:00 GMT |
i am not sure if this is the problem but worth trying it
1 .You are creating the FormsAuthenticationTicket with theUserName thatwill be associated with the Ticket , which is right
FormsAuthenticationTicket authTicket = newFormsAuthenticationTicket(1, username, DateTime.Now,DateTime.Now.AddMinutes(CookieTimeOut), false,groupNames.ToString(),"/")
but when redirecting you are the UserDomain.Value when ( or tofire the Application_AuthenticateRequest ) can you please changeit to user UserName instead and see if it works
2. And also you said that you put some line of code Response.Write("Got Here") and its not hitting that means the AuthenticateRequestevent is not fired which means that The AuthenticatedUser is returningfalse or the User is not Authenticated can you please check on that aswell
void Login_Click(Object sender, EventArgs E)
{
if(AuthenticateUser(UserDomain.Value, UserName.Value, UserPass.Value))
{
LoadUser(UserName.Value);
Response.Redirect(FormsAuthentication.GetRedirectUrl(UserDomain.Value,false));// THIS SHOULD FIRE APPLICATION_AUTHENTICATEREQUEST Event , which meansthe User has to be authenticated first in ur code
}
}
3 .Also try adding the <allow users = "*' /> tag as well in theauthorization tag in the config ( this should not matter but worhgivign a try )
hth
Vivek
luvdotnet | Tues, 01 Jan 2008 02:31:00 GMT |