Permission based access control in spring












0















im trying to secure my endpoints with role based access control. I have implemented the whole structure as well as CustomUserDetailService, however im not sure how should i enforce these rules on enpoints, i was looking for some nice annotation based evaluation like @PreAuthorize(hasRole('role')). My structure looks follwoing:



Permission:



@Entity
public class Permission implements GrantedAuthority {

@Id
private Long id;

@Column(name = "NAME")
private String name;

@ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)
private Collection<Role> roles;

@Override
public String getAuthority() {
return name;
}


Role:



@Entity
public class Role implements GrantedAuthority {

@Id @Column(name="ID" )
private Long id;

@Column(name="NAME", nullable=false , unique=false)
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "role_x_permission",
joinColumns = @JoinColumn(
name = "role_id"),
inverseJoinColumns = @JoinColumn(
name = "permission_id"))
private List<Permission> permissions;

@Override
public String getAuthority() {
return name;
}


User:



@Entity(name = "User")
@Table(name = "USERS")
@Data
public class User {

@Id
private Long id;

@Column(name="LOGIN" , nullable=true , unique=false)
private String login;

@Column(name="PASSWORD" , nullable=false , unique=false)
private String password;

@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name = "USER_ROLES",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;


Now i have defined my CustomUserDetailsService:



@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserRepository userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User applicationUser = userRepository.findByUsername(username);
if (applicationUser.getId() == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(applicationUser.getLogin(), applicationUser.getPassword(),
getAuthorities(applicationUser.getRoles()));
}

@Transactional
public Collection<? extends GrantedAuthority> getUserAuthorities(String username) {
User user = userRepository.findByUsername(username);

return getAuthorities(user.getRoles());
}

private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {

return getGrantedAuthorities(getPermissions(roles));
}

private List<String> getPermissions(Collection<Role> roles) {

List<String> permissions = new ArrayList<>();
List<Permission> collection = new ArrayList<>();
for (Role role : roles) {
collection.addAll(role.getPermissions());
}
for (Permission item : collection) {
permissions.add(item.getName());
}
return permissions;
}

private List<GrantedAuthority> getGrantedAuthorities(List<String> permissions) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String permission : permissions) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return authorities;
}
}


Then i'm trying to annotate my endpoint with @PreAuthorize



@PostMapping("/doSomething")
@PreAuthorize("hasRole('doSomething')")
public SomeEntity createComment(@RequestBody SomeEntity something) {
...
}


I have user with role of USER, this role doesn't have permission to doSomething, however it seems like @PreAuthorize("hasRole('doSomething')") is not working. I'm not sure what i have done wrong, coule you please point my mistake?



Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based.



What would be correct way to authorize access to endpoint with RBAC approach?










share|improve this question

























  • Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

    – dur
    Nov 22 '18 at 12:30











  • @dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

    – Akka Jaworek
    Nov 22 '18 at 13:00











  • Possible duplicate of stackoverflow.com/questions/44004977/…

    – dur
    Nov 22 '18 at 20:49
















0















im trying to secure my endpoints with role based access control. I have implemented the whole structure as well as CustomUserDetailService, however im not sure how should i enforce these rules on enpoints, i was looking for some nice annotation based evaluation like @PreAuthorize(hasRole('role')). My structure looks follwoing:



Permission:



@Entity
public class Permission implements GrantedAuthority {

@Id
private Long id;

@Column(name = "NAME")
private String name;

@ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)
private Collection<Role> roles;

@Override
public String getAuthority() {
return name;
}


Role:



@Entity
public class Role implements GrantedAuthority {

@Id @Column(name="ID" )
private Long id;

@Column(name="NAME", nullable=false , unique=false)
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "role_x_permission",
joinColumns = @JoinColumn(
name = "role_id"),
inverseJoinColumns = @JoinColumn(
name = "permission_id"))
private List<Permission> permissions;

@Override
public String getAuthority() {
return name;
}


