I have an ASP.NET MVC web app which is utilizing claims-based authorization via WIF and Thinktecture.IdentityModel. However, rather than just intercepting the unauthorized request, I'd like to trim my navigation menus to only display the links accessible to the current user.
My initial thoughts are to accept a list of actions (ActionResult, ActionLink, route value dictionary, not quite sure yet) and execute my custom ClaimsAuthorizationManger.CheckAccess routine. In order to do this, I need to generate an AuthorizationContext, however, I'm not sure if the framework utilities (or preferably abstractions) creating the context are accessible. Anyone know if this possible? Or, if I'm going about this all wrong, what do you suggest?
Thanks and happy holidays!
As indicated by Dominick Baier, I was able to create a nice solution using
Thinktecture.IdentityModel. I've posted the code in a Gist. This specific functionality seems to be undocumented but I was able to piece together little bits and pieces from related blog posts and documentation. I'd appreciate any feedback as I'm sure there is some corner of IdentityModel or WIF that could alleviate come of my code. That said, this is working well as is. Let's start with an example usage:Razor
As depicted below, the
BuildNavigationhelper function will render a<ul>containing all the navigation items for which the user is authorized to view. In case you're wondering about theMVC.{Area}.{Controller}.{Action}()statements, those are T4MVC helpers. It is not necessary to use T4MVC. TheNavigationItemprovides an override accepting anActionResultfor convenience. In actuality, theNavigationItemonly consists of astringto display and aRouteValueDictionary(see the Gist).HTML Helper Extensions
In order to utilize the existing authorization utilities provided by Thinktecture.IdentityModel, you have to create a
RequestContext. Notice we build theRouteDatafrom theRouteValueDictionaryand then create a newRequestContextfor the authorization helper. Once important side note: if you're making use of Areas in your MVC project, as I am, theAddNamespaceInfofunction is paramount. If you have duplicated controller names in separate areas, this is how the controller factory will know how to access the correct one. Otherwise, you'll receive an exception.Thinktecture.IdentityModel ClaimsAuthorizeAttribute Wrapper
Another stumbling block I encountered was the closed nature of the
ClaimsAuthorizeAttribute. This is one area that I suspect may be eliminated by a deeper understanding of WIF. However, for the time, I've created a wrapper around theClaimsAuthorizeAttributewhich allows me to convert the attribute into claims.Claims Authorization Helper
Finally, here is the
ClaimsAuthorizationHelperwhich is responsible for resolving the necessary controller and action method, retrieving the resource claims, and calling into theClaimsAuthorizationutility provided by Thinktecture IdentityModel.Other Code
There are some other helpers and classes which have been omitted for brevity. Please see the Gist for the full code.