Can you use Shiro for Grails without Roles and Permissions? - grails

I wonder if you can use Shiro-Plugin for Grails without having permissions and roles enabled?
In our current Project, we have an external database with just username and password and I am not able to create the permissions and roles table.
Is there a way to implement one Shiro user with automatic permission to all Domains without role-management?

From Shioro plugin documentation
Create a class in src/groovy or src/java that implements the grails.plugin.springsecurity.shiro.ShiroPermissionResolver interface, and define the
Set<String> resolvePermissions(String username)
method any way you like. Register your bean as the shiroPermissionResolver bean in resources.groovy, for example
import com.mycompany.myapp.MyShiroPermissionResolver
beans = {
shiroPermissionResolver(MyShiroPermissionResolver)
}

Related

spring security: what's the best practice for include value in permission?

In spring security, or RBAC, the Authority is described as a string, such as "download-file" means user can download file. If I need to limit user maximum daily download times and assign different values to different user, means the Authority contains dynamic values, how can I do this in spring security?
As you are alluding to there is a difference between authorities (i.e. roles) and permissions. Authorities tend to broadly apply for an application and have no state while permissions tend to be on specific objects and contain state.
This seems more like a domain problem than a permissions problem. Putting the logic into security feels a bit like having a form that must contain a valid email and checking the email format in security. I'd consider moving the logic outside of the security code.
If you really want to do this with Spring Security, I'd use a custom Bean that performs the check:
#Component
public class Download {
public boolean isAlowedForUser(Authentication authentication) {
// ...
return result;
}
public boolean isAllowedForCurrentUser() {
return isAllowedForUser(SecurityContextHolder.getContext().getAuthentiation());
}
}
Then you can autowire the Bean into your code and check the permission by invoking the code. If you prefer, you can also integrate into Spring Security's method security to perform the checks. To enable it you need to specify #EnableGlobalMethodSecurity(prePostEnabled = true) at the top of one of your configuration classes. Then you can use something like this on a Spring managed Bean:
#PreAuthorize("#download.isAllowedForCurrentUser()")
public void downloadFile(String fileName) {
Please refer this link
Spring Boot : Custom Role - Permission Authorization using SpEL
You can add new permission , like "DOWNLOAD_FILE" and authenticate if the current user has that permission using -
#PreAuthorize("hasPermission('DOWNLOAD_FILE')")
You can also limit access for Roles as well
#PreAuthorize("hasRole('ADMIN') and hasPermission('DOWNLOAD_FILE')")

2 UserDomainClass in Spring Security

In the existing Grails application, I have 2 user domains, say UserAdmin and UserBasic. Both these domains have few common fields and also some distinct fields(respective to domain) and currently the login/logout is maintained using sessions for both types of users separately. I want to integrate spring-security in the existing application.
What would be the best approach to do it ? Considering that both domains also have different field. Can we inherit both the domains in a single domain and use it as Spring Security user class ? Please suggest.
Spring Security Core uses one of the implementations of UserDetails interface as a projection of authenticated user. Grails provides e.g. GrailsUser class:
https://github.com/grails-plugins/grails-spring-security-core/blob/master/src/java/grails/plugin/springsecurity/userdetails/GrailsUser.java
Keep in mind, that this class is not a "domain" class in terms of Grails application layout - it does not get persisted in the database, it's just a projection of the user that is bounded to the current session.
If you have 2 different domain classes that represents users in your application, you can try to provide your own implementation of UserDetailsService, e.g.
class CustomUserDetailsService implements UserDetailsService {
#Override
UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// 1. Check if expected user is type of UserBasic
// 2. If not, check if expected user is type of UserAdmin
// 3. If nothing found, throw an exception
// 4. Otherwise create new GrailsUser instance using UserBasic or UserAdmin data
// 5. Return created GrailsUser instance
return null
}
}
Then you have to inject your implementation by adding or modifying an entry in grails-app/conf/spring/resources.groovy e.g.
// Place your Spring DSL code here
beans = {
// other beans goes here
// ...
userDetailsService(CustomUserDetailsService)
}
This is just a concept that you can start from.

secure grails spring security controllers

I am using spring security plugin in my Grails project. In order to secure the URLs, I am using interceptUrlMap.
My User and Role classes are User.groovy and Role.groovy respectively. Based on these classes, the s2-quickstart script has generated the UserController.groovy and RoleController.groovy
The problem arises when I want to secure UserController.groovy. My requirement is that I cannot permit all users to create a new user. Therefore certain actions of the UserController need to be blocked for users with the proper role privileges.
However no matter how I try to restrict access, I see that all the actions of UserController are always accessible.
Could anyone please explain where I am going wrong. Any help is highly appreciated.
Better use annotations instead of defining rules in Config.groovy. That helps in two ways i.e. first, hot reloading will always work and second you can override any rule easily in Config.groovy. That means you can use both annotation and plain rules in Config.groovy.
So change this in Config.groovy
grails.plugin.springsecurity.securityConfigType = "Annotation"
and start protecting your controller or actions like:
import grails.plugin.springsecurity.annotation.Secured
#Secured(["ROLE_MRU"])
class UserController {
def edit() {
// action code
}
#Secured(["ROLE_ADMIN"])
def show() {
// action code
}
}
I have managed to solve the issue. The problem was that I was editing Config.groovy while the application was still running. Hot deployment was not taking place.
Once I restarted the application, the functionality started working.
Thanks for all the help.

Inject field in a grails domain class dynamically

I have a problem in a grails application. My application use a plugin to generate some domain models, I need to add a field to one of those domain models and I don't have the source code. Is there a way to do it dynamically? For example using the GORM API the metaclass or something like that?
You could probably just extend the class from the plugin and add your field. That is a common thing to do with plugins like Spring Security Core.
class MyUser extends SecUser {
String phoneNumber
...
}

Access/check Spring Security hierarchical roles programmatically

In my Grails project I defined multiple hierarchical roles using the Spring Security plugin e.g. ROLE_USER > SOME_OTHER_ROLE. When securing controller methods using the #Secured annotation it works just fine. However, I also would like to check the role programmatically in my code for one use case. Using the following approach I always get a false even though the user inherits the role through hierarchical role definition:
request.isUserInRole('SOME_OTHER_ROLE')
Also the following calls never directly return the inherited roles:
SecurityContextHolder.context?.authentication?.authorities
springSecurityService.getPrincipal().getAuthorities()
Is there a way of checking if the user also has the inherited role?
This seems like a bug (or at least an omission) in SecurityContextHolderAwareRequestWrapper which adds a request wrapper to implement the isUserInRole method.
You can use the roleVoter bean's extractAuthorities method. Add a dependency injection for it (def roleVoter) and then call
def allRoles = roleVoter.extractAuthorities(
SecurityContextHolder.context.authentication)

Resources