From edd3796ddb178a1258ebeaa767a66f9dc933b5bf Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:31:12 +0200 Subject: [PATCH 01/24] Add field for origin to LdapLoginAuthenticationManager --- .../manager/LdapLoginAuthenticationManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 1be6a778dfe..5b65b8c737e 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -50,6 +50,8 @@ public class LdapLoginAuthenticationManager extends ExternalLoginAuthenticationM protected static Logger logger = LoggerFactory.getLogger(LdapLoginAuthenticationManager.class); + private String origin = OriginKeys.LDAP; + public LdapLoginAuthenticationManager(final @Qualifier("identityProviderProvisioning") IdentityProviderProvisioning providerProvisioning) { super(providerProvisioning); } @@ -175,4 +177,9 @@ protected boolean isAddNewShadowUser() { } return result; } + + @Override + public void setOrigin(final String origin) { + this.origin = origin; + } } From e682f6390d62cd0e8dbeb4e0af19c749bb4498a6 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 18:42:55 +0200 Subject: [PATCH 02/24] Add 'origin' parameter to ExternalLoginAuthenticationManager#generateEmailIfNullOrEmpty --- .../manager/ExternalLoginAuthenticationManager.java | 6 +++--- .../manager/LdapLoginAuthenticationManager.java | 7 ------- .../provider/oauth/ExternalOAuthAuthenticationManager.java | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 26103d3df38..987f95f9466 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -219,7 +219,7 @@ protected UaaUser getUser(Authentication request, ExternalAuthenticationDetails } if (UaaStringUtils.isEmpty(email)) { - email = generateEmailIfNullOrEmpty(name); + email = generateEmailIfNullOrEmpty(name, getOrigin()); } String givenName = null; @@ -250,12 +250,12 @@ protected UaaUser getUser(Authentication request, ExternalAuthenticationDetails return new UaaUser(userPrototype); } - protected final String generateEmailIfNullOrEmpty(String name) { + protected static String generateEmailIfNullOrEmpty(final String name, final String origin) { if (name == null) { throw new BadCredentialsException("Cannot determine username from credentials supplied"); } - final String fallbackEmailDomain = FALLBACK_EMAIL_DOMAIN_TEMPLATE.formatted(getOrigin()); + final String fallbackEmailDomain = FALLBACK_EMAIL_DOMAIN_TEMPLATE.formatted(origin); // use fallback domain if no '@' is present if (!name.contains("@")) { diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 5b65b8c737e..d4b32376133 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -56,8 +56,6 @@ public LdapLoginAuthenticationManager(final @Qualifier("identityProviderProvisio super(providerProvisioning); } - private String origin = OriginKeys.LDAP; - @Override public String getOrigin() { return origin; @@ -177,9 +175,4 @@ protected boolean isAddNewShadowUser() { } return result; } - - @Override - public void setOrigin(final String origin) { - this.origin = origin; - } } diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index 6dcfd9d3e51..0ea22b2d80f 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -460,7 +460,7 @@ protected UaaUser getUser(Authentication request, AuthenticationData authenticat boolean verified = verifiedObj instanceof Boolean b ? b : false; if (!StringUtils.hasText(email)) { - email = generateEmailIfNullOrEmpty(username); + email = generateEmailIfNullOrEmpty(username, getOrigin()); } log.debug("Returning user data for username:{}, email:{}", username, email); From 623e04d9c1fd06e47b6ac3ac00b878e48e846434 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 18:48:02 +0200 Subject: [PATCH 03/24] Add 'origin' parameter to ExternalLoginAuthenticationManager#isAddNewShadowUser and all overrides --- .../manager/ExternalLoginAuthenticationManager.java | 4 ++-- .../manager/LdapLoginAuthenticationManager.java | 4 ++-- .../provider/oauth/ExternalOAuthAuthenticationManager.java | 4 ++-- .../manager/ExternalLoginAuthenticationManagerTest.java | 4 ++-- .../manager/LdapLoginAuthenticationManagerTests.java | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 987f95f9466..3a5ff602bc5 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -113,7 +113,7 @@ public Authentication authenticate(Authentication request) throws Authentication // Register new users automatically if (userFromDb == null) { - if (!isAddNewShadowUser()) { + if (!isAddNewShadowUser(getOrigin())) { throw new AccountNotPreCreatedException("The user account must be pre-created. Please contact your system administrator."); } publish(new NewUserAuthenticatedEvent(userFromRequest.authorities(List.of()))); @@ -174,7 +174,7 @@ private boolean hasUserAttributes(UaaAuthentication authentication) { protected abstract ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException; - protected abstract boolean isAddNewShadowUser(); + protected abstract boolean isAddNewShadowUser(final String origin); protected MultiValueMap getUserAttributes(UserDetails request) { return new LinkedMultiValueMap<>(); diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index d4b32376133..c61225f9317 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -164,10 +164,10 @@ protected boolean isAutoAddAuthorities() { } @Override - protected boolean isAddNewShadowUser() { + protected boolean isAddNewShadowUser(final String origin) { boolean result = true; if (getProviderProvisioning() != null) { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(origin, IdentityZoneHolder.get().getId()); LdapIdentityProviderDefinition ldapIdentityProviderDefinition = ObjectUtils.castInstance(provider.getConfig(), LdapIdentityProviderDefinition.class); if (ldapIdentityProviderDefinition != null) { result = ldapIdentityProviderDefinition.isAddShadowUserOnLogin(); diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index 0ea22b2d80f..f4d71c4ce03 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -597,8 +597,8 @@ private boolean isRegisteredIdpAuthentication(Authentication request) { } @Override - protected boolean isAddNewShadowUser() { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), identityZoneManager.getCurrentIdentityZoneId()); + protected boolean isAddNewShadowUser(final String origin) { + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(origin, identityZoneManager.getCurrentIdentityZoneId()); return provider.getConfig().isAddShadowUserOnLogin(); } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 8b19c36a5b1..296ecc4d70d 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -122,7 +122,7 @@ protected Object getExternalAuthenticationDetails(Authentication authentication) } @Override - protected boolean isAddNewShadowUser() { + protected boolean isAddNewShadowUser(String origin) { return true; } @@ -376,7 +376,7 @@ void shadowUserCreationDisabled() { when(ldapUserDetails.getDn()).thenReturn(dn); manager = new LdapLoginAuthenticationManager(null) { @Override - protected boolean isAddNewShadowUser() { + protected boolean isAddNewShadowUser(final String origin) { return false; } }; diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java index 04ae27aeff9..96a0b0515f0 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java @@ -174,7 +174,7 @@ void userAuthenticated() { @Test void shadowUserCreationDisabledWillNotAddShadowUser() { definition.setAddShadowUserOnLogin(false); - assertThat(am.isAddNewShadowUser()).isFalse(); + assertThat(am.isAddNewShadowUser(origin)).isFalse(); } @Test From fee358d0d2f279d0fa95f793bce0bf71fca3afa6 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:06:45 +0200 Subject: [PATCH 04/24] Rename type parameter of ExternalLoginAuthenticationManager --- .../manager/ExternalLoginAuthenticationManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 3a5ff602bc5..85d30b0f9ec 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -54,7 +54,7 @@ import static java.util.Collections.emptySet; -public abstract class ExternalLoginAuthenticationManager implements AuthenticationManager, ApplicationEventPublisherAware, BeanNameAware { +public abstract class ExternalLoginAuthenticationManager implements AuthenticationManager, ApplicationEventPublisherAware, BeanNameAware { public static final String USER_ATTRIBUTE_PREFIX = "user.attribute."; private static final String FALLBACK_EMAIL_DOMAIN_TEMPLATE = "user.from.%s.cf"; @@ -95,7 +95,7 @@ public Authentication authenticate(Authentication request) throws Authentication if (logger.isDebugEnabled()) { logger.debug("Starting external authentication for:{}", UaaStringUtils.getCleanedUserControlString(request.toString())); } - ExternalAuthenticationDetails authenticationData = getExternalAuthenticationDetails(request); + EAD authenticationData = getExternalAuthenticationDetails(request); UaaUser userFromRequest = getUser(request, authenticationData); if (userFromRequest == null) { return null; @@ -139,7 +139,7 @@ public Authentication authenticate(Authentication request) throws Authentication return success; } - protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, ExternalAuthenticationDetails authenticationData) { + protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, EAD authenticationData) { if (request.getPrincipal() instanceof UserDetails userDetails) { authentication.setUserAttributes(getUserAttributes(userDetails)); authentication.setExternalGroups(new HashSet<>(getExternalUserAuthorities(userDetails))); @@ -172,7 +172,7 @@ private boolean hasUserAttributes(UaaAuthentication authentication) { return authentication.getUserAttributes() != null && !authentication.getUserAttributes().isEmpty(); } - protected abstract ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException; + protected abstract EAD getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException; protected abstract boolean isAddNewShadowUser(final String origin); @@ -190,7 +190,7 @@ protected final void publish(ApplicationEvent event) { protected abstract UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb); - protected UaaUser getUser(Authentication request, ExternalAuthenticationDetails authDetails) { + protected UaaUser getUser(Authentication request, EAD authDetails) { UserDetails userDetails; if (request.getPrincipal() instanceof UserDetails) { userDetails = (UserDetails) request.getPrincipal(); From 6fc3f4cd11bb0eee8c437fc1115f82fd215b5938 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:08:11 +0200 Subject: [PATCH 05/24] Extract variable for origin in ExternalLoginAuthenticationManager#authenticate --- .../ExternalLoginAuthenticationManager.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 85d30b0f9ec..fb7840adbda 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -95,7 +95,10 @@ public Authentication authenticate(Authentication request) throws Authentication if (logger.isDebugEnabled()) { logger.debug("Starting external authentication for:{}", UaaStringUtils.getCleanedUserControlString(request.toString())); } + EAD authenticationData = getExternalAuthenticationDetails(request); + final String origin = getOrigin(); + UaaUser userFromRequest = getUser(request, authenticationData); if (userFromRequest == null) { return null; @@ -104,21 +107,21 @@ public Authentication authenticate(Authentication request) throws Authentication UaaUser userFromDb; try { - logger.debug("Searching for user by (username:{} , origin:{})", userFromRequest.getUsername(), getOrigin()); - userFromDb = userDatabase.retrieveUserByName(userFromRequest.getUsername(), getOrigin()); + logger.debug("Searching for user by (username:{} , origin:{})", userFromRequest.getUsername(), origin); + userFromDb = userDatabase.retrieveUserByName(userFromRequest.getUsername(), origin); } catch (UsernameNotFoundException e) { - logger.debug("Searching for user by (email:{} , origin:{})", userFromRequest.getEmail(), getOrigin()); - userFromDb = userDatabase.retrieveUserByEmail(userFromRequest.getEmail(), getOrigin()); + logger.debug("Searching for user by (email:{} , origin:{})", userFromRequest.getEmail(), origin); + userFromDb = userDatabase.retrieveUserByEmail(userFromRequest.getEmail(), origin); } // Register new users automatically if (userFromDb == null) { - if (!isAddNewShadowUser(getOrigin())) { + if (!isAddNewShadowUser(origin)) { throw new AccountNotPreCreatedException("The user account must be pre-created. Please contact your system administrator."); } publish(new NewUserAuthenticatedEvent(userFromRequest.authorities(List.of()))); try { - userFromDb = userDatabase.retrieveUserByName(userFromRequest.getUsername(), getOrigin()); + userFromDb = userDatabase.retrieveUserByName(userFromRequest.getUsername(), origin); } catch (UsernameNotFoundException ex) { throw new BadCredentialsException("Unable to register user in internal UAA store."); } From 995682ad5f8c3ffe5bd5f0de4723a2c32c79efea Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:12:31 +0200 Subject: [PATCH 06/24] Add 'origin' parameter to LdapLoginAuthenticationManager#isAutoAddAuthorities --- .../manager/LdapLoginAuthenticationManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index c61225f9317..55c58ec3d7d 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -146,15 +146,15 @@ protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequ userModified = true; } } - ExternalGroupAuthorizationEvent event = new ExternalGroupAuthorizationEvent(userFromDb, userModified, request.getAuthorities(), isAutoAddAuthorities()); + ExternalGroupAuthorizationEvent event = new ExternalGroupAuthorizationEvent(userFromDb, userModified, request.getAuthorities(), isAutoAddAuthorities(getOrigin())); publish(event); return getUserDatabase().retrieveUserById(userFromDb.getId()); } - protected boolean isAutoAddAuthorities() { + protected boolean isAutoAddAuthorities(final String origin) { Boolean result = true; if (getProviderProvisioning() != null) { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(origin, IdentityZoneHolder.get().getId()); LdapIdentityProviderDefinition ldapIdentityProviderDefinition = ObjectUtils.castInstance(provider.getConfig(), LdapIdentityProviderDefinition.class); if (ldapIdentityProviderDefinition != null) { result = ldapIdentityProviderDefinition.isAutoAddGroups(); From b97e851fb2d0b3cdb291945d805cca308249ec27 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:15:03 +0200 Subject: [PATCH 07/24] Add base class for ExternalAuthenticationDetails --- .../ExternalLoginAuthenticationManager.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index fb7840adbda..37239fafb58 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -1,5 +1,8 @@ package org.cloudfoundry.identity.uaa.authentication.manager; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -313,4 +316,23 @@ protected final List evaluateExternalGroupMappings(Strin public void setBeanName(@NonNull String name) { this.name = name; } + + @Data + @Builder + @AllArgsConstructor + public static class ExternalAuthenticationDetails { + private String origin; + + public ExternalAuthenticationDetails() { + this.origin = "unknown"; + } + + public final String getOrigin() { + return origin; + } + + public final void setOrigin(final String origin) { + this.origin = origin; + } + } } From 115585b0521f696c84b0b337fcf228e7dd00e313 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:19:56 +0200 Subject: [PATCH 08/24] Add super class constraint to type parameter of ExternalLoginAuthenticationManager --- .../ExternalLoginAuthenticationManager.java | 2 +- .../manager/LdapLoginAuthenticationManager.java | 15 ++++++++------- .../oauth/ExternalOAuthAuthenticationManager.java | 4 +++- .../ExternalLoginAuthenticationManagerTest.java | 9 +++++---- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 37239fafb58..80780a53192 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -57,7 +57,7 @@ import static java.util.Collections.emptySet; -public abstract class ExternalLoginAuthenticationManager implements AuthenticationManager, ApplicationEventPublisherAware, BeanNameAware { +public abstract class ExternalLoginAuthenticationManager implements AuthenticationManager, ApplicationEventPublisherAware, BeanNameAware { public static final String USER_ATTRIBUTE_PREFIX = "user.attribute."; private static final String FALLBACK_EMAIL_DOMAIN_TEMPLATE = "user.from.%s.cf"; diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 55c58ec3d7d..4a23c3ca5e3 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -16,6 +16,7 @@ package org.cloudfoundry.identity.uaa.authentication.manager; import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; +import org.cloudfoundry.identity.uaa.authentication.manager.ExternalLoginAuthenticationManager.ExternalAuthenticationDetails; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.provider.IdentityProvider; import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning; @@ -46,7 +47,7 @@ import static java.util.Collections.emptyList; import static org.cloudfoundry.identity.uaa.util.UaaStringUtils.retainAllMatches; -public class LdapLoginAuthenticationManager extends ExternalLoginAuthenticationManager { +public class LdapLoginAuthenticationManager extends ExternalLoginAuthenticationManager { protected static Logger logger = LoggerFactory.getLogger(LdapLoginAuthenticationManager.class); @@ -68,16 +69,11 @@ public void setOrigin(String origin) { } @Override - protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, Object authenticationData) { + protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, ExternalAuthenticationDetails authenticationData) { super.populateAuthenticationAttributes(authentication, request, authenticationData); authentication.getAuthenticationMethods().add("pwd"); } - @Override - protected Object getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { - return null; - } - @Override protected MultiValueMap getUserAttributes(UserDetails request) { MultiValueMap result = super.getUserAttributes(request); @@ -175,4 +171,9 @@ protected boolean isAddNewShadowUser(final String origin) { } return result; } + + @Override + protected ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { + return ExternalAuthenticationDetails.builder().origin(origin).build(); + } } diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index f4d71c4ce03..b257e4982de 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -20,6 +20,7 @@ import com.nimbusds.jose.JWSHeader; import jakarta.servlet.http.HttpServletRequest; import lombok.Data; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; @@ -1034,7 +1035,8 @@ public String oauthTokenRequest(UaaAuthenticationDetails details, final Identity } @Data - protected static class AuthenticationData { + @EqualsAndHashCode(callSuper = true) + protected static class AuthenticationData extends ExternalAuthenticationDetails { private Map claims; private String username; diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 296ecc4d70d..350ad7d35fd 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -5,6 +5,7 @@ import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal; import org.cloudfoundry.identity.uaa.authentication.event.IdentityProviderAuthenticationSuccessEvent; +import org.cloudfoundry.identity.uaa.authentication.manager.ExternalLoginAuthenticationManager.ExternalAuthenticationDetails; import org.cloudfoundry.identity.uaa.provider.ExternalIdentityProviderDefinition; import org.cloudfoundry.identity.uaa.provider.IdentityProvider; import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning; @@ -60,7 +61,7 @@ class ExternalLoginAuthenticationManagerTest { private ApplicationEventPublisher applicationEventPublisher; private UaaUserDatabase uaaUserDatabase; private Authentication inputAuth; - private ExternalLoginAuthenticationManager manager; + private ExternalLoginAuthenticationManager manager; private final String origin = "test"; private UserDetails userDetails; private final String userName = "testUserName"; @@ -103,7 +104,7 @@ private void mockUaaWithUser() { inputAuth = mock(Authentication.class); when(inputAuth.getPrincipal()).thenReturn(userDetails); - manager = new ExternalLoginAuthenticationManager(null) { + manager = new ExternalLoginAuthenticationManager<>(null) { private String origin = "unknown"; @Override @@ -117,8 +118,8 @@ public void setOrigin(String origin) { } @Override - protected Object getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { - return null; + protected ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { + return ExternalAuthenticationDetails.builder().origin(origin).build(); } @Override From 3f4e371da81587df53bcb376dff9288c9bc3658d Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:28:04 +0200 Subject: [PATCH 09/24] Introduce variable for origin in ExternalOAuthAuthenticationManager#getExternalAuthenticationDetails --- .../provider/oauth/ExternalOAuthAuthenticationManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index b257e4982de..c2c396356a9 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -266,10 +266,11 @@ protected AuthenticationData getExternalAuthenticationDetails(final Authenticati codeToken.setOrigin(provider.getOriginKey()); } - setOrigin(codeToken.getOrigin()); + final String origin = codeToken.getOrigin(); + setOrigin(origin); if (provider == null) { try { - provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), identityZoneManager.getCurrentIdentityZoneId()); + provider = getProviderProvisioning().retrieveByOrigin(origin, identityZoneManager.getCurrentIdentityZoneId()); } catch (EmptyResultDataAccessException e) { logger.info("No provider found for given origin"); throw new InsufficientAuthenticationException("Could not resolve identity provider with given origin."); @@ -323,7 +324,7 @@ protected AuthenticationData getExternalAuthenticationDetails(final Authenticati return authenticationData; } - logger.debug("No identity provider found for origin:{} and zone:{}", getOrigin(), identityZoneManager.getCurrentIdentityZoneId()); + logger.debug("No identity provider found for origin:{} and zone:{}", origin, identityZoneManager.getCurrentIdentityZoneId()); return null; } From e75b552fe422f2ba5bfa78c87f6889eaada6e15e Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:38:15 +0200 Subject: [PATCH 10/24] Add parameter for authentication data to ExternalLoginAuthenticationManager#getUserAttributes and all overrides --- .../manager/ExternalLoginAuthenticationManager.java | 4 ++-- .../manager/LdapLoginAuthenticationManager.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 80780a53192..e6adbc900aa 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -147,7 +147,7 @@ public Authentication authenticate(Authentication request) throws Authentication protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, EAD authenticationData) { if (request.getPrincipal() instanceof UserDetails userDetails) { - authentication.setUserAttributes(getUserAttributes(userDetails)); + authentication.setUserAttributes(getUserAttributes(userDetails, authenticationData)); authentication.setExternalGroups(new HashSet<>(getExternalUserAuthorities(userDetails))); } @@ -182,7 +182,7 @@ private boolean hasUserAttributes(UaaAuthentication authentication) { protected abstract boolean isAddNewShadowUser(final String origin); - protected MultiValueMap getUserAttributes(UserDetails request) { + protected MultiValueMap getUserAttributes(UserDetails request, EAD authenticationData) { return new LinkedMultiValueMap<>(); } diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 4a23c3ca5e3..323d625805d 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -75,8 +75,8 @@ protected void populateAuthenticationAttributes(UaaAuthentication authentication } @Override - protected MultiValueMap getUserAttributes(UserDetails request) { - MultiValueMap result = super.getUserAttributes(request); + protected MultiValueMap getUserAttributes(UserDetails request, ExternalAuthenticationDetails authenticationData) { + MultiValueMap result = super.getUserAttributes(request, authenticationData); logger.debug("Mapping custom attributes for origin:{} and zone:{}", getOrigin(), IdentityZoneHolder.get().getId()); if (getProviderProvisioning() != null) { IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); From 1f1359cfff31181b2bdb093e117984b61f0c57f5 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:42:16 +0200 Subject: [PATCH 11/24] Add parameter for authentication data to ExternalLoginAuthenticationManager#getExternalUserAuthorities and all overrides --- .../ExternalLoginAuthenticationManager.java | 4 ++-- .../manager/LdapLoginAuthenticationManager.java | 2 +- .../ExternalOAuthAuthenticationManager.java | 2 +- .../ExternalLoginAuthenticationManagerTest.java | 2 +- .../LdapLoginAuthenticationManagerTests.java | 17 ++++++++++------- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index e6adbc900aa..6ff3b6cad0d 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -148,7 +148,7 @@ public Authentication authenticate(Authentication request) throws Authentication protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, EAD authenticationData) { if (request.getPrincipal() instanceof UserDetails userDetails) { authentication.setUserAttributes(getUserAttributes(userDetails, authenticationData)); - authentication.setExternalGroups(new HashSet<>(getExternalUserAuthorities(userDetails))); + authentication.setExternalGroups(new HashSet<>(getExternalUserAuthorities(userDetails, authenticationData))); } if (authentication.getAuthenticationMethods() == null) { @@ -186,7 +186,7 @@ protected MultiValueMap getUserAttributes(UserDetails request, E return new LinkedMultiValueMap<>(); } - protected abstract List getExternalUserAuthorities(UserDetails request); + protected abstract List getExternalUserAuthorities(UserDetails request, EAD authenticationData); protected final void publish(ApplicationEvent event) { if (eventPublisher != null) { diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 323d625805d..b0d9570a755 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -101,7 +101,7 @@ protected MultiValueMap getUserAttributes(UserDetails request, E } @Override - protected List getExternalUserAuthorities(UserDetails request) { + protected List getExternalUserAuthorities(UserDetails request, ExternalAuthenticationDetails authenticationData) { List result = new LinkedList<>(); if (getProviderProvisioning() != null) { IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index c2c396356a9..63ea00be9fa 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -437,7 +437,7 @@ protected void populateAuthenticationAttributes(UaaAuthentication authentication } @Override - protected List getExternalUserAuthorities(UserDetails request) { + protected List getExternalUserAuthorities(UserDetails request, AuthenticationData authenticationData) { return new LinkedList<>(); } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 350ad7d35fd..6ca4e60020e 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -128,7 +128,7 @@ protected boolean isAddNewShadowUser(String origin) { } @Override - protected List getExternalUserAuthorities(UserDetails request) { + protected List getExternalUserAuthorities(UserDetails request, ExternalAuthenticationDetails authenticationDetails) { return new LinkedList<>(); } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java index 96a0b0515f0..9e36bd4c5f2 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java @@ -1,6 +1,7 @@ package org.cloudfoundry.identity.uaa.authentication.manager; import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; +import org.cloudfoundry.identity.uaa.authentication.manager.ExternalLoginAuthenticationManager.ExternalAuthenticationDetails; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.extensions.PollutionPreventionExtension; import org.cloudfoundry.identity.uaa.provider.IdentityProvider; @@ -241,27 +242,29 @@ void group_white_list_with_wildcard() { ) ); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); + definition.setExternalGroupsWhitelist(emptyList()); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder(); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder(); definition.setExternalGroupsWhitelist(null); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder(); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder(); definition.setExternalGroupsWhitelist(Collections.singletonList("ldap.role.1.a")); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder("ldap.role.1.a"); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder("ldap.role.1.a"); definition.setExternalGroupsWhitelist(Arrays.asList("ldap.role.1.a", "ldap.role.2.*")); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.2.a", "ldap.role.2.b"); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.2.a", "ldap.role.2.b"); definition.setExternalGroupsWhitelist(Collections.singletonList("ldap.role.*.*")); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.2.a", "ldap.role.2.b"); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.2.a", "ldap.role.2.b"); definition.setExternalGroupsWhitelist(Arrays.asList("ldap.role.*.*", "ldap.role.*")); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.1", "ldap.role.2.a", "ldap.role.2.b", "ldap.role.2"); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.1", "ldap.role.2.a", "ldap.role.2.b", "ldap.role.2"); definition.setExternalGroupsWhitelist(Collections.singletonList("ldap*")); - assertThat(am.getExternalUserAuthorities(authDetails)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.1", "ldap.role.2.a", "ldap.role.2.b", "ldap.role.2"); + assertThat(am.getExternalUserAuthorities(authDetails, authenticationData)).containsExactlyInAnyOrder("ldap.role.1.a", "ldap.role.1.b", "ldap.role.1", "ldap.role.2.a", "ldap.role.2.b", "ldap.role.2"); } void test_authentication_attributes(boolean storeUserInfo) { From d2a7e21865d50c1775cc7d921a3c8e89874b5d5a Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:49:40 +0200 Subject: [PATCH 12/24] Add parameter for authentication data to ExternalLoginAuthenticationManager#userAuthenticated --- .../manager/ExternalLoginAuthenticationManager.java | 4 ++-- .../manager/LdapLoginAuthenticationManager.java | 2 +- .../oauth/ExternalOAuthAuthenticationManager.java | 2 +- .../ExternalLoginAuthenticationManagerTest.java | 2 +- .../manager/LdapLoginAuthenticationManagerTests.java | 11 +++++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 6ff3b6cad0d..c34186c87ec 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -131,7 +131,7 @@ public Authentication authenticate(Authentication request) throws Authentication } //user is authenticated and exists in UAA - UaaUser user = userAuthenticated(request, userFromRequest, userFromDb); + UaaUser user = userAuthenticated(request, userFromRequest, userFromDb, authenticationData); UaaAuthenticationDetails uaaAuthenticationDetails; if (request.getDetails() instanceof UaaAuthenticationDetails) { @@ -194,7 +194,7 @@ protected final void publish(ApplicationEvent event) { } } - protected abstract UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb); + protected abstract UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb, EAD authenticationData); protected UaaUser getUser(Authentication request, EAD authDetails) { UserDetails userDetails; diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index b0d9570a755..88c6e56c986 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -127,7 +127,7 @@ protected Set getAuthoritiesAsNames(Collection extractExternalOAuthUserAuthorities(Map getExternalUserAuthorities(UserDetails request, ExternalA } @Override - protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb) { + protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb, ExternalAuthenticationDetails authenticationDetails) { return userFromDb; } }; diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java index 9e36bd4c5f2..7acc1c7a426 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java @@ -160,14 +160,15 @@ void getUserWithNonLdapInfo() { @Test void userAuthenticated() { UaaUser user = getUaaUser(); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); UaaUser userFromRequest = am.getUser(auth, null); definition.setAutoAddGroups(true); - UaaUser result = am.userAuthenticated(auth, user, userFromRequest); + UaaUser result = am.userAuthenticated(auth, user, userFromRequest, authenticationData); assertThat(result).isSameAs(dbUser); verify(publisher, times(1)).publishEvent(ArgumentMatchers.any()); definition.setAutoAddGroups(false); - result = am.userAuthenticated(auth, userFromRequest, user); + result = am.userAuthenticated(auth, userFromRequest, user, authenticationData); assertThat(result).isSameAs(dbUser); verify(publisher, times(2)).publishEvent(ArgumentMatchers.any()); } @@ -184,8 +185,9 @@ void update_existingUser_if_attributes_different() { when(auth.getPrincipal()).thenReturn(authDetails); UaaUser user = getUaaUser(); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); UaaUser userFromRequest = am.getUser(auth, null); - am.userAuthenticated(auth, userFromRequest, user); + am.userAuthenticated(auth, userFromRequest, user, authenticationData); ArgumentCaptor captor = ArgumentCaptor.forClass(ExternalGroupAuthorizationEvent.class); verify(publisher, times(1)).publishEvent(captor.capture()); @@ -200,8 +202,9 @@ void dontUpdate_existingUser_if_attributes_same() { ExtendedLdapUserImpl authDetails = getAuthDetails(user.getEmail(), user.getGivenName(), user.getFamilyName(), user.getPhoneNumber()); when(auth.getPrincipal()).thenReturn(authDetails); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); UaaUser userFromRequest = am.getUser(auth, null); - am.userAuthenticated(auth, userFromRequest, user); + am.userAuthenticated(auth, userFromRequest, user, authenticationData); ArgumentCaptor captor = ArgumentCaptor.forClass(ExternalGroupAuthorizationEvent.class); verify(publisher, times(1)).publishEvent(captor.capture()); From f0220af3727dff716dae1e67dc0dd069daf1d55d Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:53:00 +0200 Subject: [PATCH 13/24] Set origin in authentication data in ExternalOAuthAuthenticationManager#getExternalAuthenticationDetails --- .../provider/oauth/ExternalOAuthAuthenticationManager.java | 1 + .../oauth/ExternalOAuthAuthenticationManagerIT.java | 6 +++--- .../token/TokenExchangeOverrideAuthManagerMockMvcTests.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index 5e540d6e0e4..a4e64967a7c 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -279,6 +279,7 @@ protected AuthenticationData getExternalAuthenticationDetails(final Authenticati if (provider != null && provider.getConfig() instanceof AbstractExternalOAuthIdentityProviderDefinition config) { final AuthenticationData authenticationData = new AuthenticationData(); + authenticationData.setOrigin(origin); final Map claims = getClaimsFromToken(codeToken, provider); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java index ee911071a4d..199f8132924 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java @@ -451,7 +451,7 @@ void when_exchanging_an_id_token_retrieved_from_the_internal_uaa_idp_for_an_acce assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); assertThat(externalAuthenticationDetails.getClaims()).containsEntry(ClaimConstants.ORIGIN, UAA_ORIGIN); - assertThat(externalOAuthAuthenticationManager.getOrigin()).isEqualTo(UAA_ORIGIN); + assertThat(externalAuthenticationDetails.getOrigin()).isEqualTo(UAA_ORIGIN); } @ParameterizedTest @@ -496,7 +496,7 @@ void when_exchanging_an_id_token_retrieved_by_uaa_via_an_oidc_idp_for_an_access_ assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); assertThat(externalAuthenticationDetails.getClaims()).containsEntry(ClaimConstants.ORIGIN, idpProvider.getOriginKey()); - assertThat(externalOAuthAuthenticationManager.getOrigin()).isEqualTo(idpProvider.getOriginKey()); + assertThat(externalAuthenticationDetails.getOrigin()).isEqualTo(idpProvider.getOriginKey()); } @Test @@ -521,7 +521,7 @@ void when_exchanging_an_id_token_retrieved_by_uaa_via_an_registered_oidc_idp_for assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); assertThat(externalAuthenticationDetails.getClaims()).containsEntry(ClaimConstants.ORIGIN, OriginKeys.UAA); - assertThat(externalOAuthAuthenticationManager.getOrigin()).isEqualTo(idpProvider.getOriginKey()); + assertThat(externalAuthenticationDetails.getOrigin()).isEqualTo(idpProvider.getOriginKey()); } @Test diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenExchangeOverrideAuthManagerMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenExchangeOverrideAuthManagerMockMvcTests.java index 05dd0a3d544..4e2a85c7485 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenExchangeOverrideAuthManagerMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/token/TokenExchangeOverrideAuthManagerMockMvcTests.java @@ -64,7 +64,7 @@ ExternalOAuthAuthenticationManager tokenExchangeAuthenticationManager( @Override public AuthenticationData getExternalAuthenticationDetails(Authentication authentication) { AuthenticationData result = super.getExternalAuthenticationDetails(authentication); - this.setOrigin("override-origin"); + result.setOrigin("override-origin"); return result; } From be4075a7f988dc43e7670af601b1a4c90a5e2131 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:55:39 +0200 Subject: [PATCH 14/24] Use authentication data object instead of null in ExternalLoginAuthenticationManagerTest#populateAttributesStoresCustomAttributesAndRoles --- .../ExternalLoginAuthenticationManagerTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 9606f76a4df..2773473accf 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -533,13 +533,16 @@ void populateAttributesStoresCustomAttributesAndRoles() { HashSet externalGroupsOnAuthentication = new HashSet<>(externalGroups); when(uaaAuthentication.getExternalGroups()).thenReturn(externalGroupsOnAuthentication); + final ExternalAuthenticationDetails authenticationDetails = mock(ExternalAuthenticationDetails.class); + when(authenticationDetails.getOrigin()).thenReturn(origin); + providerDefinition.setStoreCustomAttributes(false); - manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), null); + manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), authenticationDetails); verify(manager.getUserDatabase(), never()).storeUserInfo(anyString(), any()); // when there are both attributes and groups, store them providerDefinition.setStoreCustomAttributes(true); - manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), null); + manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), authenticationDetails); UserInfo userInfo = new UserInfo() .setUserAttributes(userAttributes) .setRoles(externalGroups); @@ -548,7 +551,7 @@ void populateAttributesStoresCustomAttributesAndRoles() { // when provider is null do not store anything reset(manager.getUserDatabase()); manager.setProviderProvisioning(null); - manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), null); + manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), authenticationDetails); verify(manager.getUserDatabase(), never()).storeUserInfo(anyString(), any()); manager.setProviderProvisioning(providerProvisioning); @@ -556,7 +559,7 @@ void populateAttributesStoresCustomAttributesAndRoles() { // when attributes is empty but roles have contents, store it reset(manager.getUserDatabase()); userAttributes.clear(); - manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), null); + manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), authenticationDetails); userInfo = new UserInfo() .setUserAttributes(userAttributes) .setRoles(externalGroups); @@ -566,7 +569,7 @@ void populateAttributesStoresCustomAttributesAndRoles() { reset(manager.getUserDatabase()); userAttributes.clear(); externalGroupsOnAuthentication.clear(); - manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), null); + manager.populateAuthenticationAttributes(uaaAuthentication, mock(Authentication.class), authenticationDetails); verify(manager.getUserDatabase(), never()).storeUserInfo(anyString(), any()); } From d2c042176457a2541b247c790e2105d35659bdba Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:57:15 +0200 Subject: [PATCH 15/24] Read origin from authentication data in ExternalOAuthAuthenticationManager#getUser --- .../provider/oauth/ExternalOAuthAuthenticationManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index a4e64967a7c..4a6a4791b82 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -463,7 +463,7 @@ protected UaaUser getUser(Authentication request, AuthenticationData authenticat boolean verified = verifiedObj instanceof Boolean b ? b : false; if (!StringUtils.hasText(email)) { - email = generateEmailIfNullOrEmpty(username, getOrigin()); + email = generateEmailIfNullOrEmpty(username, authenticationData.getOrigin()); } log.debug("Returning user data for username:{}, email:{}", username, email); @@ -479,7 +479,7 @@ protected UaaUser getUser(Authentication request, AuthenticationData authenticat .withPassword("") .withAuthorities(authenticationData.getAuthorities()) .withCreated(new Date()) - .withOrigin(getOrigin()) + .withOrigin(authenticationData.getOrigin()) .withExternalId((String) authenticationData.getClaims().get(SUB)) .withVerified(verified) .withZoneId(identityZoneManager.getCurrentIdentityZoneId()) From b6892ef56ffe197cda1e5c82afe98e116433e908 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:58:01 +0200 Subject: [PATCH 16/24] Read origin from authentication data in ExternalLoginAuthenticationManager#authenticate --- .../manager/ExternalLoginAuthenticationManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index c34186c87ec..5e227f1c4c3 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -100,7 +100,10 @@ public Authentication authenticate(Authentication request) throws Authentication } EAD authenticationData = getExternalAuthenticationDetails(request); - final String origin = getOrigin(); + if (authenticationData == null) { + return null; + } + final String origin = authenticationData.getOrigin(); UaaUser userFromRequest = getUser(request, authenticationData); if (userFromRequest == null) { From 77c04618ad866796b2a74d5d91a9c12bb6e06492 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:58:31 +0200 Subject: [PATCH 17/24] Read origin from authentication data in ExternalLoginAuthenticationManager#populateAuthenticationAttributes --- .../manager/ExternalLoginAuthenticationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 5e227f1c4c3..062a78bb898 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -162,7 +162,7 @@ protected void populateAuthenticationAttributes(UaaAuthentication authentication // persist the user attributes and external groups in the user info table if configured in the IdP if ((hasUserAttributes(authentication) || hasExternalGroups(authentication)) && getProviderProvisioning() != null) { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(authenticationData.getOrigin(), IdentityZoneHolder.get().getId()); if (provider.getConfig() != null && provider.getConfig().isStoreCustomAttributes()) { logger.debug("Storing custom attributes for user_id:{}", authentication.getPrincipal().getId()); UserInfo userInfo = new UserInfo() From cf99e28974d1a74127e9995278977c5af2629761 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 19:58:57 +0200 Subject: [PATCH 18/24] Read origin from authentication data in ExternalLoginAuthenticationManager#getUser --- .../ExternalLoginAuthenticationManager.java | 4 ++-- .../LdapLoginAuthenticationManagerTests.java | 12 +++++++----- .../ExternalOAuthAuthenticationManagerIT.java | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 062a78bb898..1f0b92e4ebc 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -228,7 +228,7 @@ protected UaaUser getUser(Authentication request, EAD authDetails) { } if (UaaStringUtils.isEmpty(email)) { - email = generateEmailIfNullOrEmpty(name, getOrigin()); + email = generateEmailIfNullOrEmpty(name, authDetails.getOrigin()); } String givenName = null; @@ -251,7 +251,7 @@ protected UaaUser getUser(Authentication request, EAD authDetails) { .withFamilyName(familyName) .withCreated(new Date()) .withModified(new Date()) - .withOrigin(getOrigin()) + .withOrigin(authDetails.getOrigin()) .withExternalId(externalId) .withZoneId(IdentityZoneHolder.get().getId()) .withPhoneNumber(phoneNumber); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java index 7acc1c7a426..8cf69a9ef9a 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManagerTests.java @@ -139,7 +139,8 @@ void setUp() { @Test void getUserWithExtendedLdapInfo() { - UaaUser user = am.getUser(auth, null); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); + UaaUser user = am.getUser(auth, authenticationData); assertThat(user.getExternalId()).isEqualTo(DN); assertThat(user.getEmail()).isEqualTo(LDAP_EMAIL); assertThat(user.getOrigin()).isEqualTo(origin); @@ -151,7 +152,8 @@ void getUserWithNonLdapInfo() { UserDetails mockNonLdapUserDetails = mockNonLdapUserDetails(); when(mockNonLdapUserDetails.getUsername()).thenReturn(TEST_EMAIL); when(auth.getPrincipal()).thenReturn(mockNonLdapUserDetails); - UaaUser user = am.getUser(auth, null); + final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); + UaaUser user = am.getUser(auth, authenticationData); assertThat(user.getExternalId()).isEqualTo(TEST_EMAIL); assertThat(user.getEmail()).isEqualTo(TEST_EMAIL); assertThat(user.getOrigin()).isEqualTo(origin); @@ -161,7 +163,7 @@ void getUserWithNonLdapInfo() { void userAuthenticated() { UaaUser user = getUaaUser(); final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); - UaaUser userFromRequest = am.getUser(auth, null); + UaaUser userFromRequest = am.getUser(auth, authenticationData); definition.setAutoAddGroups(true); UaaUser result = am.userAuthenticated(auth, user, userFromRequest, authenticationData); assertThat(result).isSameAs(dbUser); @@ -186,7 +188,7 @@ void update_existingUser_if_attributes_different() { UaaUser user = getUaaUser(); final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); - UaaUser userFromRequest = am.getUser(auth, null); + UaaUser userFromRequest = am.getUser(auth, authenticationData); am.userAuthenticated(auth, userFromRequest, user, authenticationData); ArgumentCaptor captor = ArgumentCaptor.forClass(ExternalGroupAuthorizationEvent.class); verify(publisher, times(1)).publishEvent(captor.capture()); @@ -203,7 +205,7 @@ void dontUpdate_existingUser_if_attributes_same() { when(auth.getPrincipal()).thenReturn(authDetails); final ExternalAuthenticationDetails authenticationData = ExternalAuthenticationDetails.builder().origin(origin).build(); - UaaUser userFromRequest = am.getUser(auth, null); + UaaUser userFromRequest = am.getUser(auth, authenticationData); am.userAuthenticated(auth, userFromRequest, user, authenticationData); ArgumentCaptor captor = ArgumentCaptor.forClass(ExternalGroupAuthorizationEvent.class); verify(publisher, times(1)).publishEvent(captor.capture()); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java index 199f8132924..6e3a78308be 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java @@ -32,6 +32,7 @@ import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning; import org.cloudfoundry.identity.uaa.provider.OIDCIdentityProviderDefinition; import org.cloudfoundry.identity.uaa.provider.RawExternalOAuthIdentityProviderDefinition; +import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthAuthenticationManager.AuthenticationData; import org.cloudfoundry.identity.uaa.scim.ScimGroupExternalMember; import org.cloudfoundry.identity.uaa.scim.ScimGroupExternalMembershipManager; import org.cloudfoundry.identity.uaa.user.InMemoryUaaUserDatabase; @@ -446,7 +447,7 @@ void when_exchanging_an_id_token_retrieved_from_the_internal_uaa_idp_for_an_acce xCodeToken.setIdToken(idToken); xCodeToken.setOrigin(null); - ExternalOAuthAuthenticationManager.AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager + AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager .getExternalAuthenticationDetails(xCodeToken); assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); @@ -491,7 +492,7 @@ void when_exchanging_an_id_token_retrieved_by_uaa_via_an_oidc_idp_for_an_access_ xCodeToken.setIdToken(idToken); xCodeToken.setOrigin(null); - ExternalOAuthAuthenticationManager.AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager + AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager .getExternalAuthenticationDetails(xCodeToken); assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); @@ -516,7 +517,7 @@ void when_exchanging_an_id_token_retrieved_by_uaa_via_an_registered_oidc_idp_for xCodeToken.setIdToken(idToken); xCodeToken.setOrigin(null); - ExternalOAuthAuthenticationManager.AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager + AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager .getExternalAuthenticationDetails(xCodeToken); assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); @@ -539,7 +540,7 @@ void when_exchanging_an_id_token_retrieved_by_an_external_oidc_idp_for_an_access xCodeToken.setIdToken(idToken); xCodeToken.setOrigin(null); - ExternalOAuthAuthenticationManager.AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager + AuthenticationData externalAuthenticationDetails = externalOAuthAuthenticationManager .getExternalAuthenticationDetails(xCodeToken); assertThat(username).isEqualTo(externalAuthenticationDetails.getUsername()); @@ -1019,12 +1020,14 @@ void getUserWithNullEmail() { @Test void getUserSetsTheRightOrigin() { - externalOAuthAuthenticationManager.getUser(xCodeToken, externalOAuthAuthenticationManager.getExternalAuthenticationDetails(xCodeToken)); - assertThat(externalOAuthAuthenticationManager.getOrigin()).isEqualTo(ORIGIN); + AuthenticationData authenticationData = externalOAuthAuthenticationManager.getExternalAuthenticationDetails(xCodeToken); + externalOAuthAuthenticationManager.getUser(xCodeToken, authenticationData); + assertThat(authenticationData.getOrigin()).isEqualTo(ORIGIN); ExternalOAuthCodeToken otherToken = new ExternalOAuthCodeToken(CODE, "other_origin", "http://localhost/callback/the_origin"); - externalOAuthAuthenticationManager.getUser(otherToken, externalOAuthAuthenticationManager.getExternalAuthenticationDetails(otherToken)); - assertThat(externalOAuthAuthenticationManager.getOrigin()).isEqualTo("other_origin"); + AuthenticationData authenticationDataOtherToken = externalOAuthAuthenticationManager.getExternalAuthenticationDetails(otherToken); + externalOAuthAuthenticationManager.getUser(otherToken, authenticationDataOtherToken); + assertThat(authenticationDataOtherToken.getOrigin()).isEqualTo("other_origin"); } @Test From 0c915a87429ebeb3a8fdcffdddd3177b3f90e568 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:02:22 +0200 Subject: [PATCH 19/24] Read origin from authentication data in LdapLoginAuthenticationManager#getUserAttributes --- .../manager/LdapLoginAuthenticationManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 88c6e56c986..1be7d2eb7b3 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -77,9 +77,9 @@ protected void populateAuthenticationAttributes(UaaAuthentication authentication @Override protected MultiValueMap getUserAttributes(UserDetails request, ExternalAuthenticationDetails authenticationData) { MultiValueMap result = super.getUserAttributes(request, authenticationData); - logger.debug("Mapping custom attributes for origin:{} and zone:{}", getOrigin(), IdentityZoneHolder.get().getId()); + logger.debug("Mapping custom attributes for origin:{} and zone:{}", authenticationData.getOrigin(), IdentityZoneHolder.get().getId()); if (getProviderProvisioning() != null) { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(authenticationData.getOrigin(), IdentityZoneHolder.get().getId()); if (request instanceof ExtendedLdapUserDetails ldapDetails) { LdapIdentityProviderDefinition ldapIdentityProviderDefinition = ObjectUtils.castInstance(provider.getConfig(), LdapIdentityProviderDefinition.class); Map providerMappings = ldapIdentityProviderDefinition.getAttributeMappings(); @@ -95,7 +95,7 @@ protected MultiValueMap getUserAttributes(UserDetails request, E } } } else { - logger.debug("Did not find custom attribute configuration for origin:{} and zone:{}", getOrigin(), IdentityZoneHolder.get().getId()); + logger.debug("Did not find custom attribute configuration for origin:{} and zone:{}", authenticationData.getOrigin(), IdentityZoneHolder.get().getId()); } return result; } From 23283ebdfc74f5d0cf7647355b701f7999a28cba Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:02:41 +0200 Subject: [PATCH 20/24] Read origin from authentication data in LdapLoginAuthenticationManager#getExternalUserAuthorities --- .../authentication/manager/LdapLoginAuthenticationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 1be7d2eb7b3..b29b31d01a8 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -104,7 +104,7 @@ protected MultiValueMap getUserAttributes(UserDetails request, E protected List getExternalUserAuthorities(UserDetails request, ExternalAuthenticationDetails authenticationData) { List result = new LinkedList<>(); if (getProviderProvisioning() != null) { - IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId()); + IdentityProvider provider = getProviderProvisioning().retrieveByOrigin(authenticationData.getOrigin(), IdentityZoneHolder.get().getId()); LdapIdentityProviderDefinition ldapIdentityProviderDefinition = ObjectUtils.castInstance(provider.getConfig(), LdapIdentityProviderDefinition.class); List externalWhiteList = ldapIdentityProviderDefinition.getExternalGroupsWhitelist(); result = new ArrayList<>(retainAllMatches(getAuthoritiesAsNames(request.getAuthorities()), externalWhiteList)); From 06ecfa17208722813c73b24465006f7b272166a4 Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:02:59 +0200 Subject: [PATCH 21/24] Read origin from authentication data in LdapLoginAuthenticationManager#userAuthenticated --- .../authentication/manager/LdapLoginAuthenticationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index b29b31d01a8..24b9399a57b 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -142,7 +142,7 @@ protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequ userModified = true; } } - ExternalGroupAuthorizationEvent event = new ExternalGroupAuthorizationEvent(userFromDb, userModified, request.getAuthorities(), isAutoAddAuthorities(getOrigin())); + ExternalGroupAuthorizationEvent event = new ExternalGroupAuthorizationEvent(userFromDb, userModified, request.getAuthorities(), isAutoAddAuthorities(authenticationData.getOrigin())); publish(event); return getUserDatabase().retrieveUserById(userFromDb.getId()); } From b37e8134a4b4498e371808ea3baa40a11d57de7a Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:09:56 +0200 Subject: [PATCH 22/24] Remove setting thread local in ExternalOAuthAuthenticationManager#getExternalAuthenticationDetails --- .../oauth/ExternalOAuthAuthenticationManager.java | 2 +- .../ExternalLoginAuthenticationManagerTest.java | 2 +- .../ExternalOAuthAuthenticationManagerIT.java | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index 4a6a4791b82..ebe7e13d6dc 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -267,7 +267,7 @@ protected AuthenticationData getExternalAuthenticationDetails(final Authenticati } final String origin = codeToken.getOrigin(); - setOrigin(origin); + if (provider == null) { try { provider = getProviderProvisioning().retrieveByOrigin(origin, identityZoneManager.getCurrentIdentityZoneId()); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 2773473accf..419616f58df 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -586,7 +586,7 @@ void authenticateUserExists() { @Test void authenticateUserDoesNotExists() { - String origin = "external"; + origin = "external"; manager.setOrigin(origin); when(uaaUserDatabase.retrieveUserByName(eq(userName), eq(origin))) diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java index 6e3a78308be..85d97e2b730 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java @@ -1020,10 +1020,24 @@ void getUserWithNullEmail() { @Test void getUserSetsTheRightOrigin() { + final IdentityProvider> idp = MultitenancyFixture.identityProvider("the_origin", "uaa"); + idp.setConfig(config); + when(provisioning.retrieveByOrigin(eq(ORIGIN), anyString())).thenReturn(idp); + + final IdentityProvider> otherIdp = MultitenancyFixture.identityProvider("other_origin", "uaa"); + otherIdp.setConfig(config); + when(provisioning.retrieveByOrigin(eq("other_origin"), anyString())).thenReturn(otherIdp); + + mockToken(); AuthenticationData authenticationData = externalOAuthAuthenticationManager.getExternalAuthenticationDetails(xCodeToken); + assertThat(authenticationData).isNotNull(); externalOAuthAuthenticationManager.getUser(xCodeToken, authenticationData); assertThat(authenticationData.getOrigin()).isEqualTo(ORIGIN); + mockUaaServer.verify(); + mockUaaServer.reset(); + + mockToken(); ExternalOAuthCodeToken otherToken = new ExternalOAuthCodeToken(CODE, "other_origin", "http://localhost/callback/the_origin"); AuthenticationData authenticationDataOtherToken = externalOAuthAuthenticationManager.getExternalAuthenticationDetails(otherToken); externalOAuthAuthenticationManager.getUser(otherToken, authenticationDataOtherToken); From 4ec390ed680034aa4ac407abe3f30bf8db0a306b Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:13:43 +0200 Subject: [PATCH 23/24] Remove thread local from ExternalOAuthAuthenticationManager --- .../ExternalOAuthAuthenticationManager.java | 24 ------- .../ExternalOAuthAuthenticationManagerIT.java | 63 ------------------- 2 files changed, 87 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java index ebe7e13d6dc..7ec3ba692b2 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManager.java @@ -148,9 +148,6 @@ public class ExternalOAuthAuthenticationManager extends ExternalLoginAuthenticat private final KeyInfoService keyInfoService; private final IdentityZoneManager identityZoneManager; - //origin is per thread during execution - private final ThreadLocal origin = ThreadLocal.withInitial(() -> "unknown"); - public ExternalOAuthAuthenticationManager( IdentityProviderProvisioning providerProvisioning, IdentityZoneManager identityZoneManager, @@ -169,27 +166,6 @@ public ExternalOAuthAuthenticationManager( this.oidcMetadataFetcher = oidcMetadataFetcher; } - @Override - public String getOrigin() { - //origin is per thread during execution - return origin.get(); - } - - @Override - public void setOrigin(String origin) { - this.origin.set(origin); - } - - @Override - public Authentication authenticate(final Authentication request) throws AuthenticationException { - try { - return super.authenticate(request); - } finally { - // clear ThreadLocal holding the origin key - origin.remove(); - } - } - /** * Resolve the IdP trust for the received ID token: *
    diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java index 85d97e2b730..824f933b85a 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/oauth/ExternalOAuthAuthenticationManagerIT.java @@ -88,7 +88,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.CountDownLatch; import java.util.stream.Stream; import static java.util.Collections.emptyList; @@ -314,68 +313,6 @@ void verify_hmac_256_signature() throws Exception { assertThat(new String(Base64.encodeBase64URLSafe(hmacData))).isEqualTo(externalOAuthAuthenticationManager.hmacSignAndEncode(data, key)); } - @Test - void authManager_origin_is_thread_safe() throws Exception { - CountDownLatch countDownLatchA = new CountDownLatch(1); - CountDownLatch countDownLatchB = new CountDownLatch(1); - - final String[] thread1Origin = new String[1]; - final String[] thread2Origin = new String[1]; - Thread thread1 = new Thread() { - @Override - public void run() { - externalOAuthAuthenticationManager.setOrigin("a"); - resumeThread2(); - pauseThread1(); - thread1Origin[0] = externalOAuthAuthenticationManager.getOrigin(); - } - - private void resumeThread2() { - countDownLatchB.countDown(); - } - - private void pauseThread1() { - try { - countDownLatchA.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }; - - Thread thread2 = new Thread() { - @Override - public void run() { - pauseThread2(); - externalOAuthAuthenticationManager.setOrigin("b"); - resumeThread1(); - - thread2Origin[0] = externalOAuthAuthenticationManager.getOrigin(); - } - - private void resumeThread1() { - countDownLatchA.countDown(); - } - - private void pauseThread2() { - try { - countDownLatchB.await(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }; - - thread2.start(); - thread1.start(); - - thread1.join(); - thread2.join(); - - assertThat(thread1Origin[0]).isEqualTo("a"); - assertThat(thread2Origin[0]).isEqualTo("b"); - } - @Test void when_a_null_id_token_is_provided_resolveOriginProvider_should_throw_a_jwt_validation_exception() { assertThatThrownBy(() -> externalOAuthAuthenticationManager.resolveOriginProvider(null)) From 908306a9ac0cb28c8a2397da191ad6eebd8bda8e Mon Sep 17 00:00:00 2001 From: Adrian Hoelzl Date: Wed, 1 Oct 2025 20:16:48 +0200 Subject: [PATCH 24/24] Remove getter and setter for origin property in ExternalLoginAuthenticationManager --- .../ExternalLoginAuthenticationManager.java | 4 ---- .../LdapLoginAuthenticationManager.java | 17 +++++--------- ...xternalLoginAuthenticationManagerTest.java | 22 +------------------ 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java index 1f0b92e4ebc..6def53fc23e 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManager.java @@ -89,10 +89,6 @@ public final void setApplicationEventPublisher(@NonNull ApplicationEventPublishe this.eventPublisher = eventPublisher; } - public abstract String getOrigin(); - - public abstract void setOrigin(String origin); - @Override public Authentication authenticate(Authentication request) throws AuthenticationException { if (logger.isDebugEnabled()) { diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java index 24b9399a57b..c485f418504 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/LdapLoginAuthenticationManager.java @@ -15,6 +15,7 @@ package org.cloudfoundry.identity.uaa.authentication.manager; +import com.google.common.annotations.VisibleForTesting; import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; import org.cloudfoundry.identity.uaa.authentication.manager.ExternalLoginAuthenticationManager.ExternalAuthenticationDetails; import org.cloudfoundry.identity.uaa.constants.OriginKeys; @@ -57,17 +58,6 @@ public LdapLoginAuthenticationManager(final @Qualifier("identityProviderProvisio super(providerProvisioning); } - @Override - public String getOrigin() { - return origin; - } - - @Override - public void setOrigin(String origin) { - // only used in LdapLoginAuthenticationManagerTests - this.origin = origin; - } - @Override protected void populateAuthenticationAttributes(UaaAuthentication authentication, Authentication request, ExternalAuthenticationDetails authenticationData) { super.populateAuthenticationAttributes(authentication, request, authenticationData); @@ -172,6 +162,11 @@ protected boolean isAddNewShadowUser(final String origin) { return result; } + @VisibleForTesting + public void setOrigin(final String origin) { + this.origin = origin; + } + @Override protected ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { return ExternalAuthenticationDetails.builder().origin(origin).build(); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java index 419616f58df..8d758848790 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/ExternalLoginAuthenticationManagerTest.java @@ -62,7 +62,7 @@ class ExternalLoginAuthenticationManagerTest { private UaaUserDatabase uaaUserDatabase; private Authentication inputAuth; private ExternalLoginAuthenticationManager manager; - private final String origin = "test"; + private String origin = "test"; private UserDetails userDetails; private final String userName = "testUserName"; private final String password = ""; @@ -105,18 +105,6 @@ private void mockUaaWithUser() { when(inputAuth.getPrincipal()).thenReturn(userDetails); manager = new ExternalLoginAuthenticationManager<>(null) { - private String origin = "unknown"; - - @Override - public String getOrigin() { - return origin; - } - - @Override - public void setOrigin(String origin) { - this.origin = origin; - } - @Override protected ExternalAuthenticationDetails getExternalAuthenticationDetails(Authentication authentication) throws AuthenticationException { return ExternalAuthenticationDetails.builder().origin(origin).build(); @@ -153,7 +141,6 @@ private UaaUser addUserToDb(String userName, String userId, String origin, Strin } private void setupManager() { - manager.setOrigin(origin); String beanName = "ExternalLoginAuthenticationManagerTestBean"; manager.setBeanName(beanName); manager.setApplicationEventPublisher(applicationEventPublisher); @@ -354,7 +341,6 @@ void authenticateLdapUserDetailsPrincipal() { manager = new LdapLoginAuthenticationManager(null); setupManager(); manager.setProviderProvisioning(null); - manager.setOrigin(origin); when(user.getOrigin()).thenReturn(origin); when(uaaUserDatabase.retrieveUserByName(eq(userName), eq(origin))).thenReturn(user); when(inputAuth.getPrincipal()).thenReturn(ldapUserDetails); @@ -383,7 +369,6 @@ protected boolean isAddNewShadowUser(final String origin) { }; setupManager(); - manager.setOrigin(origin); when(uaaUserDatabase.retrieveUserByName(eq(userName), eq(origin))).thenReturn(null); when(inputAuth.getPrincipal()).thenReturn(ldapUserDetails); @@ -415,7 +400,6 @@ void authenticateCreateUserWithLdapUserDetailsPrincipal() { manager = new LdapLoginAuthenticationManager(null); setupManager(); manager.setProviderProvisioning(null); - manager.setOrigin(origin); when(user.getEmail()).thenReturn(email); when(user.getOrigin()).thenReturn(origin); when(user.getExternalId()).thenReturn(dn); @@ -446,7 +430,6 @@ void authenticateCreateUserWithUserDetailsPrincipal() { manager = new LdapLoginAuthenticationManager(null); setupManager(); - manager.setOrigin(origin); manager.setProviderProvisioning(null); when(user.getOrigin()).thenReturn(origin); @@ -496,7 +479,6 @@ void authenticateInvitedUserWithoutAcceptance() { manager = new LdapLoginAuthenticationManager(null); setupManager(); manager.setProviderProvisioning(null); - manager.setOrigin(origin); when(uaaUserDatabase.retrieveUserByName(eq(username), eq(origin))) .thenThrow(new UsernameNotFoundException("")); @@ -520,7 +502,6 @@ void authenticateInvitedUserWithoutAcceptance() { void populateAttributesStoresCustomAttributesAndRoles() { manager = new LdapLoginAuthenticationManager(null); setupManager(); - manager.setOrigin(origin); IdentityProvider provider = mock(IdentityProvider.class); ExternalIdentityProviderDefinition providerDefinition = new ExternalIdentityProviderDefinition(); when(provider.getConfig()).thenReturn(providerDefinition); @@ -587,7 +568,6 @@ void authenticateUserExists() { @Test void authenticateUserDoesNotExists() { origin = "external"; - manager.setOrigin(origin); when(uaaUserDatabase.retrieveUserByName(eq(userName), eq(origin))) .thenReturn(null)