Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
edd3796
Add field for origin to LdapLoginAuthenticationManager
adrianhoelzl-sap Oct 1, 2025
e682f63
Add 'origin' parameter to ExternalLoginAuthenticationManager#generate…
adrianhoelzl-sap Oct 1, 2025
623e04d
Add 'origin' parameter to ExternalLoginAuthenticationManager#isAddNew…
adrianhoelzl-sap Oct 1, 2025
fee358d
Rename type parameter of ExternalLoginAuthenticationManager
adrianhoelzl-sap Oct 1, 2025
6fc3f4c
Extract variable for origin in ExternalLoginAuthenticationManager#aut…
adrianhoelzl-sap Oct 1, 2025
995682a
Add 'origin' parameter to LdapLoginAuthenticationManager#isAutoAddAut…
adrianhoelzl-sap Oct 1, 2025
b97e851
Add base class for ExternalAuthenticationDetails
adrianhoelzl-sap Oct 1, 2025
115585b
Add super class constraint to type parameter of ExternalLoginAuthenti…
adrianhoelzl-sap Oct 1, 2025
3f4e371
Introduce variable for origin in ExternalOAuthAuthenticationManager#g…
adrianhoelzl-sap Oct 1, 2025
e75b552
Add parameter for authentication data to ExternalLoginAuthenticationM…
adrianhoelzl-sap Oct 1, 2025
1f1359c
Add parameter for authentication data to ExternalLoginAuthenticationM…
adrianhoelzl-sap Oct 1, 2025
d2a7e21
Add parameter for authentication data to ExternalLoginAuthenticationM…
adrianhoelzl-sap Oct 1, 2025
f0220af
Set origin in authentication data in ExternalOAuthAuthenticationManag…
adrianhoelzl-sap Oct 1, 2025
be4075a
Use authentication data object instead of null in ExternalLoginAuthen…
adrianhoelzl-sap Oct 1, 2025
d2c0421
Read origin from authentication data in ExternalOAuthAuthenticationMa…
adrianhoelzl-sap Oct 1, 2025
b6892ef
Read origin from authentication data in ExternalLoginAuthenticationMa…
adrianhoelzl-sap Oct 1, 2025
77c0461
Read origin from authentication data in ExternalLoginAuthenticationMa…
adrianhoelzl-sap Oct 1, 2025
cf99e28
Read origin from authentication data in ExternalLoginAuthenticationMa…
adrianhoelzl-sap Oct 1, 2025
0c915a8
Read origin from authentication data in LdapLoginAuthenticationManage…
adrianhoelzl-sap Oct 1, 2025
23283eb
Read origin from authentication data in LdapLoginAuthenticationManage…
adrianhoelzl-sap Oct 1, 2025
06ecfa1
Read origin from authentication data in LdapLoginAuthenticationManage…
adrianhoelzl-sap Oct 1, 2025
b37e813
Remove setting thread local in ExternalOAuthAuthenticationManager#get…
adrianhoelzl-sap Oct 1, 2025
4ec390e
Remove thread local from ExternalOAuthAuthenticationManager
adrianhoelzl-sap Oct 1, 2025
908306a
Remove getter and setter for origin property in ExternalLoginAuthenti…
adrianhoelzl-sap Oct 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -54,7 +57,7 @@

import static java.util.Collections.emptySet;

public abstract class ExternalLoginAuthenticationManager<ExternalAuthenticationDetails> implements AuthenticationManager, ApplicationEventPublisherAware, BeanNameAware {
public abstract class ExternalLoginAuthenticationManager<EAD extends ExternalLoginAuthenticationManager.ExternalAuthenticationDetails> 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";
Expand Down Expand Up @@ -86,16 +89,18 @@ 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()) {
logger.debug("Starting external authentication for:{}", UaaStringUtils.getCleanedUserControlString(request.toString()));
}
ExternalAuthenticationDetails authenticationData = getExternalAuthenticationDetails(request);

EAD authenticationData = getExternalAuthenticationDetails(request);
if (authenticationData == null) {
return null;
}
final String origin = authenticationData.getOrigin();

UaaUser userFromRequest = getUser(request, authenticationData);
if (userFromRequest == null) {
return null;
Expand All @@ -104,28 +109,28 @@ 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()) {
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.");
}
}

//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) {
Expand All @@ -139,10 +144,10 @@ 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)));
authentication.setUserAttributes(getUserAttributes(userDetails, authenticationData));
authentication.setExternalGroups(new HashSet<>(getExternalUserAuthorities(userDetails, authenticationData)));
}

