I was looking for an implementation / example of loading and authorizing a resource at a controller level. I am looking for the same functionality as load_and_authorize_resource in the cancan gem in ruby on rails.
Has anyone come across one / have an example how to implement something similar using Mvc .Net attributes?
Thanks!
The load_and_authorize_resource behaviour
With rails, controller and model names are linked up by convention. The attribute load_and_authorize_resource takes that to its advantage. When an action is hit that requires an instance of a resource, the load_and_authorize_resource verifies whether the instance of the resource can be accessed. If it can, it will load it up in an instance variable, if it cant, it will return a 404 or any error behaviour you have configured the attribute to produce.
For example, if I have a resource picture, and only user that own a certain picture can edit the picture's name.
So we would have a Edit action, which obviously would have a pictureId of the picture you want to edit. load_and_authorize_resource would verify whether the current context/user has access to the resource.
Here is a small video introduction of the module.
I am not aware of the existence of such plugin for ASP.NET MVC. To mimic it's functionality you could write a custom Authorize attribute though:
public class LoadAndAuthorizeResourceAttribute : AuthorizeAttribute
{
private class ModelDescriptor
{
public string Name { get; set; }
public Type ModelType { get; set; }
}
private const string ModelTypeKey = "__ModelTypeKey__";
public override void OnAuthorization(AuthorizationContext filterContext)
{
var parameters = filterContext.ActionDescriptor.GetParameters();
if (parameters.Length > 0)
{
// store the type of the action parameter so that we could access it later
// in the AuthorizeCore method
filterContext.HttpContext.Items[ModelTypeKey] = new ModelDescriptor
{
Name = parameters[0].ParameterName,
ModelType = parameters[0].ParameterType,
};
}
base.OnAuthorization(filterContext);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
// the user is not authenticated or authorized => no need to continue
return false;
}
// get the currently authenticated username
string username = httpContext.User.Identity.Name;
// get the id of the resource that he is trying to manipulate
// the id should be sent either as part of the query string or the routes
string id = httpContext.Request.RequestContext.RouteData.Values["id"] as string;
// get the action param type
var modelDescriptor = httpContext.Items[ModelTypeKey] as ModelDescriptor;
if (modelDescriptor == null)
{
throw new InvalidOperationException("The controller action that was decorated with this attribute must take a model as argument");
}
// now load the corresponding entity from your database given the
// username, id and type
object model = LoadModel(id, username, modelDescriptor.ModelType);
if (model == null)
{
// the model that satisfies the given criteria was not found in the database
return false;
}
httpContext.Request.RequestContext.RouteData.Values[modelDescriptor.Name] = model;
return true;
}
private object LoadModel(string id, string username, Type modelType)
{
// TODO: depending on how you are querying your database
// you should load the corresponding model here or return null
// if not found
throw new NotImplementedException();
}
}
and now you could have a controller action that is decorated with this attribute:
[LoadAndAuthorizeResource]
public ActionResult Edit(Picture model)
{
... if we get that far the user is authorized to modify this model
}
Related
I have just created a custom Authorize method so that a User on the website I am building, is only able to see his/her view.
public class UserAuthorize : AuthorizeAttribute
{
public string Username { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
string username = httpContext.User.Identity.Name;
if(new RolesBL().IsUserInRole(username, 1))//1 is Admin
{
return true;
}
return Username.Equals(username);
}
}
I am having trouble passing through the data from the controller to this method
[UserAuthorize(Username = username)]
public ActionResult Details(string username)
{
User u = new UsersBL().GetUser(username);
return View(u);
}
How can I pass the username in the View's parameter to the Authorize method as well.
Thanks and Regards
This is not a case where using authorization makes sense. You should instead prevent the user from being able to pass in an argument to override the user that they are logged in as.
public ActionResult Details()
{
User u = new UsersBL().GetUser(this.User.Identity.Name);
return View(u);
}
Your query then acts as a filter to ensure only the logged in user's information is seen.
If you need a super user to be able to view/edit each user, then you would need to use a role to ensure that only users in that role can edit other users. But in that case, the standard AuthorizeAttribute will suffice.
public ActionResult Details()
{
User u = new UsersBL().GetUser(this.User.Identity.Name);
return View(u);
}
[Authorize(Roles = "SuperUser")]
public ActionResult Details(string username)
{
User u = new UsersBL().GetUser(username);
return View(u);
}
The arguments in an [Attribute] declaration are all defined at compile-time, and must therefore be constants. You can't "pass in" the run-time value of an action parameter.
Besides which, the attribute will be used prior to the action method being invoked (to determine whether the action can be invoked) - and so that parameter won't even be instantiated.
You might however be able to access the username value within the UserAuthorize attribute implementation, since the httpContext parameter gives you access to the request details, which presumably contains the user name as part of the query string.
Using ASP.NET MVC 5 and Entity Framework. How can I secure my application so I cant access other users data?
To do CRUD stuff I have index, create, edit, delete methods in FooController so I can use:
/Foo/
to view my information I click one and get
/Foo/Details/5
When I type in 3 in the browser I get someone else's information.
/Foo/Details/3
How can I secure this from being accessed everywhere? I use Owin Identity and are logged into the application.
You could write a custom authorization filter by deriving from the AuthorizeAttribute class and inside you could check whether the currently authenticated user has access to the requested resource.
For example:
public class MyAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
string id = httpContext.Request["id"];
string currentUser = httpContext.User.Identity.Name;
return HasAccessToResource(id, currentUser);
}
private bool HasAccessToResource(string id, string currentUser)
{
// You know what to do here => check in your backend whether the
// current user is authorized to access the specified resource id
throw new NotImplementedException();
}
}
and then decorate your controllers/actions with this custom attribute:
[MyAuthorize]
public ActionResult Delete(string id)
{
// if you get that far, the current user is owner of the requested resource
...
}
I am designing an MVC 3 application where multiple tenants reside in a single database.
What is the best way to prevent users from editing/viewing other tenants data in MVC? (i.e. someone could type in '/People/Edit/1' and edit the person with Id of 1- regardless of wether they are part of the tenants data or not).
I know I can override 'OnActionExecuting(ActionExecutingContext filterContext)' for each controller- but it sounds crazy to have to handle each action seperately, get the ID or OBJECT depending on if its a POST or GET and then check if the operation is allowed.
Any better ideas?
Also, I do not want to go down the route of creating a different database or schema for each tenant.
Thanks in advance.
Instead of passing ids to your controller actions write a custom model binder for your entities which will fetch it from the database. So for example let's assume that you have the following model:
public class Person
{
public string Id { get; set; }
... some other properties
}
Now instead of having:
[HttpPost]
public ActionResult Edit(string id)
{
...
}
write:
[HttpPost]
public ActionResult Edit(Person person)
{
...
}
and then write a custom model binder for Person:
public class PersonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var id = bindingContext.ValueProvider.GetValue("id");
// check if an id was provided and if the user is authenticated
if (!controllerContext.HttpContext.User.Identity.IsAuthenticated || id == null)
{
throw new HttpException(403, "Forbidden");
}
var currentUser = controllerContext.HttpContext.User.Identity.Name;
// fetch the person from your repository given the id and belonging
// to the currently authenticated user
var person = _repository.GetPerson(id.AttemptedValue, currentUser);
if (person == null)
{
// no person found matching
throw new HttpException(403, "Forbidden");
}
return person;
}
}
which you would register in Application_Start:
ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());
Original answer
To solve the problem quickly use guids instead of a auto-increasing integer. However this is just delaying the problem.
One of the things you can do is to role your own authorize attribuut http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx Or you can chose to create a global actionfilter. http://www.asp.net/mvc/tutorials/understanding-action-filters-cs
Addition information on how you could do it based on request in comment
public class MySuperFilter : ActionFilterAttribute
{
//Called by the MVC framework before the action method executes.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
String user = filterContext.HttpContext.User.Identity.Name;
int id = int.Parse(filterContext.RouteData.GetRequiredString("Id"));
if (!IsValidUser(user,id))
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary {{ "Controller", "YourController" },
{ "Action", "YourAction" } });
}
base.OnActionExecuting(filterContext);
}
private bool IsValidUser(string user,int id)
{
//Check if the user has acces to the page
return true;
}
}
It's a non-elegant solution but depending on scope it could be easiest. Having designed a similar system that has relatively few points of entry for multiple tenants data we just merely check that the CurrentUser is the Owner of the object that is being queried. Our use objects a common base interface that has the owner field so the check is made not carrying about the specific object but just from the interface. If there's a mismatch we throw a security exception and log that a user is probably playing around the query string seeing if they get our website to leak data the way many production websites do.
In other words, is this a really stupid idea?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// get the area, controller and action
var area = filterContext.RouteData.Values["area"];
var controller = filterContext.RouteData.Values["controller"];
var action = filterContext.RouteData.Values["action"];
string verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}/{2}/{3}", area, controller, action, verb);
// set role name to area/controller/action name
this.Roles = roleName;
base.OnAuthorization(filterContext);
}
}
UPDATE
I'm trying to avoid the following, in a scenario where we have extremely granular role permissions because the roles are setup on a per-client basis and attached to user groups:
public partial class HomeController : Controller
{
[Authorize(Roles = "/supplierarea/homecontroller/indexaction/")]
public virtual ActionResult Index()
{
return View();
}
[Authorize(Roles = "/supplierarea/homecontroller/aboutaction/")]
public virtual ActionResult About()
{
return View();
}
}
Can anyone enlighten me to a secure way to write this AuthorizeRouteAttribute to access the route information and use this as the role name? As Levi says, the RouteData.Values isn't secure.
Is the use of the executing httpContext.Request.Path any more secure or better practice?
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
return;
}
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}", path, verb);
if (!filterContext.HttpContext.User.IsInRole(roleName))
{
// role auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
// P.S. I want to tell the logged in user they don't
// have access, not ask them to login. They are already
// logged in!
return;
}
//
base.OnAuthorization(filterContext);
}
This maybe illustrates the issue a little further:
enum Version
{
PathBasedRole,
InsecureButWorks,
SecureButMissingAreaName
}
string GetRoleName(AuthorizationContext filterContext, Version version)
{
//
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// recommended way to access controller and action names
var controller =
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action =
filterContext.ActionDescriptor.ActionName;
var area = "oh dear...."; // mmmm, where's thearea name???
//
var insecureArea = filterContext.RouteData.Values["area"];
var insecureController = filterContext.RouteData.Values["controller"];
var insecureAction = filterContext.RouteData.Values["action"];
string pathRoleName =
String.Format("{0}/{1}", path, verb);
string insecureRoleName =
String.Format("{0}/{1}/{2}/{3}",
insecureArea,
insecureController,
insecureAction,
verb);
string secureRoleName =
String.Format("{0}/{1}/{2}/{3}",
area,
controller,
action,
verb);
string roleName = String.Empty;
switch (version)
{
case Version.InsecureButWorks:
roleName = insecureRoleName;
break;
case Version.PathBasedRole:
roleName = pathRoleName;
break;
case Version.SecureButMissingAreaName:
// let's hope they don't choose this, because
// I have no idea what the area name is
roleName = secureRoleName;
break;
default:
roleName = String.Empty;
break;
}
return roleName;
}
Please do not do this.
If you really need to, you can use the Type of the controller or the MethodInfo of the action to make security decisions. But basing everything off of strings is asking for trouble. Remember, there's no guaranteed 1:1 mapping of Routing values to actual controller. If you're using the Routing tuple (a, b, c) to validate access to SomeController::SomeAction but somebody discovers that (a, b', c) also hits that same action, that person can bypass your security mechanisms.
Edit to respond to comments:
You have access to the controller's Type and the action's MethodInfo via the filterContext parameter's ActionDescriptor property. This is the only sure-fire way to determine what action will really execute when the MVC pipeline is processing, because it's possible that your lookup doesn't exactly match what's going on behind the scenes with MVC. Once you have the Type / MethodInfo / whatever, you can use whatever information you wish (such as their fully-qualified names) to make security decisions.
As a practical example, consider an area MyArea with a controller FooController and an action TheAction. Normally the way that you would hit this FooController::TheAction is via this URL:
/MyArea/Foo/TheAction
And Routing gives the tuple (Area = "MyArea", Controller = "Foo", Action = "TheAction").
However, you can also hit FooController::TheAction via this URL:
/Foo/TheAction
And Routing will give the tuple (Area = "", Controller = "Foo", Action = "TheAction"). Remember, areas are associated with routes, not controllers. And since a controller can be hit by multiple routes (if the definitions match), then a controller can also be logically associated with multiple areas. This is why we tell developers never to use routes (or areas or the <location> tag, by extension) to make security decisions.
Additionally, there's a bug in your class in that it's mutable (it mutates its own Roles property in OnAuthorization). Action filter attributes must be immutable, since they may be cached by parts of the pipeline and reused. Depending on where this attribute is declared in your application, this opens a timing attack, which a malicious site visitor could then exploit to grant himself access to any action he wishes.
For more info, see also my responses at:
Area level security for asp.net mvc
How to get currently executing area?
If you want to do this, taking Levi's recommendation into account, the answer is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
namespace MvcApplication1.Extension.Attribute
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : AuthorizeAttribute
{
/// <summary>
/// Called when a process requests authorization.
/// </summary>
/// <param name="filterContext">The filter context, which encapsulates information for using <see cref="T:System.Web.Mvc.AuthorizeAttribute"/>.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="filterContext"/> parameter is null.</exception>
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
return;
}
// these values combined are our roleName
string roleName = GetRoleName(filterContext);
if (!filterContext.HttpContext.User.IsInRole(roleName))
{
filterContext.Controller.TempData.Add("RedirectReason", "You are not authorized to access this page.");
filterContext.Result = new RedirectResult("~/Error/Unauthorized");
return;
}
//
base.OnAuthorization(filterContext);
}
/// <summary>
/// Gets the name of the role. Theorectical construct that illustrates a problem with the
/// area name. RouteData is apparently insecure, but the area name is available there.
/// </summary>
/// <param name="filterContext">The filter context.</param>
/// <param name="version">The version.</param>
/// <returns></returns>
string GetRoleName(AuthorizationContext filterContext)
{
//
var verb = filterContext.HttpContext.Request.HttpMethod;
// recommended way to access controller and action names
var controllerFullName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerType.FullName;
var actionName = filterContext.ActionDescriptor.ActionName;
return String.Format("{0}.{1}-{2}", controllerFullName, actionName, verb);
}
}
}
I did not want to provide a HttpUnauthorizedResult in the case of a user not being in role, because the result is to send the user to the login page. Considering that they are already logged in, this is extremely confusing to the user.
This is a short notice! Be sure to use filterContext.RouteData.DataTokens["area"];
instead of filterContext.RouteData.Values["area"];
Good Luck.
So I was reading another question regarding login loop when you have a user logging in, set to return to a URL which they might not have access to after logging in (ie. an admin page, and the user logs in with a normal account).
The solution under WebForms seems to be to utilize the UrlAuthorizationModule.CheckUrlAccessForPrincipal method. However that does not work for URLs going to Action Methods secured with the Authorize Attribute. I figured I could work out which method the URL was pointing at and reflect over it to solve my problem - but I can't seem to work out how I get this information out of the routing table.
Anyone ever worked with this, or have a solution for this? If I can just get hold of the route information from a URL I think I could work the rest out, but if anyone has a generic solution - ie. some hidden method akin to the before mentioned one for MVC, then that would be totally awesome as well.
I'm not asking how to check if the User has acces to a specified Controller/Action pair. I first and foremost need to work out how to get the Controller/Action pair from the RouteTable based off the URL. The reason for all the background story, is in case that there does indeed exist an equivalent to UrlAuthorizationModule.CheckUrlAccessForPrincipal for MVC.
John Farrell (jfar)'s answer (SecurityTrimmingExtensions class) updated for MVC 4:
public static class SecurityCheck
{
public static bool ActionIsAuthorized(string actionName, string controllerName)
{
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
ControllerBase controller = factory.CreateController(HttpContext.Current.Request.RequestContext, controllerName) as ControllerBase;
var controllerContext = new ControllerContext(HttpContext.Current.Request.RequestContext, controller);
var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
foreach (var authAttribute in actionDescriptor.GetFilterAttributes(true).Where(a => a is AuthorizeAttribute).Select(a => a as AuthorizeAttribute))
{
authAttribute.OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
}
I ported and hacked this code from the MvcSitemap:
public static class SecurityTrimmingExtensions
{
/// <summary>
/// Returns true if a specific controller action exists and
/// the user has the ability to access it.
/// </summary>
/// <param name="htmlHelper"></param>
/// <param name="actionName"></param>
/// <param name="controllerName"></param>
/// <returns></returns>
public static bool HasActionPermission( this HtmlHelper htmlHelper, string actionName, string controllerName )
{
//if the controller name is empty the ASP.NET convention is:
//"we are linking to a different controller
ControllerBase controllerToLinkTo = string.IsNullOrEmpty(controllerName)
? htmlHelper.ViewContext.Controller
: GetControllerByName(htmlHelper, controllerName);
var controllerContext = new ControllerContext(htmlHelper.ViewContext.RequestContext, controllerToLinkTo);
var controllerDescriptor = new ReflectedControllerDescriptor(controllerToLinkTo.GetType());
var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
return ActionIsAuthorized(controllerContext, actionDescriptor);
}
private static bool ActionIsAuthorized(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (actionDescriptor == null)
return false; // action does not exist so say yes - should we authorise this?!
AuthorizationContext authContext = new AuthorizationContext(controllerContext);
// run each auth filter until on fails
// performance could be improved by some caching
foreach (IAuthorizationFilter authFilter in actionDescriptor.GetFilters().AuthorizationFilters)
{
authFilter.OnAuthorization(authContext);
if (authContext.Result != null)
return false;
}
return true;
}
private static ControllerBase GetControllerByName(HtmlHelper helper, string controllerName)
{
// Instantiate the controller and call Execute
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
IController controller = factory.CreateController(helper.ViewContext.RequestContext, controllerName);
if (controller == null)
{
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentUICulture,
"Controller factory {0} controller {1} returned null",
factory.GetType(),
controllerName));
}
return (ControllerBase)controller;
}
It could use some caching but for my case that was a premature optimization.
What is the problem you are trying to solve? It sounds like you may be headed down a path to a complex solution that could use a simple solution instead.
If a user doesn't have permissions to access the page after login, are you wanting non-logged in users to go to one page, while logged in users go to a different page?
If that's the case I might be tempted to create another controller for just such scenarios and redirect to that controller anywhere the user doesn't have access. Or if you are using your own base Controller I would put the functionality there.
Then the controller could present the desired view. For example if a non-logged in user tries to access a page they could get redirected to a generic error page. If the user is logged in, they could get redirected to a not authorized page.
This is very similar to Robert's answer.
Here's a basic skeleton for a base controller.
public BaseController: Controller
{
... // Some code
public ActionResult DisplayErrorPage()
{
// Assumes you have a User object with a IsLoggedIn property
if (User.IsLoggedIn())
return View("NotAuthorized");
// Redirect user to login page
return RedirectToAction("Logon", "Account");
}
}
Then in lets say a AdminController (that inherits from BaseController) action
public ActionResult HighlyRestrictedAction()
{
// Assumes there is a User object with a HasAccess property
if (User.HasAccess("HighlyRestrictedAction") == false)
return DisplayErrorPage();
// At this point the user is logged in and has permissions
...
}
This is probably going to sound controversial, but I check security at the beginning of each controller method, inside the method:
public class ProductController : Controller
{
IProductRepository _repository
public ActionResult Details(int id)
{
if(!_repository.UserHasAccess(id))
return View("NotAuthorized");
var item = _repository.GetProduct(id);
if (item == null)
return View("NotFound");
return View(item);
}
}
The reason I don't use the [Authorize] attributes for this is that you cannot pass an id, or any other identifying information, to the attribute at runtime.
In my application I have created a custom filter derived from AuthorizeAttribute, so any unauthorized access will simply go to AccessDenied page. For links, I replace Html.ActionLink with a custom helper Html.SecureLink. In this helper extension, I check for this user's roles access to controller/action against database. If he/she have the authorization, return link otherwise return the link text with special remarks (could be image/ coloring/ js)
Why not attribute your controller methods with the security requirement.
I wrote an attribute to do this as follows:
public class RequiresRoleAttribute : ActionFilterAttribute
{
public string Role { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (string.IsNullOrEmpty(Role))
{
throw new InvalidOperationException("No role specified.");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.HttpContext.Response.Redirect(loginUrl, true);
}
else
{
bool isAuthorised = filterContext.HttpContext.User.IsInRole(this.Role);
<< Complete Logic Here >>
}
}
}
i just spent some time implementing #jfar's solution (updating it for non-deprecated GetFilters() version), and then i realized that i can skip this whole thing.
in my case (and i assume most cases) I have a custom AuthorizationAttribute to implement site authorization which in turn calls my authorization service to make the actual access level determinenation.
So in my html helper for generating menu links, i skipped right to the auth service:
#Html.MenuItem(#Url, "icon-whatever", "TargetController", "TargetAction")
public static MvcHtmlString MenuItem(this HtmlHelper htmlHelper, UrlHelper url,string iconCss, string targetController, string targetAction)
{
var auth = IoC.Resolve<IClientAuthorizationService>().Authorize(targetController, targetAction);
if (auth == AccessLevel.None)
return MvcHtmlString.Create("");
*user is determined within the client auth service
public string GetUser() {
return HttpContext.Current.User.Identity.Name;
}
*could also add some behavior for read-only access. it's nice because my auth service takes care of caching so i don't have to worry about performance.