diff --git a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java index 63d7bba4eac..864843a4d2d 100644 --- a/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java +++ b/ldap/src/integration-test/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManagerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited + * Copyright 2004-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,6 +49,7 @@ /** * @author Luke Taylor * @author EddĂș MelĂ©ndez + * @author Roman Zabaluev */ @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = ApacheDsContainerConfig.class) @@ -60,6 +61,8 @@ public class LdapUserDetailsManagerTests { private static final List TEST_AUTHORITIES = AuthorityUtils.createAuthorityList("ROLE_CLOWNS", "ROLE_ACROBATS"); + private static final String DEFAULT_ROLE_PREFIX = "ROLE_"; + private LdapUserDetailsManager mgr; private SpringSecurityLdapTemplate template; @@ -248,4 +251,35 @@ public void testPasswordChangeWithWrongOldPasswordFails() { .isThrownBy(() -> this.mgr.changePassword("wrongpassword", "yossariansnewpassword")); } + @Test + public void testRoleNamesStartWithDefaultRolePrefix() { + this.mgr.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=people", "uid")); + this.mgr.setGroupSearchBase("ou=groups"); + LdapUserDetails bob = (LdapUserDetails) this.mgr.loadUserByUsername("bob"); + + assertThat(bob.getAuthorities()).isNotEmpty(); + + bob.getAuthorities() + .stream() + .map(GrantedAuthority::getAuthority) + .forEach((authority) -> assertThat(authority).startsWith(DEFAULT_ROLE_PREFIX)); + } + + @Test + public void testRoleNamesStartWithCustomRolePrefix() { + var customPrefix = "GROUP_"; + this.mgr.setRolePrefix(customPrefix); + + this.mgr.setUsernameMapper(new DefaultLdapUsernameToDnMapper("ou=people", "uid")); + this.mgr.setGroupSearchBase("ou=groups"); + LdapUserDetails bob = (LdapUserDetails) this.mgr.loadUserByUsername("bob"); + + assertThat(bob.getAuthorities()).isNotEmpty(); + + bob.getAuthorities() + .stream() + .map(GrantedAuthority::getAuthority) + .forEach((authority) -> assertThat(authority).startsWith(customPrefix)); + } + } diff --git a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java index a1487b66653..cb3d4c3ff08 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java +++ b/ldap/src/main/java/org/springframework/security/ldap/userdetails/LdapUserDetailsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -104,7 +104,7 @@ public class LdapUserDetailsManager implements UserDetailsManager { /** The attribute which contains members of a group */ private String groupMemberAttributeName = "uniquemember"; - private final String rolePrefix = "ROLE_"; + private String rolePrefix = "ROLE_"; /** The pattern to be used for the user search. {0} is the user's DN */ private String groupSearchFilter = "(uniquemember={0})"; @@ -403,6 +403,16 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy secur this.securityContextHolderStrategy = securityContextHolderStrategy; } + /** + * Sets the role prefix used when converting authorities. The default value is "ROLE_" + * @param rolePrefix role prefix + * @since 6.3 + */ + public void setRolePrefix(String rolePrefix) { + Assert.notNull(rolePrefix, "A rolePrefix must be supplied"); + this.rolePrefix = rolePrefix; + } + private void changePasswordUsingAttributeModification(DistinguishedName userDn, String oldPassword, String newPassword) { ModificationItem[] passwordChange = new ModificationItem[] { new ModificationItem(DirContext.REPLACE_ATTRIBUTE,