Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Excluding GrantedAuthority from userDetails in spring security

I want to consider role as an attribute of a user rather than having an independent role class, hence I don't need to have a table for roles in my DB. But the generic spring UserDetails service passes GrantedAuthority (i.e. Collection<GrantedAuthority> getAuthorities()) as one of the user detail parameters.

What I want to do is replacing this generic GrantedAuthority parameter with a role (String role) declared in my 'User' class as shown below.

@Entity(name="usr")
public class User {
    @Id
    @Column(unique=true)
    private String username;
    private String password;
    private String role;

    public String getUsername() {               
        return username;        
    }

    public void setUsername(String username) {          
        this.username = username;       
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

And my customUserdetail service class:

@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository repository;

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {               
        try {
            x.y.User  user = repository.findByUsername(username);

            boolean enabled = true;
            boolean accountNonExpired = true;
            boolean credentialsNonExpired = true;
            boolean accountNonLocked = true;

            return new User(
                    user.getUsername(), 
                    user.getPassword(),
                    enabled,
                    accountNonExpired,
                    credentialsNonExpired,
                    accountNonLocked,
                    user.getRole());        

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }               
}

It returns an error since I passed user.getRole(), which is String, instead of Collection<GrantedAuthority> getAuthorities(), which is the default role type in spring security.

how can I customize it so that I can use the role (which is a string type) I've declared as an attribute of the 'User' class?

Mind: the normal security flow must be preserved!. meaning, without affecting the normal spring security flow.

Thank you in advance!.

like image 230
eyasu Avatar asked Nov 18 '13 17:11

eyasu


2 Answers

It can be done by implementing UserDetails interface by your User entity and overriding getAuthorities() method:

public class User implements UserDetails {
    ...
    private String role;
    ...

    @Override
    public Set<GrantedAuthority> getAuthorities() {
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(this.role));
        return authorities;
    }
}

And it's better to keep to Spring Security naming convention for role names, i.e. to start it with the "ROLE_" prefix.

like image 166
maxnx Avatar answered Oct 09 '22 11:10

maxnx


Your data model is decidedly different from Spring Security and its contract. To whit, in Spring Security, a user can have multiple roles.. This is part of the contract laid out by its interfaces. Your proposed data model violates that, and hence could not be made to work with Spring Security without a tremendous amount of what I like to call "Frankensteining". You'd also lose a great deal of flexibility that comes with the Spring Security design. In short, it's more effort than it's worth.

like image 31
Taylor Avatar answered Oct 09 '22 10:10

Taylor