Require SSL in WebApi?

.NetSslasp.net Web-Api

.Net Problem Overview


Is there a way to require SSL for WebApi? An attribute?

I don't see an applicable attribute under System.Web.Http, something like the RequireHttps attribute we have for MVC. I'm just trying to avoid rolling my own attribute/ message handler if there is a built in solution.

.Net Solutions


Solution 1 - .Net

public class RequireHttpsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
        }
    }
}

Solution 2 - .Net

You can use the RequireHttpsHandler from WebAPIContrib project. Basically, all it does is to check the incoming request URI scheme:

if (request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
  // Forbidden (or do a redirect)...
}

Alternately, Carlos Figueira has another implementation on his MSDN blog.

Solution 3 - .Net

It is puzzling that there is no equivalent to the ASP.NET MVC RequireHttps attribute in ASP.NET Web API. However you can easily create one based on RequireHttps from MVC.

using System;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

...

public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if (actionContext == null)
        {
            throw new ArgumentNullException("actionContext");
        }

        if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            HandleNonHttpsRequest(actionContext);
        }
        else
        {
            base.OnAuthorization(actionContext);
        }
    }

    protected virtual void HandleNonHttpsRequest(HttpActionContext actionContext)
    {
        actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
        actionContext.Response.ReasonPhrase = "SSL Required";
    }
}

All that there is left to do is to argue about how much redundant code there is.

Solution 4 - .Net

you can use the following filter class to force your action method to use SSL, this will handle your request wither its a GET method or any other verb, if its a get method it will redirect the browser (using the location header) to the new URI. Otherwise a message will be shown to use https

Below code shows that you have to override OnAuthorization method after inheriting from AuthorizationFilterAttribute.

        string _HtmlBody = string.Empty;
        UriBuilder httpsNewUri;

        var _Request = actionContext.Request;

        if (_Request.RequestUri.Scheme != Uri.UriSchemeHttps )
        {

            _HtmlBody = "<p>Https is required</p>";

            if (_Request.Method.Method == "GET"){

                actionContext.Response = _Request.CreateResponse(HttpStatusCode.Found);
                actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html");

                httpsNewUri = new UriBuilder(_Request.RequestUri);
                httpsNewUri.Scheme = Uri.UriSchemeHttps;
                httpsNewUri.Port = 443;

                //To ask a web browser to load a different web page with the same URI but different scheme and port
                actionContext.Response.Headers.Location = httpsNewUri.Uri;

            
            }else{

                actionContext.Response = _Request.CreateResponse(HttpStatusCode.NotFound);
                actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html");
            
            }
}

Solution 5 - .Net

You can use the following code; (automatically redirect to https) redirect to https when an http based request is made.

To check it in visual studio you need to enable ssl in visual studio. This can be done using enable ssl property to true.

public class RequireHttpsAttribute: AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if(actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            // constructing the https url
            var uriBuilder = new UriBuilder(actionContext.Request.RequestUri)
            {
                Scheme = Uri.UriSchemeHttps,
                Port = 44353 // port used in visual studio for this 
            };

            actionContext.Response.Headers.Location = uriBuilder.Uri;
        }
    }
}

Use this in Register method like this

config.Filters.Add(new RequireHttpsAttribute());

Solution 6 - .Net

After some research I determined this is probably the most appropriate response. It could be updated to provide json, text, or xml despite the specification indicating Html is recommended.

public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
    public override void OnAuthorization(HttpActionContext context)
    {
        if (context.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
        {
            context.Response = new HttpResponseMessage(HttpStatusCode.UpgradeRequired);
            context.Response.Headers.Add("Upgrade", "TLS/1.1, HTTP/1.1");
            context.Response.Headers.Add("Connection", "Upgrade");
            context.Response.Headers.Remove("Content-Type");
            context.Response.Headers.Add("Content-Type", "text/html");
            context.Response.Content = new StringContent("<html><head></head><body><h1>Http protocol is not valid for this service call.</h1><h3>Please use the secure protocol https.</h3></body></html>");
        }
        else base.OnAuthorization(context);
    }
}

Here is the specification: [RFC 2817][1]

[1]: https://www.rfc-editor.org/rfc/rfc2817#section-4.2 "RFC 2817"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEBarrView Question on Stackoverflow
Solution 1 - .NetThe LightView Answer on Stackoverflow
Solution 2 - .NetTeoman SoygulView Answer on Stackoverflow
Solution 3 - .NetAdrian TomanView Answer on Stackoverflow
Solution 4 - .NetAmjad HusseiniView Answer on Stackoverflow
Solution 5 - .NetNayas SubramanianView Answer on Stackoverflow
Solution 6 - .NetN-ateView Answer on Stackoverflow