0
votes

I'm working on an ASP.Net Web application that uses Forms-based authentication. I'm authenticating against an Active Directory domain. I'm getting successful authentication, getting the information I need from AD, and then using Response.Redirect() to redirect the user to the application's Default.aspx page, but instead it is returning to Login.aspx. I can't figure out what's going wrong.

Here's my login code (gets run when the user enters their domain, username, and password and clicks "Login"):

protected void btnLogin_Click(object sender, EventArgs e)
{
    string adPath = "LDAP://my.ad.path:636";

    FormsAuth.LdapAuthentication adAuth = new FormsAuth.LdapAuthentication(adPath);

    bool isAuthenticated = false;
    //"loggedInUser" is a class to hold information about the user
    loggedInUser = adAuth.LoginAndGetRequestorLoginInfo(out isAuthenticated, tbxDomain.Text, tbxUsername.Text, tbxPassword.Text);

    if (isAuthenticated)
    {
        //Create the ticket
        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, tbxUsername.Text, DateTime.Now,
            DateTime.Now.AddMinutes(60), true, tbxUsername.Text);

        //Encrypt the ticket.
        string encryptedTicket = FormsAuthentication.Encrypt(authTicket);

        //Create a cookie, and then add the encrypted ticket to the cookie as data.
        HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);

        //Set cookie expiration to match ticket expiration
        authCookie.Expires = authTicket.Expiration;

        //Add the cookie to the outgoing cookies collection.
        Response.Cookies.Add(authCookie);

        //Store user information in session to use later
        Session["verifiedUser"] = loggedInUser;

        //Now redirect to default page
        Response.Redirect("~/User/Default.aspx");
    }
    else
    {
        lblError.Text = "Authentication did not succeed. Please check your user name and password.";
        lblError.Visible = true;
    }
} //end method btnLogin_Click

Here's the LDAP authentication code (in a separate class):

using System;
using System.DirectoryServices;
using System.Text;

namespace FormsAuth
{
    public class LdapAuthentication
    {
        private string _path;
        private string _filterAttribute;

        public LdapAuthentication(string path)
        {
            _path = path;
        }

        public bool IsAuthenticated(string domain, string username, string pwd)
        {
            string domainAndUsername = domain + @"\" + username;
            DirectoryEntry entry = new DirectoryEntry(_path);

            try
            {
                //Bind to the native AdsObject to force authentication.
                object obj = entry.NativeObject;

                DirectorySearcher search = new DirectorySearcher(entry);

                search.Filter = String.Format("(SAMAccountName={0})", username);
                search.PropertiesToLoad.Add("SAMAccountName");

                SearchResult result = search.FindOne();

                if (result == null)
                {
                    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;
        }

        public Requestor LoginAndGetRequestorLoginInfo(out bool isAuthenticated, string domain, string username, string pwd)
        {
            Requestor req = new Requestor();
            DirectoryEntry entry = new DirectoryEntry(_path);

            try
            {
                //Bind to the native AdsObject to force authentication.
                object obj = entry.NativeObject;

                DirectorySearcher search = new DirectorySearcher(entry);

                search.Filter = String.Format("(sAMAccountName={0})", username);
                search.PropertiesToLoad.Add("sAMAccountName");
                search.PropertiesToLoad.Add("cn");
                search.PropertiesToLoad.Add("sn");
                search.PropertiesToLoad.Add("givenName");
                search.PropertiesToLoad.Add("employeeID");
                search.PropertiesToLoad.Add("telephoneNumber");
                search.PropertiesToLoad.Add("mail");

                SearchResult result = search.FindOne();

                if (result == null)
                {
                    isAuthenticated = false;
                    return null;
                }

                //Populate Requestor object with results returned from directory search
                if (result.Properties["sAMAccountName"] != null && result.Properties["sAMAccountName"].Count > 0)
                {
                    req.Login = domain + "\\" + result.Properties["sAMAccountName"][0].ToString();
                }
                if (result.Properties["sn"] != null && result.Properties["sn"].Count > 0)
                {
                    req.LName = result.Properties["sn"][0].ToString();
                }
                if (result.Properties["givenName"] != null && result.Properties["givenName"].Count > 0)
                {
                    req.FName = result.Properties["givenName"][0].ToString();
                }
                if (result.Properties["employeeID"] != null && result.Properties["employeeID"].Count > 0)
                {
                    if (result.Properties["employeeID"][0].ToString().Length > 0)
                    {
                        req.EmployeeID = Convert.ToInt32(result.Properties["employeeID"][0].ToString());
                    }
                }
                if (result.Properties["telephoneNumber"] != null && result.Properties["telephoneNumber"].Count > 0)
                {
                    req.Phone = result.Properties["telephoneNumber"][0].ToString();
                }
                if (result.Properties["mail"] != null && result.Properties["mail"].Count > 0)
                {
                    req.Email = result.Properties["mail"][0].ToString();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error authenticating user. " + ex.Message);
            }

            isAuthenticated = true;
            return req;
        } //end method LoginAndGetRequestorLoginInfo
    }
}
1
Have you checked that in the web.config file, you've set authorization to your site root (or the /user folder) so that only ? is denied? I've denied authorization to * by mistake once and it caused a problem similar to yours.Geeky Guy
In the root Web.config, it's <authorization><allow users="*"/><deny users="?"/></authorization>. In the User folder Web.config, it's <allow roles="Admin,Manager,User"/><deny users="*"/>. The user I'm testing with is a member of all three roles (using SQL Membership for role management).timbck2
Does the user landing page have any redirection code?Geeky Guy
No, it's just a static page with instructions on where to go next.timbck2
Instructions on where to go next?Geeky Guy

1 Answers

0
votes

As it turns out from the comments in the questions, it's a matter of the order roles and members have been authorized or deauthorized in the configuration.

Authorization happens in the order it's declared. So even if you give authorization to some members and roles, they'll get deauthorized if later you deny access to all.

Just have authorization done in a way that everybody gets denied access first, then some roles and members get authorized after that, and you're all set.