Bit lost on first custom Authorization Attributehttp://forums.asp.net/t/1531406.aspx/1?Bit+lost+on+first+custom+Authorization+AttributeTue, 02 Mar 2010 16:30:29 -050015314063708234http://forums.asp.net/p/1531406/3708234.aspx/1?Bit+lost+on+first+custom+Authorization+AttributeBit lost on first custom Authorization Attribute <p>I want to create a single custom authorization attribute to be added to controller actions that require authenticated users.</p> <p>My first shot at this, so I may have it all wrong<br> </p> <p>Got 3 Roles which corresponds to 3 Areas in my application (Client app, so I'll just call them RoleOne, RoleTwo, RoleThree and AreaOne, AreaTwo, AreaThree).</p> <p>Each area have similiar (to a point) views and actions, like Sign Up, Area specific home, etc. </p> <p>In the attribute I want to determine the current area, controller and action.&nbsp; Then I just add code like:</p> <ul> <li>If not logged in, and in AreaOne, go to AreaOne Signup (etc)</li><li>If logged in as RoleOne, and AreaOne Home is requested, go there, but if AreaTwo Home is requested ,go to AreaTwo Signup</li></ul> <p>So in my attribute class I need to determine the current area, controller and action, and see what kind of user we have logged in (if any)</p> <p>Using ActionExecutingContext it seems I can determine the contoller and action method names, however I cannot find the Area name, and altered the attribute to be called like this:<pre class="prettyprint">public string Area { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { HttpContext ctx = HttpContext.Current; if(ctx.Request.IsAuthenticated) { var user = ctx.User.Identity.Name; if(ctx.User.IsInRole(Area)) { // all fine....just get out? } else { // redirect to the signup action for this area } } else { // redirect user to signup action for this area } base.OnActionExecuting(filterContext); }</pre><br> </p> 2010-03-02T04:57:31-05:003708296http://forums.asp.net/p/1531406/3708296.aspx/1?Re+Bit+lost+on+first+custom+Authorization+AttributeRe: Bit lost on first custom Authorization Attribute <p>Made the above code a bit simpler (and yes, it does the job for now).</p> <p>Note I compare the current user name with the area name, as I'm using a mocked role provider for now.&nbsp; (will change to IsInRole() later)<pre class="prettyprint">public string Area { get; set; } // If the user is not logged in with a role matching the area's name, redirect to the signup for that area public override void OnActionExecuting(ActionExecutingContext filterContext) { if (HttpContext.Current.User.Identity.Name != Area.ToString()) HttpContext.Current.Response.Redirect(&quot;~/&quot; &#43; Area &#43; &quot;/Signup/&quot;); base.OnActionExecuting(filterContext); }</pre><br> </p> 2010-03-02T05:33:57-05:003708509http://forums.asp.net/p/1531406/3708509.aspx/1?Re+Bit+lost+on+first+custom+Authorization+AttributeRe: Bit lost on first custom Authorization Attribute <p>Please note - authorization or other security decisions must <b><span style="color:rgb(255,0,0)"><span style="font-size:medium">never </span></span></b>be made based on the current area, e.g. examining the current route to determine which area the current request belongs to. &nbsp;The only supported way of accomplishing this is to put an [Authorize] or other similar filter <i>which doesn't depend on the current area</i> on a base controller, then making sure that each controller within an area subclasses that base controller.</p> <p>Your first code sample is vulnerable because it tries to get information (like the area name) from the route servicing the request. &nbsp;This makes the route itself responsible for the security decision, which is a Very Bad Thing since Routing can be bypassed.</p> <p>Your second code sample should be fine because you've statically included the name as part of the attribute, so what you're doing is really no different than [Authorize] with a custom redirect URL.</p> <p>Subtle but important difference. :)</p> 2010-03-02T07:24:55-05:003708586http://forums.asp.net/p/1531406/3708586.aspx/1?Re+Bit+lost+on+first+custom+Authorization+AttributeRe: Bit lost on first custom Authorization Attribute <p>Thanks for the answer Levi.</p> <p>Lucky for me, this is just a temporary solution (I'm &quot;only&quot; working on views and routes at this stage).&nbsp; (Converting the static html prototype/design to views, leaving the logic for either later or other team members)</p> <p>If you know about some usefull links on this topic, please share!</p> <p><br> </p> <p>Thanks again.&nbsp; :-)<br> </p> 2010-03-02T08:01:22-05:003709604http://forums.asp.net/p/1531406/3709604.aspx/1?Re+Bit+lost+on+first+custom+Authorization+AttributeRe: Bit lost on first custom Authorization Attribute <p>The best and safest thing for you to do would be to subclass AuthorizeAttribute and override only the HandleUnauthorizedRequest method. &nbsp;Then you could attribute your methods like so:</p> <p>[MyCustomAuthorization(Roles = &quot;some_role[, some_other_role[, ...]]&quot;)]</p> <p>Don't override any other method as the default logic should suffice in your case. &nbsp;(The default logic handles things like the IsInRole() check, suppressing output caching, etc.) &nbsp;Then from the HandleUnauthorizedAttribute method, set filterContext.Result = new RedirectResult(&quot;url_to_redirect_to&quot;).</p> <p>Good luck. :)</p> 2010-03-02T16:30:29-05:00