Florian
Florian

Reputation: 5071

Can I calculate user authorization with Spring's hasAuthority without throwing/catching an exception?

My Java application uses Spring's @PreAuthorize("hasAuthority('SomeScopeName')") on methods to assert that the user is authorized to perform the actions in the methods. This annotation throws an AccessDeniedException if the user is unauthorized:

@Override
@PreAuthorize("hasAuthority('SomeScopeName')")
public void assertHasDisplayAuthorization() {
    // empty on purpose
}

One of the application's endpoints wants to inform the user interface about which actions the user is able to perform. For that, it calculates an Authorizations object that renders as JSON like { canDisplay: true, canEdit: false, ... }:

public Authorizations getAuthorizations() {
    return new Authorizations(hasDisplayAuthorization(), hasEditAuthorization(), ...);
}

That calculation calls the @PreAuthorize'd methods to determine the user's authorization:

private boolean hasDisplayAuthorization() {
    try {
        validator.assertHasDisplayAuthorization();
        return true;
    } catch (AccessDeniedException e) {
        return false;
    }
}

This works, but I don't like the fact that I need to throw and catch an exception just to calculate a simple true/false.

Is there a possibility to calculate the Authorizations object without having to throw exceptions?

For example, would it be possible and reliable to calculate the authorization in an @Value annotation and just assign it to an object attribute?

@Value("hasAuthority('SomeScopeName')")
boolean canDisplay;

... return new Authorizations(canDisplay, ...);

Upvotes: 0

Views: 44

Answers (1)

Toni
Toni

Reputation: 5145

Instead of using @PreAuthorize, you can do it manually using the following class:

public class SecurityHelper {
  public static boolean hasAuthority(String authority) {
    Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
    return authorities.contains(new SimpleGrantedAuthority(authority));
  }
}

Then, you can define an additional class with methods for checking each scope, for example:

public class AuthorityChecker {
  public static boolean hasDisplayAuthorization(){
    return SecurityHelper.hasAuthority("SomeScopeName");
  }
  //...
}

Keep in mind, that it will work as long as SecurityContext is available in the current thread, otherwise, it will throw an exception.

Upvotes: 1

Related Questions