Is this a good approach?
Not really, its not the authentication mechanism you want to prevent, you are likely to want to restrict access to just your MVC front end, the razor templates. You could use a custom filter similar to how it is explained in this response to ASP.NET MVC preventing users from direct URL except your filter should check that Request.Url.Host is in your list of known endpoints.
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace Customer.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class PreventFromUrl : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// MVC requests will originate from the same host as the server
// external apps may not have a referrer or it will be from a different domain
// If you have your own non-mvc code, in the same domain, we trust you know what you're doing :)
if (filterContext.HttpContext.Request.UrlReferrer == null
|| filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
{
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
}
}
}
If a Filter does not work, consider moving your Web API to a separate project, but be aware that this is really just a security by obscurity measure, it is still possible to use cookie based authentication to obtain access to your MVC endpoints once the caller has authenticated.
Using the authentication type alone does not provide any additional security benefits, you are just saying that each route requires specific way to authenticate, you are not doing anything to deny access itself.
You are expecting all non-MVC traffic to use OAuth, but because your site supports cookies, external apps could still programmatically and legitimately use cookie based authentication and gain access to your MVC controller endpoints.
is it important to deny access to your MVC controllers?
Your application logic should always be written with security in mind, your server-side controllers should not rely on the front end to validate and sanitise user inputs, any business rules and validation expressed in the user interface should also be evaluated in the controller logic.
Perform and design validation and business rules in the back-end first, in your controllers.
Because front end scripts are executed on the client they are therefor in a much more vulnerable state. It is trivial to capture and monitor the traffic that the front end sends back to the client, there for it you can work around client-side validations by manipulating the data before sending it back to the server.
Or worse, evolving client technologies might create scenarios where your client-side scripts and logic do not evaluate the way you originally expected, accidentally allowing un-sanitised or invalid data to flow through.
When the controller performs all business rule validation, as we are conditioned to do in Web API, then in general it should not really matter if the end client is your expected MVC client or something custom written. Even if someone wrote an app to automate or impersonate a valid user, If the caller has legitimately authenticated, let them in, because they could otherwise login directly through the MVC site manually or through the API.
It is pretty easy in MVC apps to put validation in the user interface level and to skip performing the same checks in the server-side, in this scenario, or when your MVC app exposes more data than you want to allow external clients to access it can become important to deny access to these MVC routes for non-mvc callers.
In general, supporting multiple authentication mechanisms is a good approach for an API because it broadens the options that clients can use to interact with the API. So supporting multiple types of auth to access the WebAPI routes IS a good approach.
This scenario makes it easy for your front end to access data through both the MVC controllers and the WebAPI. A common scenario that I encounter is when we use the API to secure access to external files and images. we can put the URL for the resource endpoint directly into and use the auth cookie that is already in the user's browser to access through the API.
Supporting Mutliple Authentication Mechanisms or Providers will increase the attack surface of your API. This not necessarily a bad thing, but it is something to be aware of and to audit.
Increased attack surface does not automatically mean that the service is more vulnerable, but it does mean that there are more points of potential failure in your authentication.