diff --git a/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java b/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java index 98dbbe0e52..5c7165bde5 100644 --- a/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java +++ b/core/src/main/java/org/springframework/security/core/authority/AuthorityUtils.java @@ -22,6 +22,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Stream; import org.springframework.security.core.GrantedAuthority; import org.springframework.util.Assert; @@ -39,6 +40,8 @@ public final class AuthorityUtils { public static final List NO_AUTHORITIES = Collections.emptyList(); + private static String[] KNOWN_PREFIXES = { "ROLE_", "SCOPE_", "FACTOR_" }; + private AuthorityUtils() { } @@ -93,4 +96,38 @@ public final class AuthorityUtils { return grantedAuthorities; } + /** + * Return a {@link Stream} containing only the authorities of the given type; + * {@code "ROLE"}, {@code "SCOPE"}, or {@code "FACTOR"}. + * @param type the authority type; {@code "ROLE"}, {@code "SCOPE"}, or + * {@code "FACTOR"} + * @param authorities the list of authorities + * @return a {@link Stream} containing the authorities of the given type + */ + public static Stream authoritiesOfType(String type, Collection authorities) { + return authorities.stream().filter((a) -> a.getAuthority().startsWith(type + "_")); + } + + /** + * Return the simple name of a {@link GrantedAuthority}, which is its name, less any + * common prefix; that is, {@code ROLE_}, {@code SCOPE_}, or {@code FACTOR_}. + *

+ * For example, if the authority is {@code ROLE_USER}, then the simple name is + * {@code user}. + *

+ * If the authority is {@code FACTOR_PASSWORD}, then the simple name is + * {@code password}. + * @param authority the granted authority + * @return the simple name of the authority + */ + public static String getSimpleName(GrantedAuthority authority) { + String name = authority.getAuthority(); + for (String prefix : KNOWN_PREFIXES) { + if (name.startsWith(prefix)) { + return name.substring(prefix.length()); + } + } + return name; + } + } diff --git a/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java b/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java index 77ab2e4210..0fa6643b5c 100644 --- a/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java +++ b/core/src/test/java/org/springframework/security/core/authority/AuthorityUtilsTests.java @@ -54,4 +54,38 @@ public class AuthorityUtilsTests { assertThat(authorities).element(2).extracting(GrantedAuthority::getAuthority).isEqualTo("ROLE_C"); } + @Test + public void getSimpleNameWhenRoleThenRemovesPrefix() { + GrantedAuthority role = new SimpleGrantedAuthority("ROLE_ADMIN"); + assertThat(AuthorityUtils.getSimpleName(role)).isEqualTo("ADMIN"); + } + + @Test + public void getSimpleNameWhenScopeThenRemovesPrefix() { + GrantedAuthority role = new SimpleGrantedAuthority("SCOPE_message:read"); + assertThat(AuthorityUtils.getSimpleName(role)).isEqualTo("message:read"); + } + + @Test + public void getSimpleNameWhenFactorThenRemovesPrefix() { + GrantedAuthority role = new SimpleGrantedAuthority("FACTOR_PASSWORD"); + assertThat(AuthorityUtils.getSimpleName(role)).isEqualTo("PASSWORD"); + } + + @Test + public void authoritiesOfTypeWhenEmptyThenReturnsEmptyStream() { + List authorities = AuthorityUtils.createAuthorityList("ROLE_USER"); + List factors = AuthorityUtils.authoritiesOfType("FACTOR", authorities).toList(); + assertThat(factors).isEmpty(); + } + + @Test + public void authoritiesOfTypeWhenFactorsThenReturnsOnlyFactors() { + List authorities = AuthorityUtils.createAuthorityList("ROLE_USER", "FACTOR_PASSWORD", + "FACTOR_OTT"); + List factors = AuthorityUtils.authoritiesOfType("FACTOR", authorities).toList(); + assertThat(factors).extracting(GrantedAuthority::getAuthority) + .containsExactlyInAnyOrder("FACTOR_PASSWORD", "FACTOR_OTT"); + } + }