Avoid hard-coded roles in MVC? - asp.net-mvc

I understand that in mvc to implement role based security at the controller or action level for my site I could paint the class or method with something like the following:
[Authorize(Roles = "DOMAIN\GROUPNAME")]
(I use windows authentication)
Previously in asp.net I might have done this with a location section in the config.
The problem I have with doing this is that this site is installed in various environments in the company and for each environment that value could be different.
Is there a way to give these roles an alias with a mapping in the config? Or have I got something wrong here?
EDIT
I tried:
[Authorize(Roles=ConfigurationSettings.AppSettings["UpdateRole"])]
But this gives me the error: "An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type"

Take a look at this:
ASP.NET MVC - Dynamic Authorization

Related

Greedy segment with .NET MVC 5 Attribute Routing

I would like to define a route as follows -
[Route("clients/{*code}/{id:guid}/update")]
public ActionResult Update(string code, Guid id)
{
}
Code will be something like "foo/bar/xyz".
Unfortunately, out-of-the-box MVC doesn't support greedy parameters in the middle of a Route definition.
This has previously been solved using the old MVC routing conventions, however I would like to have this as a RouteAtribute defintion.
As far as I know you cannot do it directly. However, you should be able to use IIS module UrlRewrite and rewrite the query with a greedy parameter in the middle to the one with a greedy parameter at the end.
So a client queries: clients/{*code}/{id:guid}/update
and your web api sees clients/{id:guid}/update/{*code}
From what I can tell there is no out-of-the-box way of doing this other than to use custom code like this example. Hope it helps.

How to customize rolePrefix in Grails using Spring Security plugin?

I am working on a grails 2.3.8 project and trying to customize the Role Hierarchy. I am trying to change the default value of rolePrefix = 'ROLE_' in resources.groovy with rolePrefix = 'PERM_'. I understand that to make this work, I need to make the following changes in my Config.groovy into something like:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'tpo.core.acl.AdminAccount'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'tpo.core.acl.AdminAccountPermission'
grails.plugins.springsecurity.authority.className = 'tpo.core.acl.Permission'
And to establish hierarchy, I need to add this too in my Config.groovy
grails.plugins.springsecurity.roleHierarchy = '''
PERM_ACCOUNT_ALL > PERM_ACCOUNT_CREATE
PERM_ACCOUNT_ALL > PERM_ACCOUNT_READ
PERM_ACCOUNT_ALL > PERM_ACCOUNT_UPDATE
PERM_ACCOUNT_ALL > PERM_ACCOUNT_DELETE
'''
So in my Controller, it is something like,
#Secured(['PERM_ACCOUNT_ALL'])
def index() {
redirect(action: "list", params: params)
}
When I try to run my application, and access my controller's index() action, I was prompted to log in, this is expected because of the presence of #Secured(), but having successfully logged in, I was not yet able to access the index() action, and it displayed, Sorry, you're not authorized to view this page. The permission was assigned to the user that I used to logged in, but still, I was not able to access it.
Where am I missing?
There's a lot more to it than that :)
The reason that the plugin doesn't allow this change is to support the standard voters. Currently there are three styles of strings that can be used to specify access rules - role names, SPeL expressions, and the funky "IS_AUTHENTICATED" ones - IS_AUTHENTICATED_ANONYMOUSLY, IS_AUTHENTICATED_FULLY, and IS_AUTHENTICATED_REMEMBERED. Additionally there's a new way that was added for the 2.0 release - using a Closure and any arbitrary Groovy code inside of it, but that's unrelated to role names.
Each of the registered voters is queried to determine if they "support" (i.e. can vote on) each of these tokens. The logic is currently rather straightforward - the "IS_AUTHENTICATED_..." strings are handled by one voter, strings starting with "ROLE_" are handled by another, and everything else is assumed to be a SPeL expression.
To be honest, I think since roles would have to have been "registered" at startup anyway (to specify what access rules are allowed for each role in annotations, Config.groovy, etc.) that the role voter could do more than just check that the string starts with some prefix - it could look at its collection of known role names. So it probably wouldn't be too much work to add support for custom role prefixes for the 2.0 release, and I'll look into that. But for now, the plugin is as customizable as much as possible in every way except for this one exception.

ASP.net MVC - using AuthorizeAttribute in multiple environments with Windows Authentication

