Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails Spring Security plugin - modify logged in user's authorities

I have a simple Grails app with Spring Security Core plugin installed and working fine. However, I haven't found any solution to the problem with updating a logged in user's authorities in the security context. I am not talking about updating the current user's details (i.e. springSecurityService.reauthenticate).

My problem is: I have a simple user management app with ROLE_ADMIN and ROLE_USER authorities used. Now, I have 2 administrators logged in at the same time (with ROLE_ADMIN authority) from different computers, and one admin decides to change the other admin's authority from ROLE_ADMIN to ROLE_USER.

How can I update the user and role so that the modified user (with new ROLE_USER role) cannot perform any ROLE_ADMIN level actions and is immediately redirected to ROLE_USER level pages? Is there a way to update the security context so I don't have to do additional checking in all the controller actions whether the logged in user's authorities have been changed? Can I use the cahceUsers property for that somehow? I haven't modified the cacheUsers and in my understanding, it's false by default. Please, correct me if I'm wrong.

EDIT: The sequence that's causing the problem is

  1. Administrator "A" modifies administrator "B" and sets a new role (ROLE_USER) for administrator "B"

  2. the code calls PersonRole.removeAll(personInstanceB) and PersonRole.create(personInstanceB, roleAdmin) and everything is updated normally

  3. at the same time Administrator "B" is already logged in when their authorities are modified. Administrator "B" can continue working on ROLE_ADMIN restricted pages until he/she logs out and does a new login. Only then the authorities are updated and Administrator "B" has the new role (ROLE_USER)

  4. I want Administrator "B" to be redirected to the ROLE_USER pages when the user is updated with the new role and not only after logout/login

  5. calling springSecurityService.reauthenticate personInstanceB.username) causes Administrator "A" to be "logged in" as Administrator "B" so this does not work.

Any ideas would be very welcome. I may have missed something simple here but I have no idea what the solution would be.

Cheers, mizzzto

like image 450
mizzzto Avatar asked Jun 20 '11 09:06

mizzzto


2 Answers

This is untested but give it a try

In your controller/service class,

...

User user = User.get(springSecurityService.principal.id) //get the user
Role adminRole = //get or create the admin Role
UserRole.remove user, role // remove admin Role

Role userRole = // get or create the user Role
UserRole.create user, role //add the user Role

... 

if (!user.hasErrors() && user.save(flush: true)) {
    springSecurityService.reauthenticate user.username // refresh the users security deatils
}

....

EDIT

That is a lot clearer now.

What I would do off the top of my head is use the switch user function. see Switch User

  • First you set the useSwitchUserFilter attribute to true
  • It is advised you make a new role(e.g ROLE_SWITCH_USER) for this priviledge.
  • in your admin page somewhere,

    <sec:ifAllGranted roles='ROLE_SWITCH_USER'>
       <form action='/j_spring_security_switch_user' method='POST'>
          Switch to user: <input type='text' name='j_username'/> <br/>
          <input type='submit' value='Switch'/>
       </form>
    </sec:ifAllGranted>
    
  • log in as the user you wish to edit using their username
  • change their role settings by making a call to the adminToUser() method below(for example)
  • switch back to the original user
  • Done.

-- You can use the code form the first answer to create a method in your controller or service that take a userInstance and changes thier role from admin to user.

def adminToUser(user, adminRole, userRole){
    UserRole.remove user, adminRole
    UserRole.create user, userRole 
    if (!user.hasErrors() && user.save(flush: true)) {
        springSecurityService.reauthenticate user.username 
    }
}
like image 75
gotomanners Avatar answered Nov 15 '22 20:11

gotomanners


I have solved this problem by reauthenticating twice:

Save the name of the administrator who is demoting the other user:

def originalUserName = springSecurityService.principal.name
springSecurityService.reauthenticate user.username
springSecurityService.reauthenticate originalUserName
like image 7
Tony the Tech Avatar answered Nov 15 '22 20:11

Tony the Tech