From 1509a987eb416fc977b715413874f53c9174335e Mon Sep 17 00:00:00 2001 From: Roman Zabaluev Date: Sat, 10 Feb 2024 12:51:29 +0700 Subject: [PATCH] Impl custom rolePrefix in LdapUserDetailsManager Closes gh-2083 --- .../LdapUserDetailsManagerTests.java | 36 ++++++++++++++++++- .../userdetails/LdapUserDetailsManager.java | 14 ++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) 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 63d7bba4ea..864843a4d2 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 @@ import static org.mockito.Mockito.verify; /** * @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 class LdapUserDetailsManagerTests { .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 a1487b6665..cb3d4c3ff0 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 class LdapUserDetailsManager implements UserDetailsManager { 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,