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.
Related
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.
Currently I'm doing a check :
#if(this.User.Identity.Name=="DOMAIN\\USERID"){
This works great but I'd like to have multiple users(2-3) to check for. I'd also like to not have it hard coded. Is there a way to do this in the web.config or in a database?
You could add a list in the config...User1,User2 etc and then use linq and .Any() against this list?
var users = "user1,user2,user3".Split(','); //list will come from your config
bool result = users.Any(u => u == this.User.Identity.Name);
Also, since you're using MVC, if you want to use authorization for controllers etc, you can use the [Authorize] attribute. See this SO link too Authorize attribute in ASP.NET MVC
Maybe use roles instead then add the relevant users to that role? This would make it easier to expand on in the future, plus you don't have to hard code a list of users.
In ASP.NET MVC, we can assign multiple roles in AuthorizeAttribute. I'm currently using Fluent Security. The documentation says RequireRolePolicy can support one or more roles.
I want to do the code below:
configuration.For<MyController>(x => x.Index()).RequireRole("Administrator, Editor");
but it seems that it only checks one role. How to assign multiple roles to it?
Ok I got it now.
configuration.For<MyController>(x => x.Index()).RequireAllRolesPolicy("Administrator", "Editor");
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
I'm developing a Grails (Version 1.3.3) Web-Application using the Grails Spring-Security Plugin, Spring-Security-Core-1.0.1 (which, in turn, uses spring-security-3.0.2.RELEASE).
I would like to provide Spring-Security annotation-based access control on actions within a controller.
I have been able to successfully do basic authentication using the following annotations:
#Secured("hasAnyRole('ROLE_USER')")
def list = {
...
}
This works - providing access to the list action/view only to those with the ROLE_USER role.
However, the set of which roles are allowed to perform certain controller-actions may change over time and is a function of the system's overall state. That is, the set of roles allowed to perform a given action might be returned by a service or domain-object method.
One way I might be able to do something like this would be to use Spring-Security's "Expression Based Access Control" (#Pre and #Post annotations), something like the example at the Spring Security Documentation:
#PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);
In this example for access control decisions, one can gain access to the objects sent to the method (eg contact) using the #contact syntax.
However, I can't get #PreAuthorize (or #RolesAllowed) annotations to work on a Grails controller-action. If I annotate the list action with #PreAuthorize (rather than #Secured, as above), I get the following error:
Annotation
#org.springframework.security.access.prepost.PreAuthorize
is not allowed on element FIELD
This isn't surprising -- the action is a Groovy closure (a field with executable code), rather than a method. However, I've also tried using the annotation on methods, called from the closure, like:
def list = {
testMethod()
....
}
#PreAuthorize("hasRole('ROLE_USER')")
public boolean testMethod(){
println "testMethod succeess"
return true;
}
While this doesn't throw any errors, it also doesn't appear to provide any access control. ("testMethod success" is printed whether or not the user has ROLE_USER).
So, I've tried a few different things (and read the documentation), but haven't been able to work out a nice way of using #PreAuthorize annotations with a Grails controller-action. Is this possible? Is there a better way in a Grails app to use Spring-Security-Annotations to provide access-control that is a function of the state of the system?
You need to use the ACL plugin to use those annotations, but they won't work on controller actions for the reasons you point out. #Secured works because I created a copy of the Spring Security annotation that allows it to be placed on fields as well as methods and classes, and I look for them and wire them up explicitly. You'll need to use annotated services that you call from your controllers.