User:



@Entity(name = "User")
@Table(name = "USERS")
@Data
public class User {

@Id
private Long id;

@Column(name="LOGIN" , nullable=true , unique=false)
private String login;

@Column(name="PASSWORD" , nullable=false , unique=false)
private String password;

@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name = "USER_ROLES",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;


Now i have defined my CustomUserDetailsService:



@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserRepository userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User applicationUser = userRepository.findByUsername(username);
if (applicationUser.getId() == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(applicationUser.getLogin(), applicationUser.getPassword(),
getAuthorities(applicationUser.getRoles()));
}

@Transactional
public Collection<? extends GrantedAuthority> getUserAuthorities(String username) {
User user = userRepository.findByUsername(username);

return getAuthorities(user.getRoles());
}

private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {

return getGrantedAuthorities(getPermissions(roles));
}

private List<String> getPermissions(Collection<Role> roles) {

List<String> permissions = new ArrayList<>();
List<Permission> collection = new ArrayList<>();
for (Role role : roles) {
collection.addAll(role.getPermissions());
}
for (Permission item : collection) {
permissions.add(item.getName());
}
return permissions;
}

private List<GrantedAuthority> getGrantedAuthorities(List<String> permissions) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String permission : permissions) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return authorities;
}
}


Then i'm trying to annotate my endpoint with @PreAuthorize



@PostMapping("/doSomething")
@PreAuthorize("hasRole('doSomething')")
public SomeEntity createComment(@RequestBody SomeEntity something) {
...
}


I have user with role of USER, this role doesn't have permission to doSomething, however it seems like @PreAuthorize("hasRole('doSomething')") is not working. I'm not sure what i have done wrong, coule you please point my mistake?



Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based.



What would be correct way to authorize access to endpoint with RBAC approach?










share|improve this question

























  • Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

    – dur
    Nov 22 '18 at 12:30











  • @dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

    – Akka Jaworek
    Nov 22 '18 at 13:00











  • Possible duplicate of stackoverflow.com/questions/44004977/…

    – dur
    Nov 22 '18 at 20:49














0












0








0








im trying to secure my endpoints with role based access control. I have implemented the whole structure as well as CustomUserDetailService, however im not sure how should i enforce these rules on enpoints, i was looking for some nice annotation based evaluation like @PreAuthorize(hasRole('role')). My structure looks follwoing:



Permission:



@Entity
public class Permission implements GrantedAuthority {

@Id
private Long id;

@Column(name = "NAME")
private String name;

@ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)
private Collection<Role> roles;

@Override
public String getAuthority() {
return name;
}


Role:



@Entity
public class Role implements GrantedAuthority {

@Id @Column(name="ID" )
private Long id;

@Column(name="NAME", nullable=false , unique=false)
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "role_x_permission",
joinColumns = @JoinColumn(
name = "role_id"),
inverseJoinColumns = @JoinColumn(
name = "permission_id"))
private List<Permission> permissions;

@Override
public String getAuthority() {
return name;
}


User:



@Entity(name = "User")
@Table(name = "USERS")
@Data
public class User {

@Id
private Long id;

@Column(name="LOGIN" , nullable=true , unique=false)
private String login;

@Column(name="PASSWORD" , nullable=false , unique=false)
private String password;

@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name = "USER_ROLES",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;


Now i have defined my CustomUserDetailsService:



@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserRepository userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User applicationUser = userRepository.findByUsername(username);
if (applicationUser.getId() == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(applicationUser.getLogin(), applicationUser.getPassword(),
getAuthorities(applicationUser.getRoles()));
}

@Transactional
public Collection<? extends GrantedAuthority> getUserAuthorities(String username) {
User user = userRepository.findByUsername(username);

return getAuthorities(user.getRoles());
}

private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {

return getGrantedAuthorities(getPermissions(roles));
}

private List<String> getPermissions(Collection<Role> roles) {

List<String> permissions = new ArrayList<>();
List<Permission> collection = new ArrayList<>();
for (Role role : roles) {
collection.addAll(role.getPermissions());
}
for (Permission item : collection) {
permissions.add(item.getName());
}
return permissions;
}

private List<GrantedAuthority> getGrantedAuthorities(List<String> permissions) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String permission : permissions) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return authorities;
}
}


