The UserDetails.getAuthorities()
holds all roles of currently logged in user. As You already have a custom UserDetails
You only need to add the additional role to the values returned by getAuthorities()
on the mid-session start, and then remove it on the mid-session end. (see edit below)
ie:
public class MyUserDetails implements UserDetails {
// holds the authorities granted to the user in DB
private List<GrantedAuthority> authorities;
// holds the temporarily added authorities for the mid-session
private List<GrantedAuthority> extraAuthorities;
public GrantedAuthority[] getAuthorities() {
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
auths.addAll(this.authorities);
auths.addAll(this.extraAuthorities);
return auths;
}
public void addExtraAuthorities(GrantedAuthority...auths) {
for (GrantedAuthority a : auths) {
this.extraAuthorities.add(a);
}
}
public void clearExtraAuthorities() {
this.extraAuthorities.clear();
}
}
Or You could create a wrapper around the original UserDetails that will hold the extra authorities and wrap it and set to the current Authentication object on the mid-session start and unwrap on the mid-session end.
Edit:
As Ben pointed out in the comment the UserDetails.getAuthorities()
does get called only once, at the login, when the Authentication
object is created - I forgot about that. But that brings us to the right answer, and this time I'm sure it's gonna work, cause I did it myself this way. The Authentication.getAuthorities()
is the method to attend to, not the UserDetails.getAuthorities()
. And I really recommend a wrapper for that, not the custom implementaion of Authentication
interace, as it'll be more flexible and allow to transparentlysupport diffrent authentication mechanisms underneath.
ie:
public class MidSessionAuthenticationWrapper implements Authentication {
private Authentication wrapped;
private List<GrantedAuthority> authorities;
public MidSessionAuthenticationWrapper(
Authentication wrapped, Collection<GrantedAuthority> extraAuths) {
this.wrapped = wrapped;
this.authorities = new ArrayList<GrantedAuthority>(wrapped.getAuthorities());
this.authorities.addAll(extraAuths);
}
public Authentication getWrapped() {
return this.wrapped;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.authorities;
}
// delegate all the other methods of Authentication interace to this.wrapped
}
Then all You need to do is on the mid-session start:
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
Collection<GrantedAuthority> extraAuths =
null; // calculate the extra authorities
MidSessionAuthenticationWrapper midSessionAuthentication =
new MidSessionAuthenticationWrapper(authentication, extraAuths);
SecurityContextHolder.getContext().setAuthentication(midSessionAuthentication);
And on the mid-session end:
MidSessionAuthenticationWrapper midSessionAuthentication =
(MidSessionAuthenticationWrapper) SecurityContextHolder.getContext().getAuthentication();
Authentication authentication = midSessionAuthentication.getWrapped();
SecurityContextHolder.getContext().setAuthentication(authentication);