0

So I'm trying to recycle some code that was for a 'code behind' patterned .NET app for my MVC app and the Authenticate class they used. How the SignInController's Index method based on the code they gave me is supposed to work is to call an Authenticate class method in the else if which gets a token and redirects back to the Index method at which point since the app now has a token, it goes into the first if conditional and a different method in the aforementioned Authenticate validates the token. Since users will not start out with a token, the else if will always be dove into first.

In order to soothe the "Not all code paths return a value" error I have to add a return statement at the end of the else if clause and an else clause. However, if I return null Index doesn't get redirected to as confirmed by breakpoints. However, if I do return RedirectToAction("Index", "SignIn"); I get an error about "Cannot redirect after HTTP headers have been sent" which I suspect is because the Redirect call from the Authenticate class hasn't been completed yet. However I'm at odds as to how to remedy situation as either return value fails to redirect the web app back to Index...

Original "look behind" styled .NET code that I'm trying to recycle from a colleague's app:

if (string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name) &&  HttpContext.Current.Request.QueryString["Token"] != null)
{
// we’ve got a token, they must have logged in .. double-check the token
string ssoToken = HttpContext.Current.Request.QueryString["Token"].ToString();
string userRoles = string.Empty;
  if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
  {
      string userName = HttpContext.Current.User.Identity.Name;
      ((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
      RedirectOnSuccess();

  }
  else
  {
      RedirectToForbiddenPage();
  }
}
else if(string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
{
   // no user data..go ask them to get SSOToken from service
   Authenticate.isUserAuthenticated();
}

My attempt to repurpose it into a MVC styled .NET app:

        public ActionResult Index()
        {
            if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name) && System.Web.HttpContext.Current.Request.QueryString["Token"] != null)
            {
                // we’ve got a token, they must have logged in ... double-check the token
                string ssoToken = System.Web.HttpContext.Current.Request.QueryString["Token"].ToString();
                string userRoles = string.Empty;
                if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
                {
                    string userName = System.Web.HttpContext.Current.User.Identity.Name;
                    //((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
                    //RedirectOnSuccess();

                    // TODO: Not sure what the MVC equivalent would be for commented out code above
                    return RedirectToAction("Index", "Checklist");   
                }
                else
                {
                    //RedirectToForbiddenPage();
HttpStatusCodeResult(HttpStatusCode.Forbidden);
                }
            }
            else if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name))
            {
                // no user data...go ask them to get SSOToken from service
                Authenticate.isUserAuthenticated();
                return null; // Screwed if I don't return anything because of build error, screwed if I do return something because it messes with the redirect
            }
            else
            {
                return null;
            }
        }

Authenticate class snippet at the end of isUserAuthenticated that gets the token:

//string RedirectURL = GetBaseVirtualDirectory() + "/SignIn/Index";
string RedirectURL = "https://localhost:XXXX1/SignIn/Index";
HttpContext.Current.Response.Redirect(authServiceURL + "/Windows/Auth?RedirectURL=" + RedirectURL, true);
Kurt Wagner
  • 3,295
  • 13
  • 44
  • 71
  • Possible duplicate of [Why do I get "Cannot redirect after HTTP headers have been sent" when I call Response.Redirect()?](http://stackoverflow.com/questions/159523/why-do-i-get-cannot-redirect-after-http-headers-have-been-sent-when-i-call-res) – Michael Freidgeim Mar 22 '17 at 06:29

1 Answers1

0

The problem is that your Authenticate.ValidateSSOToken method already called HttpContext.Current.Response.Redirect, which, as error message confirms, added a redirect header (Location) to the response.

You might be able to clear the response before calling RedirectToAction.

But a method called ValidateSSOToke probably should not do any redirects itself. It should return a status and you should do any redirects outside of it based on that status.

And doing all that validation inside your Action is probably not a good practice to begin with.

Viktor A
  • 146
  • 8
  • Well the thing is it's not even getting to ValidateSSOToken yet. In terms of current flow. User visits site -> Since user doesn't have token, method goes to else if to get token -> else if calls Authenticate.isUserAuthenticaed -> isUserAuthenticated calls auth service w/ a redirect URL back to Index -> (flow breaks here at the end if return, [flow that's supposed to happen after follows]) -> app goes through first if -> when going through second if, calls service again to validate token -> user cookies et al get set -> method redirects to the Checklist which is the UI that the user wants – Kurt Wagner Feb 02 '16 at 18:26
  • Oh, my mistake, it's isUserAuthenticated not ValidateSSOToken. But everything else probably still holds true. isUserAuthenticated should not do the redirect. – Viktor A Feb 02 '16 at 18:36