using System; using System.Data; using System.Web; using System.Web.Configuration; using System.Web.Security; using System.Linq; using System.Xml.Linq; using Neo.Afx.Utilities; using DPUruNet; namespace Neo.Afx.Security { /// /// Manages authentication to a . /// public static class DomainAuthenticationProvider { private const int DPFJ_PROBABILITY_ONE = 0x7fffffff; const string EventSource = "DomainAuthenticationProvider"; //const string ExceptionMessage = "An exception occurred. Please check the log."; #region AuthenticationMode /// /// Gets the. /// public static AuthenticationMode AuthenticationMode { get { var authType = HttpContext.Current.User.Identity.AuthenticationType; return (string.IsNullOrEmpty(authType) || authType == "Forms") ? AuthenticationMode.Forms : AuthenticationMode.Windows; } } #endregion #region DefaultUrl /// /// Gets the default URL. /// public static string DefaultUrl { get { return FormsAuthentication.DefaultUrl.TrimStart('/'); } } #endregion #region Signout /// /// Sign the user out if the user was signed in using forms authentication. /// public static void Signout() { if(AuthenticationMode == AuthenticationMode.Forms) { // Destroy the user's authentication cookie. FormsAuthentication.SignOut(); // abandon a session and clear the session ID cookie. HttpContext.Current.Session.Abandon(); HttpContext.Current.Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", "")); } } #endregion #region SetAuthCookie /// /// Sets the auth cookie. /// /// The name of the user. /// true if [persistent]; false otherwise. /// The data to be stored in the ticket. public static void SetAuthCookie(string userName, bool persistent, string data = null) { // Notice that this cookie will have all the attributes according to // the ones in the config file setting. var cookie = FormsAuthentication.GetAuthCookie(userName, persistent); var ticket = FormsAuthentication.Decrypt(cookie.Value); // Store the Guid inside the Forms Ticket with all the attributes // aligned with the config Forms section. var newticket = new FormsAuthenticationTicket( ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, persistent, data, ticket.CookiePath); var encryptedTicket = FormsAuthentication.Encrypt(newticket); FormsAuthentication.SetAuthCookie(userName, persistent); } #endregion #region GetUserID /// /// Gets the ID of the current user. /// /// The ID of the user; -1 if not found. public static long GetUserID() { return GetUserID(HttpContext.Current.User.Identity.Name); } /// /// Gets the user ID. /// /// The name of the user to retrieved. /// The ID of the user; -1 if not found. public static long GetUserID(string userName) { var membershipProvider = (DomainMembershipProvider)Membership.Provider; return membershipProvider.GetUserID(userName, AuthenticationMode); } #endregion #region ValidateWindowsUser /// /// Verifies that the current windows user is authenticated and valid; if so, sets the forms auth cookie. /// /// true if the windows user is authenticated and valid; false otherwise. public static bool ValidateWindowsUser() { var context = HttpContext.Current; if(context.User.Identity.IsAuthenticated) { var membershipProvider = (DomainMembershipProvider)Membership.Provider; try { var wi = context.Request.LogonUserIdentity; if(wi != null) { var userName = membershipProvider.GetUserName(wi.Name); if(userName != null) { SetAuthCookie(userName, false, "AuthType=Windows"); return true; } } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { // DomainMembershipProvider writes exception to event log } } return false; } #endregion #region ValidateUser #region ValidateUser(string userName, string password, bool rememberMe) /// /// Verifies that the given user name and password are valid. /// /// The user name to be verified. /// The password to be verified. /// true if the authentication cookie should be persisted; false otherwise. /// true if the user name and password are valid; false otherwise. public static bool ValidateUser(string userName, string password, bool rememberMe) { var membershipProvider = (DomainMembershipProvider)Membership.Provider; try { var token = membershipProvider.GetToken(userName); if(token != null) { var challengeToken = XElement.Parse(token); var credentials = SecurePassword.CreateSecureCredentials(challengeToken, password); if(Membership.ValidateUser(userName, credentials)) { SetAuthCookie(userName, rememberMe, "AuthType=Forms"); return true; } } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { // DomainMembershipProvider writes exception to event log } return false; } #endregion #region ValidateUser(string fingerPrint, bool rememberMe, ref string userName) /// /// Verifies that the given fingerprint is valid /// /// The fingerprint to be verified. /// true if the authentication cookie should be persisted; false otherwise. /// true if the fingerprint valid; false otherwise. public static bool ValidateUser(string fingerPrint, bool rememberMe, ref string userName) { return ValidateUser(fingerPrint, rememberMe, 0, ref userName); } #endregion #region ValidateUser(string fingerPrint, bool rememberMe, long userID, ref string userName) /// /// Verifies that the given fingerprint is valid /// /// The fingerprint to be verified. /// true if the authentication cookie should be persisted; false otherwise. /// true if the fingerprint valid; false otherwise. public static bool ValidateUser(string fingerPrint, bool rememberMe, long userID, ref string userName) { var validUserFound = false; int thresholdScore = DPFJ_PROBABILITY_ONE * 1 / 100000; var membershipProvider = (DomainMembershipProvider)Membership.Provider; try { var fingerprintBytes = Convert.FromBase64String(fingerPrint); Fmd fmd = new Fmd(fingerprintBytes, (int)Constants.Formats.Fmd.DP_VERIFICATION, "1.0.0"); using (var fingerPrintTable = membershipProvider.GetUserFingerprintTemplates()) { if (fingerPrintTable.Rows.Count > 0) { //If a userid was provided, check if you can find the id in the list and check that fingerprint first if (userID > 0) { var r = fingerPrintTable.AsEnumerable().Where(a => a.Field("UserID") == userID).FirstOrDefault(); if (r != null) { Fmd[] fmds = new Fmd[1]; fmds[0] = new Fmd((Byte[])r.Field("FingerprintTemplate"), (int)Constants.Formats.Fmd.DP_REGISTRATION, "1.0.0"); IdentifyResult identifyResult = Comparison.Identify(fmd, 0, fmds, thresholdScore, 2); if (identifyResult.ResultCode == Constants.ResultCode.DP_SUCCESS) { if (identifyResult.Indexes.Length == 1) { SetAuthCookie(r.Field("Email").ToString(), rememberMe, "AuthType=Forms"); userName = r.Field("Email").ToString(); validUserFound = true; } } } } //if the specified user was not found, check all the other users if (!validUserFound) { foreach (DataRow r in fingerPrintTable.Rows) { Fmd[] fmds = new Fmd[1]; fmds[0] = new Fmd((Byte[])r.Field("FingerprintTemplate"), (int)Constants.Formats.Fmd.DP_REGISTRATION, "1.0.0"); IdentifyResult identifyResult = Comparison.Identify(fmd, 0, fmds, thresholdScore, 2); if (identifyResult.ResultCode == Constants.ResultCode.DP_SUCCESS) { if (identifyResult.Indexes.Length == 1) { SetAuthCookie(r.Field("Email").ToString(), rememberMe, "AuthType=Forms"); userName = r.Field("Email").ToString(); validUserFound = true; break; } } } } } } } // ReSharper disable EmptyGeneralCatchClause catch (Exception ex) // ReSharper restore EmptyGeneralCatchClause { // DomainMembershipProvider writes exception to event log } return validUserFound; } #endregion #endregion #region GetResetQuestion /// /// Gets the password question for the user. /// /// The user name to be queried. /// The password question for the user. public static string GetResetQuestion(string userName) { var membershipProvider = (DomainMembershipProvider)Membership.Provider; return membershipProvider.GetPasswordQuestion(userName); } #endregion #region ResetPassword /// /// Resets a user's password to a new, automatically generated password. /// /// The user to reset the password for. /// The password question for the specified user. /// The password answer for the specified user. /// The new password for the specified user. public static bool ResetPassword(string userName, string question, string answer) { var membershipProvider = (DomainMembershipProvider)Membership.Provider; try { var token = membershipProvider.GetResetToken(userName); if(token != null) { var challengeToken = XElement.Parse(token); if(challengeToken.Value == question) { var credentials = SecurePassword.CreateSecureCredentials(challengeToken, answer); membershipProvider.ResetPassword(userName, credentials); return true; } } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { // DomainMembershipProvider writes exception to event log } return false; } #endregion } }