if (authentication.getAuthenticationMethods() == null) {
Expand All @@ -153,7 +158,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<ExternalIdentityProviderDefinition> provider = getProviderProvisioning().retrieveByOrigin(getOrigin(), IdentityZoneHolder.get().getId());
IdentityProvider<ExternalIdentityProviderDefinition> 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()
Expand All @@ -172,25 +177,25 @@ 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();
protected abstract boolean isAddNewShadowUser(final String origin);

protected MultiValueMap<String, String> getUserAttributes(UserDetails request) {
protected MultiValueMap<String, String> getUserAttributes(UserDetails request, EAD authenticationData) {
return new LinkedMultiValueMap<>();
}

protected abstract List<String> getExternalUserAuthorities(UserDetails request);
protected abstract List<String> getExternalUserAuthorities(UserDetails request, EAD authenticationData);

protected final void publish(ApplicationEvent event) {
if (eventPublisher != null) {
eventPublisher.publishEvent(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, ExternalAuthenticationDetails authDetails) {
protected UaaUser getUser(Authentication request, EAD authDetails) {
UserDetails userDetails;
if (request.getPrincipal() instanceof UserDetails) {
userDetails = (UserDetails) request.getPrincipal();
Expand Down Expand Up @@ -219,7 +224,7 @@ protected UaaUser getUser(Authentication request, ExternalAuthenticationDetails
}

if (UaaStringUtils.isEmpty(email)) {
email = generateEmailIfNullOrEmpty(name);
email = generateEmailIfNullOrEmpty(name, authDetails.getOrigin());
}

String givenName = null;
Expand All @@ -242,20 +247,20 @@ protected UaaUser getUser(Authentication request, ExternalAuthenticationDetails
.withFamilyName(familyName)
.withCreated(new Date())
.withModified(new Date())
.withOrigin(getOrigin())
.withOrigin(authDetails.getOrigin())
.withExternalId(externalId)
.withZoneId(IdentityZoneHolder.get().getId())
.withPhoneNumber(phoneNumber);

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("@")) {
Expand Down Expand Up @@ -310,4 +315,23 @@ protected final List<SimpleGrantedAuthority> 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@

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;
import org.cloudfoundry.identity.uaa.provider.IdentityProvider;
import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning;
Expand Down Expand Up @@ -46,44 +48,28 @@
import static java.util.Collections.emptyList;
import static org.cloudfoundry.identity.uaa.util.UaaStringUtils.retainAllMatches;

public class LdapLoginAuthenticationManager extends ExternalLoginAuthenticationManager<Object> {
public class LdapLoginAuthenticationManager extends ExternalLoginAuthenticationManager<ExternalAuthenticationDetails> {

protected static Logger logger = LoggerFactory.getLogger(LdapLoginAuthenticationManager.class);

public LdapLoginAuthenticationManager(final @Qualifier("identityProviderProvisioning") IdentityProviderProvisioning providerProvisioning) {
super(providerProvisioning);
}

private String origin = OriginKeys.LDAP;

@Override
public String getOrigin() {
return origin;
}

@Override
public void setOrigin(String origin) {
// only used in LdapLoginAuthenticationManagerTests
this.origin = origin;
public LdapLoginAuthenticationManager(final @Qualifier("identityProviderProvisioning") IdentityProviderProvisioning providerProvisioning) {
super(providerProvisioning);
}

@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<String, String> getUserAttributes(UserDetails request) {
MultiValueMap<String, String> result = super.getUserAttributes(request);
logger.debug("Mapping custom attributes for origin:{} and zone:{}", getOrigin(), IdentityZoneHolder.get().getId());
protected MultiValueMap<String, String> getUserAttributes(UserDetails request, ExternalAuthenticationDetails authenticationData) {
MultiValueMap<String, String> result = super.getUserAttributes(request, authenticationData);
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<String, Object> providerMappings = ldapIdentityProviderDefinition.getAttributeMappings();
Expand All @@ -99,16 +85,16 @@ protected MultiValueMap<String, String> getUserAttributes(UserDetails request) {
}
}
} 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;
}

@Override
protected List<String> getExternalUserAuthorities(UserDetails request) {
protected List<String> getExternalUserAuthorities(UserDetails request, ExternalAuthenticationDetails authenticationData) {
List<String> 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<String> externalWhiteList = ldapIdentityProviderDefinition.getExternalGroupsWhitelist();
result = new ArrayList<>(retainAllMatches(getAuthoritiesAsNames(request.getAuthorities()), externalWhiteList));
Expand All @@ -131,7 +117,7 @@ protected Set<String> getAuthoritiesAsNames(Collection<? extends GrantedAuthorit
}

@Override
protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb) {
protected UaaUser userAuthenticated(Authentication request, UaaUser userFromRequest, UaaUser userFromDb, ExternalAuthenticationDetails authenticationData) {
boolean userModified = false;
//we must check and see if the email address has changed between authentications
if (request.getPrincipal() != null && request.getPrincipal() instanceof ExtendedLdapUserDetails) {
Expand All @@ -146,15 +132,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(authenticationData.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();
Expand All @@ -164,15 +150,25 @@ 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();
}
}
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();
}
}
Loading
Loading