Then i'm trying to annotate my endpoint with @PreAuthorize



@PostMapping("/doSomething")
@PreAuthorize("hasRole('doSomething')")
public SomeEntity createComment(@RequestBody SomeEntity something) {
...
}


I have user with role of USER, this role doesn't have permission to doSomething, however it seems like @PreAuthorize("hasRole('doSomething')") is not working. I'm not sure what i have done wrong, coule you please point my mistake?



Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based.



What would be correct way to authorize access to endpoint with RBAC approach?










share|improve this question
















im trying to secure my endpoints with role based access control. I have implemented the whole structure as well as CustomUserDetailService, however im not sure how should i enforce these rules on enpoints, i was looking for some nice annotation based evaluation like @PreAuthorize(hasRole('role')). My structure looks follwoing:



Permission:



@Entity
public class Permission implements GrantedAuthority {

@Id
private Long id;

@Column(name = "NAME")
private String name;

@ManyToMany(mappedBy = "permissions", fetch = FetchType.LAZY)
private Collection<Role> roles;

@Override
public String getAuthority() {
return name;
}


Role:



@Entity
public class Role implements GrantedAuthority {

@Id @Column(name="ID" )
private Long id;

@Column(name="NAME", nullable=false , unique=false)
private String name;

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "role_x_permission",
joinColumns = @JoinColumn(
name = "role_id"),
inverseJoinColumns = @JoinColumn(
name = "permission_id"))
private List<Permission> permissions;

@Override
public String getAuthority() {
return name;
}


User:



@Entity(name = "User")
@Table(name = "USERS")
@Data
public class User {

@Id
private Long id;

@Column(name="LOGIN" , nullable=true , unique=false)
private String login;

@Column(name="PASSWORD" , nullable=false , unique=false)
private String password;

@ManyToMany( fetch = FetchType.LAZY)
@JoinTable(name = "USER_ROLES",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;


Now i have defined my CustomUserDetailsService:



@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserRepository userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User applicationUser = userRepository.findByUsername(username);
if (applicationUser.getId() == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(applicationUser.getLogin(), applicationUser.getPassword(),
getAuthorities(applicationUser.getRoles()));
}

@Transactional
public Collection<? extends GrantedAuthority> getUserAuthorities(String username) {
User user = userRepository.findByUsername(username);

return getAuthorities(user.getRoles());
}

private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {

return getGrantedAuthorities(getPermissions(roles));
}

private List<String> getPermissions(Collection<Role> roles) {

List<String> permissions = new ArrayList<>();
List<Permission> collection = new ArrayList<>();
for (Role role : roles) {
collection.addAll(role.getPermissions());
}
for (Permission item : collection) {
permissions.add(item.getName());
}
return permissions;
}

private List<GrantedAuthority> getGrantedAuthorities(List<String> permissions) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String permission : permissions) {
authorities.add(new SimpleGrantedAuthority(permission));
}
return authorities;
}
}


Then i'm trying to annotate my endpoint with @PreAuthorize



@PostMapping("/doSomething")
@PreAuthorize("hasRole('doSomething')")
public SomeEntity createComment(@RequestBody SomeEntity something) {
...
}


I have user with role of USER, this role doesn't have permission to doSomething, however it seems like @PreAuthorize("hasRole('doSomething')") is not working. I'm not sure what i have done wrong, coule you please point my mistake?



Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based.



What would be correct way to authorize access to endpoint with RBAC approach?







java spring spring-security rbac






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 22 '18 at 9:34









CS_noob

4091311




4091311










asked Nov 22 '18 at 9:25









