Note that there are some explanatory texts on larger screens.

plurals
  1. POMVC 5.0 [AllowAnonymous] and the new IAuthenticationFilter
    primarykey
    data
    text
    <p>When I create a new asp.net mvc 4.0 application, one of the <strong>first thing I do</strong>, is create and set a custom authorize <code>global filter</code> like so:</p> <pre><code>//FilterConfig.cs public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); filters.Add(new CustomAuthorizationAttribute()); } </code></pre> <p>Then I create the <code>CustomAuthorizationAttribute</code> like so:</p> <pre><code>//CustomAuthorizationAttribute.cs protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { //Handle AJAX requests filterContext.HttpContext.Response.StatusCode = 403; filterContext.Result = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { //Handle regular requests base.HandleUnauthorizedRequest(filterContext); //let FormsAuthentication make the redirect based on the loginUrl defined in the web.config (if any) } } </code></pre> <p>I have two controllers: <code>HomeController</code> and <code>SecureController</code></p> <p>The HomeController is decorated with the <code>[AllowAnonymous]</code> attribute.</p> <p>The SecureController is <strong>NOT</strong> decorated with the <code>[AllowAnonymous]</code> attribute.</p> <p>The <code>Index() ActionResult</code> of the <code>HomeController</code> displays a View with a simple button.</p> <p>When I click the button, I make an ajax call to a GetData() method that lives inside the <code>SecureController</code> like so:</p> <pre><code>$("#btnButton").click(function () { $.ajax({ url: '@Url.Action("GetData", "Secure")', type: 'get', data: {param: "test"}, success: function (data, textStatus, xhr) { console.log("SUCCESS GET"); } }); }); </code></pre> <p>Needless to say, when I click the button, I trigger the <code>CustomAuthorizationAttribute</code> because it is a global filter but also because the <code>SecureController</code> is NOT decorated with the <code>[AllowAnonymous]</code> attribute.</p> <p>Ok, I’m done with my introduction...</p> <p>With the introduction of <code>asp.net mvc 5.0</code>, we are now introduced to a new <code>authentication filter</code> which happens to get triggered <strong>before</strong> the authorization filter (which is great and gives us more granular control on how I can differentiate a user that is NOT authenticated (http 401) from a user that IS authenticated and who happens to NOT be authorized (http 403)).</p> <p>In order to give this new <code>authentication filter</code> a try, I’ve created a new asp.net mvc 5.0 (VS Express 2013 for Web) and started by doing the following: </p> <pre><code>public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //filters.Add(new HandleErrorAttribute()); filters.Add(new CustomAuthenticationAttribute()); //Notice I'm using the word Authentication and not Authorization } </code></pre> <p>Then the attribute:</p> <pre><code>public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter { public void OnAuthentication(AuthenticationContext filterContext) { } public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext) { var user = filterContext.HttpContext.User; if (user == null || !user.Identity.IsAuthenticated) { filterContext.Result = new HttpUnauthorizedResult(); } } } </code></pre> <p>I’ve created a <code>HomeController</code>. The <code>HomeController</code> is decorated with the <code>[AllowAnonymous]</code> attribute.</p> <p>Before launching the application from VS 2013, I’ve set two break points inside both methods of my CustomAuthenticationAttribute (<code>OnAuthentication</code> and <code>OnAuthenticationChallenge</code>).</p> <p>When I launch the application, I hit the first break point(<code>OnAuthentication</code>). Then, to my surprise, the code within the <code>Index() ActionResult</code> of my <code>HomeController</code> <strong>gets executed</strong> and only after I return the View() do I hit the break point on the <code>OnAuthenticationChallenge()</code> method.</p> <p><strong>Questions:</strong> I have two questions.</p> <p>Question 1)<br> I was under the impression that the <code>[AllowAnonymous]</code> attribute would <strong>automagically</strong> bypass any code within my <code>CustomAuthenticationAttribute</code> but I was wrong! Do I need to manually <strong>check</strong> for the existence of the <code>[AllowAnonymous]</code> attribute and skip any code?</p> <p>Question 2) Why is the code inside my <code>Index()</code> method of my <code>HomeController</code> gets executed <strong>after</strong> the <code>OnAuthentication</code>? Only to realize that after I return View() do the code inside the <code>OnAuthenticationChallenge()</code> gets executed?</p> <p>My concern is that I do not want the code from the <code>Index()</code> method to get executed if the user is NOT authenticated.</p> <p>Perhaps I’m looking at this the wrong way.</p> <p>If anyone can help me shed some light on this, that’d be great!</p> <p>Sincerely Vince</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload