From 50bdaeb1001b04b269dfe5968b3c2ef3856053fd Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Mon, 22 Sep 2025 11:42:14 -0600 Subject: [PATCH] Add AuthorityUtils Methods This commit adds a couple of utility methods for working with authorities by type. Now that there are infrastructural authorities that Spring Secuirty works with directly, it's helpful to be able to filter them out of the authority list. --- .../core/authority/AuthorityUtils.java | 37 +++++++++++++++++++ .../core/authority/AuthorityUtilsTests.java | 34 +++++++++++++++++ 2 files changed, 71 insertions(+) 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"); + } + }