Akka JaworekAkka Jaworek

4482418




4482418













  • Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

    – dur
    Nov 22 '18 at 12:30











  • @dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

    – Akka Jaworek
    Nov 22 '18 at 13:00











  • Possible duplicate of stackoverflow.com/questions/44004977/…

    – dur
    Nov 22 '18 at 20:49



















  • Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

    – dur
    Nov 22 '18 at 12:30











  • @dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

    – Akka Jaworek
    Nov 22 '18 at 13:00











  • Possible duplicate of stackoverflow.com/questions/44004977/…

    – dur
    Nov 22 '18 at 20:49

















Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

– dur
Nov 22 '18 at 12:30





Also, since im using RBAC this hasRole is very missleading since access is permission based, not role based. That is confusing, because RBAC means Role Based Access Control and hasRole is the right way to implement it. However, you also not using permissions, because permissions (Spring wording) is part of ACL.

– dur
Nov 22 '18 at 12:30













@dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

– Akka Jaworek
Nov 22 '18 at 13:00





@dur lets assume that for now that Permission is only for RBAC in my case. If i understood RBAC properly, each enpoint can have a permission, and the a role has set of permissions. Then hasRole needs to refer to permission correct?

– Akka Jaworek
Nov 22 '18 at 13:00













Possible duplicate of stackoverflow.com/questions/44004977/…

– dur
Nov 22 '18 at 20:49





Possible duplicate of stackoverflow.com/questions/44004977/…

– dur
Nov 22 '18 at 20:49












1 Answer
1






active

oldest

votes


















0














You should use hasAuthority('doSomething') instead of hasRole('doSomething').



Role is just a permission with a prefix Role_.



So hasRole('XXX') is same as hasAuthority('ROLE_XXX')






share|improve this answer


























  • this did not solve the problem, user is still able to doSomrthing

    – Akka Jaworek
    Nov 22 '18 at 12:38











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427611%2fpermission-based-access-control-in-spring%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You should use hasAuthority('doSomething') instead of hasRole('doSomething').



Role is just a permission with a prefix Role_.



So hasRole('XXX') is same as hasAuthority('ROLE_XXX')






share|improve this answer


























  • this did not solve the problem, user is still able to doSomrthing

    – Akka Jaworek
    Nov 22 '18 at 12:38
















0














You should use hasAuthority('doSomething') instead of hasRole('doSomething').



Role is just a permission with a prefix Role_.



So hasRole('XXX') is same as hasAuthority('ROLE_XXX')






share|improve this answer


























  • this did not solve the problem, user is still able to doSomrthing

    – Akka Jaworek
    Nov 22 '18 at 12:38














0












0








0







You should use hasAuthority('doSomething') instead of hasRole('doSomething').



Role is just a permission with a prefix Role_.



So hasRole('XXX') is same as hasAuthority('ROLE_XXX')






share|improve this answer















You should use hasAuthority('doSomething') instead of hasRole('doSomething').



Role is just a permission with a prefix Role_.



So hasRole('XXX') is same as hasAuthority('ROLE_XXX')







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 22 '18 at 11:52

























answered Nov 22 '18 at 11:47









chaoluochaoluo

1,5481916




1,5481916













  • this did not solve the problem, user is still able to doSomrthing

    – Akka Jaworek
    Nov 22 '18 at 12:38



















  • this did not solve the problem, user is still able to doSomrthing

    – Akka Jaworek
    Nov 22 '18 at 12:38

















this did not solve the problem, user is still able to doSomrthing

– Akka Jaworek
Nov 22 '18 at 12:38





this did not solve the problem, user is still able to doSomrthing

– Akka Jaworek
Nov 22 '18 at 12:38


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53427611%2fpermission-based-access-control-in-spring%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

404 Error Contact Form 7 ajax form submitting

How to know if a Active Directory user can login interactively

Refactoring coordinates for Minecraft Pi buildings written in Python