troubleshooting Question

FormsAuthentication problems

Avatar of CCongdon
CCongdonFlag for United States of America asked on
.NET ProgrammingASP.NET
5 Comments1 Solution523 ViewsLast Modified:
I'm having some odd problems. I'm programming my own login system for a .Net application. I was using another website that I didn't build but do maintain as the basis for my code. What is happening is that I want the User.Identity.Name to be a GUID that I pull from a database. Instead, what is occuring is that the username is being saved. Here's the pertinent parts of the code that I'm using... User is simply a custom class that has code to load itself from the database.  If the user is found in the database, then the GUID is loaded, otherwise a new GUID is loaded. After that it has the ability to flag if a submitted password matches the encrypted password stored in the DB. The call for User(string, bool, bool) is for a username, flag to load the password, flag to include deleted users.

The login system seems to work, except that any data I try to put in the userData variable of the FormsAuthenticationTicket cannot be retrieved, and the Identity.Name, which I intended to be a GUID, comes back as the username.



---------------------
login.aspx.cs snippet
---------------------

protected void loginBox_Authenticate(object sender, AuthenticateEventArgs e)
{
    bool isOK = Page.IsValid;
    IPrincipal p = null;
    Authentication.LoginFailure loginResponse;
    if (isOK)
    {
        p = Authentication.AuthenticateUserAsMember(loginBox.UserName, loginBox.Password, out loginResponse);
        switch (loginResponse)
        {
            case Authentication.LoginFailure.LockedOut:
            case Authentication.LoginFailure.Deleted:
                loginBox.FailureText = "Please contact support to reactivate your account.";
                isOK = false;
                break;
            case Authentication.LoginFailure.Inactive:
                loginBox.FailureText = "Please contact support to activate your account.";
                isOK = false;
                break;
            case Authentication.LoginFailure.PasswordNone:
            case Authentication.LoginFailure.PasswordUnknown:
                loginBox.FailureText = "Invalid Password or Username.";
                isOK = false;
                break;
            case Authentication.LoginFailure.UsernameNone:
            case Authentication.LoginFailure.UsernameUnknown:
                loginBox.FailureText = "Invalid User Name or Password.";
                isOK = false;
                break;
            case Authentication.LoginFailure.None:
                isOK = true;
                break;
            default: //Covers Unknown and Other
                loginBox.FailureText = "An error occured. Please contact support.";
                isOK = false;
                break;
        }
        e.Authenticated = isOK;
        if (e.Authenticated)
        {
            DateTime now = DateTime.UtcNow;
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
                    1,
                    p.Identity.Name,
                    now,
                    now.AddMinutes(30),
                    false,
                    string.Empty,
                    FormsAuthentication.FormsCookiePath);
            string encryptedTicket = FormsAuthentication.Encrypt(ticket);
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            cookie.Expires = ticket.Expiration;
            cookie["TimeZoneOffset"] = Session["TimeZoneOffset"] == null ? "0" : (int.Parse(Session["TimeZoneOffset"].ToString()) / 60).ToString();
            Response.Cookies.Add(cookie);
        }
    }
}

protected void loginBox_LoggedIn(object sender, EventArgs e)
{
    Response.Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
}

-----------------
Authentication.cs
-----------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security;
using System.Security.Principal;

namespace Site.Security
{
    public abstract class Authentication
    {
        public enum LoginFailure
        {
            Unknown = 0,
            None = 10,
            UsernameNone = 20,
            UsernameUnknown = 30,
            PasswordNone = 40,
            PasswordUnknown = 50,
            Inactive = 60,
            LockedOut = 70,
            Deleted = 80,
            Other = 100
        }

        private static IPrincipal GetPrincipalFromUserId(Guid userID, Users.UserType userType)
        {
            return new GenericPrincipal(GetIdent(userID.ToString()), new string[1] { userType.ToString() });
        }

        private static IPrincipal GetUnauthenticatedPrincipal()
        {
            return new GenericPrincipal(GetIdent(string.Empty), new string[0]);
        }

        private static IIdentity GetIdent(string userID)
        {
            return new GenericIdentity(userID);
        }

        public static IPrincipal AuthenticateUserAsMember(string userName, string password, out LoginFailure loginResponse)
        {
            User u = null;
            loginResponse = LoginFailure.Unknown;
            if (string.IsNullOrEmpty(userName))
            {
                loginResponse = LoginFailure.UsernameNone;
            }
            else if (string.IsNullOrEmpty(password))
            {
                loginResponse = LoginFailure.PasswordNone;
            }
            else
            {
                u = new User(userName, true, true);
                if (u.UserID == Guid.Empty)
                {
                    loginResponse = LoginFailure.UsernameUnknown;
                }
                else if (u.IsDeleted)
                {
                    loginResponse = LoginFailure.Deleted;
                }
                else if (u.IsLockedOut)
                {
                    loginResponse = LoginFailure.LockedOut;
                }
                else if (u.IsActive != true)
                {
                    loginResponse = LoginFailure.Inactive;
                }
                else if (u.MatchPassword(password) != true)
                {
                    loginResponse = LoginFailure.PasswordUnknown;
                }
            }
            if (loginResponse != LoginFailure.Unknown)
            {
                return GetUnauthenticatedPrincipal();
            }
            else
            {
                loginResponse = LoginFailure.None;
                u.UpdateLastLoginDate();
                return GetPrincipalFromUserId(u.UserID, u.UserType);
            }
        }
    }
}
-----------------------
root web.config snippet
-----------------------
<authentication mode="Forms">
            <forms name=".FoxTrotCorpAuth" loginUrl="~/Login.aspx" defaultUrl="~/secure/Default.aspx" protection="All" timeout="30" path="/" requireSSL="false" slidingExpiration="true" enableCrossAppRedirects="false" cookieless="UseCookies" domain="" />
        </authentication>
        <authorization>
            <allow users="*"/>
        </authorization>

--------------------------------
web.config of secured directory
--------------------------------
<configuration>
    <appSettings/>
    <connectionStrings/>
    <system.web>
        <authorization>
            <deny users="?" />
        </authorization>
    </system.web>
</configuration>
ASKER CERTIFIED SOLUTION
five22bags

Our community of experts have been thoroughly vetted for their expertise and industry experience.

Join our community to see this answer!
Unlock 1 Answer and 5 Comments.
Start Free Trial
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 5 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros