4
votes

I'm trying to deploy an ASP.NET MVC web application, which uses individual user accounts, to an AWS server, which is using an elastic load balancer (ELB). I've deployed the site to IIS on the AWS app server, connected it to my AWS SQL server, and it works as expected on the server (and indeed when I run it in Visual Studio or deploy to an internal server).

The problem comes when accessing it remotely, which of course goes via the ELB.

So basically, if I'm logged in, it's fine. If I'm not logged in, the login page is fine but nothing else is. My thinking, along with a colleague from our internal team who works with AWS (he isn't able to help me btw, I've asked!) is that when I get redirected to the login page, it's a HTTP request and not HTTPS, and that's the cause of the issue, but no matter what I've tried I can't get it to redirect with HTTPS. I've tried:

  • adding rules in my web.config file to pick up forwarded requested and redirect them to HTTPS - which doesn't seem to have made any noticeable difference
  • various different attributes added to either my FilterConfig or the Login action
  • adding rules directly in IIS using URL Rewrite

Obviously my workaround is to get everyone to go to the login page and start there rather than just the root URL, but I'd really like to get this sorted as if redirecting doesn't work here, I can see it not working elsewhere and potentially causing issues.

Update as requested: I don't actually have any control over my ELB as that's done by a different team, but my understanding from speaking to the team is that it accepts traffic as HTTPS and then passes it on to the server as HTTP.

1
Please update your question to include the configuration of your ELB listeners. It sounds like your ELB is configured to accept HTTPS (load balancer port), and pass traffic on to your server as HTTP (instance port), but would like to verify. You can view this from the AWS Web Console under EC2 > Load Balancing > Load Balancers. If not making the request as HTTPS is indeed the issue, this is also where you would be able to fix it.Anthony Neace
@AnthonyNeace updated - I'm pretty sure that you're correct and that's how it's set upalfredbulbasaur
In your web.config file, what is the loginUrl value in the forms element?Matt Houser
@MattHouser I don't have a forms element in my web.config - I have <authentication mode="None" />, which I believe was from the original ASP.NET MVC templatealfredbulbasaur
Then what is in your MVC application that's enforcing the sign-in redirect? There's something in your MVC app that's (a) requiring DashboardController to require authorization, and (b) what page to redirect to to get the user to sign-in.Matt Houser

1 Answers

3
votes

Your MVC application is configured to redirect to an absolute http URL rather than a relative URL when the user needs to sign-in.

For new MVC applications that are based on the Owin middleware, this is configured in App_Start/Startup.Auth.cs.

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        // Enables the application to validate the security stamp when the user logs in.
        // This is a security feature which is used when you change a password or add an external login to your account.  
        OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
            validateInterval: TimeSpan.FromMinutes(30),
            regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
    }
});

and add the following after the OnValidateIdentity property:

OnApplyRedirect = ApplyRedirect  

Then, later in the class, add the following function:

private static void ApplyRedirect(CookieApplyRedirectContext context)
{
    Uri absoluteUri;
    if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri))
    {
        context.Response.Redirect(absoluteUri.PathAndQuery);
        return;
    }

    context.Response.Redirect(context.RedirectUri);
}

Basically, this is converting the absolute URL to a relative URL. The relative URL then is passed back to the browser. Since the redirect is relative, it should maintain the https URL.