I am using the Spring Security ACL plugin in grails 1.3.7, but my question is probably more generic than that: I would like to allow users who have BasePermission.READ access to an object to be able to grant that same permission to other users. If user1 has read access to a document, he should be able to share that with user2, and thereby give him read access to the same document.
When the document is first created, user1 is granted read access, so I see this in the log:
DEBUG grails.app.service.org.grails.plugins.springsecurity.service.acl.AclUtilService Added permission BasePermission[...............................R=1] for Sid PrincipalSid[User user1] for com.fxpal.ara.Document with id 1
Then I try to grant the READ permission to user2 while authenticated as user1, I get this exception:
org.springframework.security.acls.model.NotFoundException: Unable to locate a matching ACE for passed permissions and SIDs
So my questions are:
1. Is having BasePermission.ADMINISTRATION required to allow users to grant permissions to other users?
2. Is there some other way to grant permissions while having only partial permissions? Where is this policy implemented, and can it be replaced?
Update:
Well, I thought I could add a new implementation of AclAuthorizationStrategy which defines the method public void securityCheck(Acl acl, int changeType), but this method doesn't take the requested permission as a parameter, foiling my strategy of checking for compatible permissions. The next thing to do would be to re-implement AclImpl to use different logic. Seems like a shame to repeat most of the same code...
You can fix this issue by either creating the
<bean id="aclAuthorizationStrategy" class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<constructor-arg>
<bean class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<constructor-arg>
<value>ROLE_ADMINISTRATOR</value>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
Here the ROLE_ADMINISTRATOR should be the Role which the Logged in User object has as part of authorities. Basically Anyone with this Role can manage Permissions.
Related
I came across this code snippet while debugging an authentication problem :
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder hash="sha-256">
<security:salt-source user-property="dateCreated" />
</security:password-encoder>
</security:authentication-provider>
<security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>
What I have noticed while debugging and playing around with the user credentials is that if the first authentication-provider (i.e. userDetailsService) fails to authenticate my user, a remote call is then made to my LDAP server to try to authenticate my user. However if the first authentication-provider manages to authenticate my user successfully, the second authentication-provider is never called.
My question is does the listing of these authentication providers work in a way that if one fails we should jump to the next? I also wonder if the order of them authentication providers listed within the authentication manager plays a role (from a priority standpoint)? An extra reference from Spring Security's official documentation will be more than appreciated.
From the Spring Security reference documentation:
Each AuthenticationProvider has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream AuthenticationProvider to decide. If none of the configured AuthenticationProviders can authenticate, then authentication will fail (...)
In practice each AuthenticationProvider knows how to perform a specific type of authentication. For example, one AuthenticationProvider might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
When multiple AuthenticationProviders are defined, they will be queried in the order they are declared.
If the first AuthenticationProvider cannot come to a conclusion it will allow the next AuthenticationProvider to try.
In Spring Security we can have roles but this is not sufficient for my case. For example if User A log in he can't view/change User B's data and both users will have same role like ROLE_USER. Is there any built in mechanism for this in Spring Security ?
You can add method level security in that you check if that user with ROLE_USER can access particular resource with help some expression as given here
And configuration can be done as given here
I am using Spring Security to control the authority in my web application.I imported the security tag in my code as below:
<%# taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>
Then I am using the code block like this to control if the user have access to the specified button:
<sec:authorize ifAnyGranted="addUser">
<button type="button">Add User</button>
</sec:authorize>
With this code,only the user who have the addUser authority can see this button and use it.
Now my question is:Can we have a super user that even if it doesn't have the addUser authority,he still can see this button?
No, I don't think there is such feature built-in in Spring Security. You can either:
have a super user role (authority) that you check for in every authorization check, or
give your super user all possible authorities in your authentication provider or user details service.
I'm not really sure that it is the expected answer, but SpringSecurity has a notion of hierachy of roles. That mean you could create a super user role and declare it to contain addUser authority (among others).
That way, any user having the superUser authority will (among other permissions) see your button
References : From Hierarchical Roles in Spring Security reference manual you could write something like
<bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<property name="hierarchy">
<value>
ROLE_SUPER_USER > ROLE_ADD_USER
</value>
</property>
</bean>
It seems as a missing requirement, thus I have created an issue in Spring Security repository:
https://github.com/spring-guides/top-spring-security-architecture/issues/5
I'm using spring-security-kerberos to authenticate the remote users - this works well. The problem that I have is that sometimes users do not have the kerberos ticket in place and I need to use another form of authentication. I've wrote my own Authentication Provider (myCusomAuthenticationProvider) for this purpose. This custom provider should ask the user for BASIC authentication and uses several LDAP servers to authenticate the user based on username and password.
The problem that I see is that my custom authentication manager always gets KerberosServiceRequestToken as the authentication token and I don't manage to get UsernamePasswordAuthenticationToken. How can I make the server return both "Negotiate" and "Basic" methods to the browser and have my own provider handle the basic authentication?
I've found a way to do it with some tweaks to the spring-security-kerberos code but I'm trying to find a better way to do this.
web.xml: http://pastebin.com/embed.php?i=ZidnBMwZ
root-context-with-krb.xml: http://pastebin.com/c8vfUZfV
This answer will help you Optional kerberos authentication
And if you're need more custom, then extends KerberosAuthenticationProvider by your class MyCustomAuthenticationProvider and paste it to class attribute:
<bean id="kerberosAuthenticationProvider" class="com.test.MyCustomAuthenticationProvider">
<property name="kerberosClient">
<bean class="org.springframework.security.extensions.kerberos.SunJaasKerberosClient">
<property name="debug" value="${krb.debug}"/>
</bean>
</property>
<property name="userDetailsService" ref="dummyUserDetailsService"/>
</bean>
I am new in ss3,and I have read its reference,also I read the spring security book.
However I do not find anything about the role-permission.
For example,here is the config for form-based authentication.
<http auto-config='true'>
<intercept-url pattern="/user/add/**" access="hasRole('USER_ADMIN')"/>
<intercept-url pattern="/user/delete/**" access="hasRole('USER_ADMIN')"/>
<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page='/login.jsp'/>
</http>
I want to control the user operation(add/delete):
<intercept-url pattern="/user/add/**" access="hasRole('USER_ADMIN')"/>
<intercept-url pattern="/user/delete/**" access="hasRole('USER_ADMIN')"/>
I define the role of 'USER_ADMIN',but this is not enough,since I want to differ the user who have 'add' permission from user who have 'delete' permission.
Maybe I can add more roles like 'user_admin_add' and 'user_admin_delete'.
But I do not think this is a good idea since the 'add' or 'delete' are permissions,not roles.
How to make it?
Also,it seems that all the roles should be configed to the xml file,I wonder if I can add new roles and permissions dynamically(in the administrator page)?
Think of roles as a privileges. And granulate them as much as you need. Another thing is that maybe you should make a more RESTFul implementation. But this is another thread.
For example, your "delete" could be a "DELETE" HTTP method. Then you could be:
<security:intercept-url pattern="/users/*" method="DELETE" access="ROLE_DELETE_USER" />
and a curl -X DELETE -u login:password 'http://example.com/users/1'
would delete the user with id 1.
By a RESTFul, since uris are either identifiers or actions, there is no use in add roles (privileges) dinamically. Since those roles are meant to be used against a new resource that should contain the xml file.
I'm afraid you cannot do this, unless you use ** wildcards. Which in my opinion if used uncarefully can lead to troubles.
Maybe I can add more roles like 'user_admin_add' and 'user_admin_delete'.
This is the way. Permissions are roles and generally there are people who view differentiation between them as unneeded.
I don't think there is much difference in having a role ROLE_USER_ADDER or a permission PERMISSION_ADD_USERS.
You can however use roles as a concept to group permissions if you need to. For instance you can have a role admin which can add and remove users. So the role ROLE_ADMIN will have PERMISSION_ADD_USER and PERMISSION_REMOVE_USER. Still spring will view both roles and permissions simply as authorities.
As for dynamic roles adding you can do it by loading the current user permission from your DB for instance. Have a look at the UserDetailsService of spring security. The UserDetails object it returns has a getAuthorities() method which you can populate from your DB.
/**
* Returns the authorities granted to the user. Cannot return <code>null</code>.
*
* #return the authorities, sorted by natural key (never <code>null</code>)
*/
Collection<GrantedAuthority> getAuthorities();
Here is a very good example of implementing your own UserDetailsService.
In my personal opinion spring security has several (lets say) unfortunately chosen names. So do not pay so much attention to the Term "Role" it works perfectly if you use it for privileges.
In my applications a use a naming convention to choose between Roles ans Privileges. (roles are written upper case, privileges lower case). But pay attention the Role Voter will pay attention only the the strings that starts with "ROLE" (Default configuration, can be changed.)
See also Spring security group based authorization
You should be thinking of roles more along the lines of, well, roles, rather than permissions. If you want to differentiate between adding and removing users, you might define roles described as ROLE_SALES and ROLE_USER_ADMIN. Sales staff might well need to be able to add new users into a system.
Regarding the dynamic application of roles, you should look at the architecture of Spring Security. You'll most likely want to use, or implement, a suitable UserDetailsService. See the UserDetailsService reference documentation.
If you're storing your user authorization information in a JDBC database, for example, you might want to use the JdbcDaoImpl.
There are some examples of using different authentication providers in the namespace introduction.