1

We want to use https only when strictly required. Why after calling an action like below it remains enabled forever?

    [RequireHttps]
    public ActionResult LogIn()
    {
        if(Request.IsAuthenticated)
            return RedirectToAction("Index", "Account");

        return View();
    }

What can we do to disable it when not needed?

Thanks.

abenci
  • 8,422
  • 19
  • 69
  • 134
  • 2
    Why do you think it's not needed? Your login cookie is just as secret as your username + password, and now you’re sending it in cleartext across the wire. Besides, you’ve already taken the time to perform the handshake and secure the channel (which is the bulk of what makes HTTPS slower than HTTP) before the MVC pipeline is run, so [RequireHttp] won’t make the current request or future requests much faster. – RickAndMSFT Mar 16 '12 at 00:26
  • I wanted to turn off it because we also host some youtube movies on the same page and IE all the times says: "Only secure content is displayed" and blocks the youtube movies... – abenci Mar 16 '12 at 07:38
  • So change your embedding to https www.youtube.com – RickAndMSFT Mar 18 '12 at 18:36
  • I don't think is possible because depending on the fact the user is logged in or not, I need to embed via http or https... – abenci Mar 20 '12 at 05:20
  • 2
    If you drop down to HTTP from HTTPS without properly signing out (see http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx ) your username + password is open for all to see. – RickAndMSFT Mar 22 '12 at 17:44

2 Answers2

11

The [RequireHttps] attribute can be used on a controller type or action method to say "this can be accessed only via SSL." Non-SSL requests to the controller or action will be redirected to the SSL version (if an HTTP GET) or rejected (if an HTTP POST). You can override the RequireHttpsAttribute and change this behavior if you wish. There's no [RequireHttp] attribute built-in that does the opposite, but you could easily make your own if you desired.

There are also overloads of Html.ActionLink() which take a protocol parameter; you can explicitly specify "http" or "https" as the protocol. Here's the MSDN documentation on one such overload. If you don't specify a protocol or if you call an overload which doesn't have a protocol parameter, it's assumed you wanted the link to have the same protocol as the current request.

The reason we don’t have a [RequireHttp] attribute in MVC is that there’s not really much benefit to it. It’s not as interesting as [RequireHttps], and it encourages users to do the wrong thing. For example, many web sites log in via SSL and redirect back to HTTP after you’re logged in, which is absolutely the wrong thing to do. Your login cookie is just as secret as your username + password, and now you’re sending it in cleartext across the wire. Besides, you’ve already taken the time to perform the handshake and secure the channel (which is the bulk of what makes HTTPS slower than HTTP) before the MVC pipeline is run, so [RequireHttp] won’t make the current request or future requests much faster.

If you're hosting utube, change your embedding to use HTTPS rather than HTTP If you drop down to HTTP from HTTPS without correctly signing out (see http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx ) your username + password is wide open. It's not enough to call SignOut.

RickAndMSFT
  • 20,912
  • 8
  • 60
  • 78
  • 1
    Rick, your comment makes lots of sense. I also read the link to SignOut. If I go to sites like Amazon and Newegg I noticed that they switch between HTTP and HTTPS when I am logged in depending the pages I visit. Is this a security vulnerability or are they using other techniques? Do they do this to improve performance? How bad can be the impact of using HTTPS for pages? – tmorell Sep 01 '13 at 23:27
4

I use this action filter that redirects back to http when the https action is completed:

using System.Web.Mvc;
using System;
public class ExitHttpsIfNotRequiredAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        // abort if it's not a secure connection
        if (!filterContext.HttpContext.Request.IsSecureConnection) return;

        // abort if a [RequireHttps] attribute is applied to controller or action
        if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), true).Length > 0) return;

        // abort if a [RetainHttps] attribute is applied to controller or action
        if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;
        if (filterContext.ActionDescriptor.GetCustomAttributes(typeof(RetainHttpsAttribute), true).Length > 0) return;

        // abort if it's not a GET request - we don't want to be redirecting on a form post
        if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) return;

        // redirect to HTTP
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }
}
David Aleu
  • 3,922
  • 3
  • 27
  • 48