I'm using windows authentication in my ASP.net MVC 3 application. I have a few different roles in my system:
Administrator
PowerUser
GeneralUser
We have a rule in place that the AD group names are different in each environment.
For example, in Development the role names will be:
Administrator_Dev
PowerUser_Dev
GeneralUser_Dev
In production it would just be:
Administrator
PowerUser
GeneralUser
Is there a good solution for using Authorize in these different environments without changing the code when I need to deploy to a different environment?
Can't you just implement all of the roles? Unless there's a chance of an Administrator_Dev role being the production site...
[Authorize(Roles = "Administrator_Dev, Administrator")]
The only solution I can think of is the conditional compilation.
Define these constants in a file with conditional compile.
#if DEV
public const string AdministratorGroupName = "Administrator_Dev";
#else
public const string AdministratorGroupName = "Administrator";
#endif
This is one of the problems with declarative authorization using custom attributes that needs to be defined at compile-time.
Another alternative is to have another custom attribute and implement the action filter yourself.
I did by simply creating application specific configuration sections in web.config, putting the name of the environment specific AD group in the application configuration section and then use the configuration property on the Authorize Attribute. I can then change the group name by using custom web.config for each environment. For most applications, you need that anyway to be able to have different connection strings for each environment. With this, you can just use the in-built Authorize Attribute.

Sending a parameter to the controller in ASP MVC 2

I am writing an area for administering several subsites, almost all of the functionality will be the same across each site (add/edit/remove pages etc) and my repository on instantiation takes the SiteIdentity so all the data access methods are agnostic in relation to this. The problem I have at the moment is trying to make my action methods also agnostic.
The URL pattern I want to use is along the lines of:
"ExternalSite/{identity}/{controller}/{action}/{id}"
A naive approach is to have each action take the identity parameter, but this means having to pass this in to my repository on each action as well as include it in the ViewData for a couple of UI elements. I'd much rather have this something that happens once in the controller, such as in its constructor.
What is the best way to do this? Currently the best I can come up with is trying to find and cast identity from the RouteData dictionary but part of me feels like there should be a more elegant solution.
It sounds like you want to use OnActionExecuting or a Custom ModelBinder to do that logic each time you have a specific parameter name (also known as a RouteData dictionary key).
Creating a custom modelbinder in ASP.NET MVC
Creating an OnActionExecuting method in ASP.NET MVC, Doing Serverside tracking in ASP.NET MVC
You have access to your route values in Request.RequestContext.RouteData, so you can make base controller and public property SiteIdentity, in such case you can access it from all actions in all inherited controllers.

ASP.NET MVC - Extending the Authorize Attribute

Currently I use [Authorize(Roles = ".....")] to secure my controller actions on my ASP.NET MVC 1 app, and this works fine. However, certain search views need to have buttons that route to these actions that need to be enabled/disabled based on the record selected on the search list, and also the security privs of the user logged in.
Therefore I think I need to have a class accessing a DB table which cross-references these target controller/actions with application roles to determine the state of these buttons. This will, obviously, make things messy as privs will need to be maintained in 2 places - in that class/DB table and also on the controller actions (plus, if I want to change the access to the action I will have to change the code and compile rather than just change a DB table entry).
Ideally I would like to extend the [Authorize] functionality so that instead of having to specify the roles in the [Authorize] code, it will query the security class based on the user, controller and action and that will then return a boolean allowing or denying access. Are there any good articles on this - I can't imagine it's an unusual thing to want to do, but I seem to be struggling to find anything on how to do it (could be Monday-morning brain). I've started some code doing this, looking at article http://schotime.net/blog/index.php/2009/02/17/custom-authorization-with-aspnet-mvc/ , and it seems to be starting off ok but I can't find the "correct" way to get the calling controller and action values from the httpContext - I could possibly fudge a bit of code to extract them from the request url, but that doesn't seem right to me and I'd rather do it properly.
Cheers
MH
I found this on another forum and so will post it here in case anyone finds it useful. Note that how you do this changes depending on whether you are using MVC 1 or 2
the class you create needs to implement
public void OnAuthorization(AuthorizationContext filterContext)
and then you can use
string controllerName = filterContext.RouteData.Values["controller"].ToString();
and the same, substituting "action" for "controller" (make sure you check for nulls in these values first). In MVC 2 this can be changed to filterContext.ActionDescriptor.ActionName and .ActionDescriptor.ControllerDescriptor.ControllerName and you won't have to check for nulls

Resources