I need a clarification about Spring Security isAuthenticated() built-in expression.
See here for documentation.
I would like to know whether or not it is really necessary or plain redundant to use isAuthenticated() when the hasRole() expression is also used.
Normally, yes it would be unnecessary. The isAuthenticated() expression's purpose is to allow you to allow access for authenticated users regardless of what roles they have.
Unless you use hasRole() in a contrived way (e.g. by selecting the role assigned to anonymous users), then there's no reason why you would also need to add isAuthenticated(), since only authenticated users will have the roles you assign to them in your application.
Related
I'm trying to get up to speed with OpenId Connect, OAuth2.0, Security Token Service and Claims. Imagine a scenario with a large website with many areas and different functionality e.g. Customer, Order, Supplier, Delivery, Returns etc. My question is this – would I create Claims on the Token Server such as CanCreateCustomer, CanReadCustomer, CanUpdateCustomer, CanDeleteCustomer etc, i.e. effectively CRUD Claims for each main area/Business Object? This would lead to many tens but more likely hundreds of Claims. Or is my understanding coming up short?
So fixing terminology, you mean "scopes", not "claims". Scopes are identifiers used to specify what access privileges are being requested. Claims are name/value pairs that contain information about a user.
So an example of a good scope would be "read_only". Whilst an example of a claim would be "email": "john.smith#example.com".
You can send claims in the id token (or JWT), or/and have them available via the userinfo endpoint (if using the "openid" scope).
You can break scopes down per service, and have them as granule as you would like. Or have them as high level (read / write / admin). I would recommend having enough scopes to actively achieve the security principle of least privilege (basically: giving people what they need to do their job). You can use namespaces if you have a lot of scopes.
Your understanding is right, but you have a lot more flexibility in OAuth2.0 scopes (claims)
These scopes can be configured in any way for eg, in your case instead of creating individual scopes for each CRUD operation for each main area, you could create group scopes like
customer.read_write
order.read_write
Etc, you can even go one level higher , by creating functionality level scopes, like
webportal.full_access
adminportal.full_access
Then in your application, after authentication, the authorisation can be done like,
ValidScopesIn({Scopes.WEBPORTAL_FULL_ACCESS, Scopes.CUSTOMER_READ_WRITE})
public void createCustomer(Customer customer) {
// your creation logic
}
I think your understanding is largely correct. However, if I understand what you describe correctly it seems more of an authorization (OAuth) rather than an authentication (OIDC) problem, and as such you might have a look at how other OAuth resource providers define their scopes (not claims btw), for instance GitHub or Slack.
I would recommended that "scopes" be configured as URIs so that collisions do not occur.
As an example.
-jim
I'm building a grails app, and the default URLMapping provided by grails is /$controller/$action?/$id
I'm concerned about the security aspects of this catch all mapping. On one hand, it's a pain to explicitly list our all of the mappings, but on the other hand it seems like there could be potential security issues, such as forgetting to secure certain mappings.
By explicitly specifying the mappings, we have much tighter control over the URLs. It also lets us making more user friendly URLs (e.g. maybe we could pluralize things like using having a people/john/ url instead of /erson/john.
Are there other concerns with leaving the default mappings? Is there a possibility that we could unintentionally expose the fact that a certain admin page is valid (I'll have to look more into spring security as to how to redirect to a 404 for trying to access admin pages for a non admin user)?
I think you answered yourself. Default url mapping "/$controller/$action?/$id" is easy to use but may be used as hole in the case of bad controllers security implementation.
But probably the best solution is to place security checks even at domains level, so even if for error a user can reach a not authorized controller an exception will block him to do anything with the domains.
When I create a new entity I would like to grant ACL permissions (aka ACL entry) to this new entity. So far so easy :-)
The problem arises in the following scenario:
An end user can create the entity without being authenticated on the web site.
The service that persists this new entity hence runs without an authentication context.
But: to grant ACEs one needs to have an active authentication context.
Spring's JdbcMutableAclService uses SecurityContextHolder.getContext().getAuthentication() to obtain the current authentication, so there seems to be no way to circumvent this requirement.
Any ideas are greatly appreciated!
Found the answer myself:
In a web application there always is an authentication context. If a user is not authenticated the authentication is org.springframework.security.authentication.AnonymousAuthenticationToken which has a single granted authority: ROLE_ANONYMOUS.
Hence it is simple to grant this user the right to create ACLs. Just configure the PermissionGrantingStrategy to use this role to authorize requests.
The main answer does not work in the current version of Spring (5.3.22) and Spring Security (5.7.3). I doubt it even worked back in 2012, when the answer was posted since it does not make sense.
PermissionGrantingStrategy is a class that only contains the method bool isGranted(Acl, List<Permission>, List<Sid>, boolean) which decides if the principals in the List<Sid> can access the object with the corresponding Acl with any of permissions in List<Permission>.
This is the function that is called when a user want to access an object with a certain permission. This method determines if access is granted or denied.
This has nothing to do with allowing anonymous users to modify existing Acls. The actual problem comes from calling MutableAcl aclService.createAcl(ObjectIdentity) when the authentication context is empty. This is implemented by JdbcMutableAclService, provided by Spring. The problem is that MutableAcl JdbcMutableAclService.createAcl(ObjectIdentity) has this call Authentication auth = SecurityContextHolder.getContext().getAuthentication(); which forces the access to authorization context even though the Sid could be passed to the createAcl method, so the business logic would be able to createAcls for the chosen users passed in the arguments.
Instead, we have this call which makes it impossible to use Acls from an unauthenticated context if we want to keep using the Spring Classes.
So, the solution would be reimplement the JdbcMutableAclService so the createAcl method does not call the authentication context, instead it has an extra arguments to indicate the Sid of the user we want to create the Acls.
If anyone has any idea on how to do that it would be greatly appreciated.
I am trying to initialize my Acl tables programmatically when my web app starts, but I cannot do it because my initialization code does not have any authantication.
Let's say I have users and articles.
Anonymous can list and read articles.
Only registered and logged user can create articles.
User can edit only own articles.
And, of course, admin can do anything.
I've looked at spring security, but didn't found a way to do that. My app don't need roles, and ACL will be too "heavy" for that.
Maybe I should implement my own security?
You're right, ACL would be too much for the task.
You can use Spring Security's authorize tag in JSP, which provides access to the logged in user via the principal object. Example to limit access to editing an article to the user with a given username:
<sec:authorize access="hasRole('SOME_PRIVILEGE_OR_ROLE') and ${someArticle.username} == principal.username">
...
</sec:authorize>
Note that SOME_PRIVILEGE_OR_ROLE could be some role like 'LOGGED_IN_USER', but could also rather specify a certain privilege, e.g. 'READ_ARTICLE' or 'UPDATE_ARTICLE'. Spring Security is flexible here. Whatever you choose, it needs to be in the GrantedAuthorities collection of your user object.
Note also that you can implement your own user object, adding further info to what the UserDetails interface provides, e.g. comparing the user's id rather than the username.
Finally, note that you need a recent version of Spring Security (>=3.1) for the Spring EL to work as in the example.
I would like implement spring acl for my object fields.
does anyone has an idea what do i have to implment for it?
for example, i have Purchase object.
i would like admin_role to have read on all the fields, and secretary_role to have read only on username and address field
Can you clarify at what point you need the security?
If this is part of a webapp, I frequently use stripes security interceptors in combination with spring to control access to what the user sees based on role.
If it's not part of a webapp and you're looking to control what a user can change there's a number of methods available from custom annotations to database control. I've found the project itself usually dictates which path I should follow.
extend org.springframework.security.acls.domain.BasePermission and introduce your own Permission flag (up to 32 bits are supported)