protected void Page_Load(object sender, EventArgs e) { preAnalyzer = Context.Items["preAnalyzer"] as FormsAuthenticationAnalyzer; postAnalyzer = new FormsAuthenticationAnalyzer(HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName], false); if (!Page.IsPostBack) { BindFields(); } ValidateFields(); }
/// <summary> /// Performs a comparison of analyses taken a different points in the request processing pipeline /// </summary> /// <param name="before">The prior analysis</param> /// <param name="after">The current analysis</param> /// <returns>A conclusion derived from the analysis change</returns> public static ComparisonResult Compare(FormsAuthenticationAnalyzer before, FormsAuthenticationAnalyzer after) { if (before.RequestIsMalicious || after.RequestIsMalicious) { return ComparisonResult.MaliciousRequest; } if (before.RequestIsAuthenticated && after.RequestIsAuthenticated) { return ComparisonResult.AuthenticatedRequest; } if (before.RequestIsAuthenticated && !after.RequestIsAuthenticated) { return ComparisonResult.LogoutRequest; } if (!before.RequestIsAuthenticated && !after.RequestIsAuthenticated && before.FormsAuthenticationCookieResult.IsExpired) { return ComparisonResult.LogoutRequest; } if (!before.RequestIsAuthenticated && after.RequestIsAuthenticated) { return ComparisonResult.LoginRequest; } return ComparisonResult.UnauthenticatedRequest; }
/// <summary> /// Detects the creation of a FormsAuthenticationCookie and FormsAuthenticationTicket /// during the processing of the current request (i.e., PostBack of Login page/action), /// records the state of both in a UserAuthenticationTicket, and adds it to the /// Provider. /// /// In the event that this request was already authenticated, it detects and handles /// sliding expiration on the Provider. /// </summary> /// <param name="sender">The HttpApplication that sent the request</param> /// <param name="e">Not used</param> private static void OnEndRequest(object sender, EventArgs e) { // EnhancedSecurity.InterceptFormsAuthenticationCookie(); FormsAuthenticationStatus status = EnhancedSecurity.GetFormsAuthStatus(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; HttpResponse response = context.Response; /* TODO: Remove this once working */ /* if (request.RawUrl.Contains("WebResource.axd")) { return; } */ if (status == FormsAuthenticationStatus.NotFound || status == FormsAuthenticationStatus.Invalid) { FormsAuthenticationAnalyzer preAnalyzer = context.Items["preAnalyzer"] as FormsAuthenticationAnalyzer; FormsAuthenticationAnalyzer postAnalyzer = new FormsAuthenticationAnalyzer(response.Cookies[FormsAuthentication.FormsCookieName], true); if (preAnalyzer != null) { ComparisonResult result = FormsAuthenticationAnalyzer.Compare(preAnalyzer, postAnalyzer); if (result == ComparisonResult.UnauthenticatedRequest) { // Nothing to do } else if (result == ComparisonResult.AuthenticatedRequest) { // Nothing to do } else if (result == ComparisonResult.LoginRequest) { // Store the ticket on the server string hash = UserAuthentication.CalculateFormsAuthTicketHash(postAnalyzer.FormsAuthenticationTicket); string key = Guid.NewGuid().ToString(); UserAuthenticationTicket userAuthTicket = new UserAuthenticationTicket { Key = key, Username = postAnalyzer.FormsAuthenticationTicket.Name, HostAddress = request.UserHostAddress, CookieDomain = postAnalyzer.FormsAuthenticationCookie.Domain, CookiePath = postAnalyzer.FormsAuthenticationCookie.Path, CookieSecure = postAnalyzer.FormsAuthenticationCookie.Secure, TicketExpiration = postAnalyzer.FormsAuthenticationTicket.Expiration, CookieName = postAnalyzer.FormsAuthenticationCookie.Name, TicketIsPersistent = postAnalyzer.FormsAuthenticationTicket.IsPersistent, TicketIssueDate = postAnalyzer.FormsAuthenticationTicket.IssueDate, TicketUserData = postAnalyzer.FormsAuthenticationTicket.UserData, TicketVersion = postAnalyzer.FormsAuthenticationTicket.Version, TicketHash = hash }; UserAuthentication.Provider.InsertTicket(userAuthTicket, postAnalyzer.FormsAuthenticationTicket.Expiration); FormsAuthenticationTicket newFormsAuthTicket = UserAuthentication.CreateFormsAuthTicket( postAnalyzer.FormsAuthenticationTicket.Name, postAnalyzer.FormsAuthenticationCookie.Path, hash + ";" + key, postAnalyzer.FormsAuthenticationTicket.IssueDate, postAnalyzer.FormsAuthenticationTicket.Expiration, false ); UserAuthentication.ClearAuthCookie(); UserAuthentication.SetAuthCookie(newFormsAuthTicket, true, true); } else if (result == ComparisonResult.LogoutRequest) { if (preAnalyzer.UserAuthenticationTicket != null) { UserAuthentication.Provider.RevokeTicket(preAnalyzer.UserAuthenticationTicket.Key); } UserAuthentication.ClearAuthCookie(); // Revoke the ticket on the server } else if (result == ComparisonResult.MaliciousRequest) { UserAuthentication.ClearAuthCookie(); // Hmm.. what to do // System.Diagnostics.Debugger.Break(); } } } else if (status == FormsAuthenticationStatus.Valid) { // TODO: Handle sliding ticket expiration // UserAuthentication.Provider.UpdateTicketExpiration(); } }
/// <summary> /// Intercepts the beginning of the request pipeline and performs analysis /// and manipulation of FormsAuthenticationCookies prior to the /// FormsAuthenticationModule's AuthenticateRequest firing. It stores some /// information about the request in the Context.Items collection for analysis /// later in the request pipeline execution. /// </summary> /// <param name="sender">The HttpApplication that sent the request</param> /// <param name="e">Not used</param> private static void OnBeginRequest(object sender, EventArgs e) { HttpContext context = HttpContext.Current; HttpRequest request = context.Request; HttpResponse response = context.Response; if (request.RawUrl.Contains(".axd")) { context.Items["BewareOfCryptographicException"] = "true"; } if (request.QueryString["aspxerrorpath"] != null) { EnhancedSecurity.DelaySuspiciousResponse(); string newUrl = RemovQueryStringArg("aspxerrorpath"); response.Redirect(newUrl, false); response.End(); } EnhancedSecurity.Initialize(); HttpCookie formsAuthCookie = context.Request.Cookies[FormsAuthentication.FormsCookieName]; FormsAuthenticationAnalyzer analyzer = new FormsAuthenticationAnalyzer(formsAuthCookie, false); context.Items["preAnalyzer"] = analyzer; if (analyzer.RequestIsAuthenticated) { if (analyzer.RequestIsMalicious) { EnhancedSecurity.SetFormsAuthStatus(FormsAuthenticationStatus.Invalid); EnhancedSecurity.DelayMaliciousResponse(); } else if (!analyzer.RequestIsValid) { EnhancedSecurity.SetFormsAuthStatus(FormsAuthenticationStatus.Invalid); } else { EnhancedSecurity.SetFormsAuthStatus(FormsAuthenticationStatus.Valid); if (UserAuthentication.Enabled) { // analyzer.FormsAuthenticationCookie.Value; context.Items["OriginalCookieValue"] = analyzer.FormsAuthenticationCookie.Value; context.Items["ServerUserData"] = analyzer.FormsAuthenticationTicket.UserData; context.Items["ServerTicketKey"] = analyzer.UserAuthenticationTicket.Key; context.Items["UserAuthenticationTicket"] = analyzer.UserAuthenticationTicket; // Substitute actual UserData from serverTicket FormsAuthenticationTicket tempFormsAuthTicket = UserAuthentication.CreateFormsAuthTicket( analyzer.UserAuthenticationTicket.Username, analyzer.UserAuthenticationTicket.CookiePath, analyzer.UserAuthenticationTicket.TicketUserData, analyzer.UserAuthenticationTicket.TicketIssueDate, analyzer.FormsAuthenticationTicket.Expiration, false ); UserAuthentication.SetAuthCookie(tempFormsAuthTicket, true, false); } } } else { if (analyzer.RequestIsMalicious) { EnhancedSecurity.SetFormsAuthStatus(FormsAuthenticationStatus.Invalid); EnhancedSecurity.DelayMaliciousResponse(); } else { EnhancedSecurity.SetFormsAuthStatus(FormsAuthenticationStatus.NotFound); } } }