From 48f18bcca8f7b50c829335a3e5bfd8854df47a96 Mon Sep 17 00:00:00 2001 From: Markus Strehle <11627201+strehle@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:55:26 +0200 Subject: [PATCH] fix: reduce DB calls in password grant flow (#3017) * fix: reduce DB calls in password grant flow 1. do not retrieve always all IdPs, but check if origin call is possible 2. do not retrieve client again (check in client authentication already) * sonar refactorings * Test error fix --- .../PasswordGrantAuthenticationManager.java | 51 ++++++++---- .../identity/uaa/client/UaaClient.java | 2 +- ...asswordGrantAuthenticationManagerTest.java | 79 ++++++++++++++----- .../webapp/WEB-INF/spring/oauth-endpoints.xml | 1 - 4 files changed, 95 insertions(+), 38 deletions(-) diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManager.java b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManager.java index c4733bf5adb..73b6f6ac437 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManager.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManager.java @@ -6,6 +6,7 @@ import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.authentication.UaaLoginHint; import org.cloudfoundry.identity.uaa.authentication.event.IdentityProviderAuthenticationFailureEvent; +import org.cloudfoundry.identity.uaa.client.UaaClient; import org.cloudfoundry.identity.uaa.constants.ClientAuthentication; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.impl.config.RestTemplateConfig; @@ -18,13 +19,13 @@ import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthAuthenticationManager; import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthCodeToken; import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthProviderConfigurator; -import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -35,7 +36,6 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; -import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails; import org.springframework.util.Base64Utils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -46,7 +46,6 @@ import java.net.URL; import java.util.*; import java.util.function.Supplier; -import java.util.stream.Collectors; import static org.cloudfoundry.identity.uaa.oauth.token.TokenConstants.GRANT_TYPE_PASSWORD; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -57,16 +56,14 @@ public class PasswordGrantAuthenticationManager implements AuthenticationManager private IdentityProviderProvisioning identityProviderProvisioning; private RestTemplateConfig restTemplateConfig; private ExternalOAuthAuthenticationManager externalOAuthAuthenticationManager; - private MultitenantClientServices clientDetailsService; private ExternalOAuthProviderConfigurator externalOAuthProviderProvisioning; private ApplicationEventPublisher eventPublisher; - public PasswordGrantAuthenticationManager(DynamicZoneAwareAuthenticationManager zoneAwareAuthzAuthenticationManager, final @Qualifier("identityProviderProvisioning") IdentityProviderProvisioning identityProviderProvisioning, RestTemplateConfig restTemplateConfig, ExternalOAuthAuthenticationManager externalOAuthAuthenticationManager, MultitenantClientServices clientDetailsService, ExternalOAuthProviderConfigurator externalOAuthProviderProvisioning) { + public PasswordGrantAuthenticationManager(DynamicZoneAwareAuthenticationManager zoneAwareAuthzAuthenticationManager, final @Qualifier("identityProviderProvisioning") IdentityProviderProvisioning identityProviderProvisioning, RestTemplateConfig restTemplateConfig, ExternalOAuthAuthenticationManager externalOAuthAuthenticationManager, ExternalOAuthProviderConfigurator externalOAuthProviderProvisioning) { this.zoneAwareAuthzAuthenticationManager = zoneAwareAuthzAuthenticationManager; this.identityProviderProvisioning = identityProviderProvisioning; this.restTemplateConfig = restTemplateConfig; this.externalOAuthAuthenticationManager = externalOAuthAuthenticationManager; - this.clientDetailsService = clientDetailsService; this.externalOAuthProviderProvisioning = externalOAuthProviderProvisioning; } @@ -76,18 +73,22 @@ public Authentication authenticate(Authentication authentication) throws Authent List allowedProviders = getAllowedProviders(); String defaultProvider = IdentityZoneHolder.get().getConfig().getDefaultIdentityProvider(); UaaLoginHint loginHintToUse; - List identityProviders = identityProviderProvisioning.retrieveActive(IdentityZoneHolder.get().getId()).stream().filter(this::providerSupportsPasswordGrant).map(IdentityProvider::getOriginKey).collect(Collectors.toList()); + IdentityProvider identityProvider = retrieveOidcPasswordIdp(uaaLoginHint, defaultProvider, allowedProviders); List possibleProviders; - if (allowedProviders == null) { - possibleProviders = identityProviders; + if (identityProvider != null) { + possibleProviders = List.of(identityProvider.getOriginKey()); } else { - possibleProviders = allowedProviders.stream().filter(identityProviders::contains).collect(Collectors.toList()); + List identityProviders = identityProviderProvisioning.retrieveActive(IdentityZoneHolder.get().getId()).stream().filter(this::providerSupportsPasswordGrant).map(IdentityProvider::getOriginKey).toList(); + possibleProviders = Optional.ofNullable(allowedProviders).orElse(identityProviders).stream().filter(identityProviders::contains).toList(); } if (uaaLoginHint == null) { if (defaultProvider != null && possibleProviders.contains(defaultProvider)) { loginHintToUse = new UaaLoginHint(defaultProvider); } else { loginHintToUse = getUaaLoginHintForChainedAuth(possibleProviders); + if (identityProvider == null) { + identityProvider = retrieveOidcPasswordIdp(loginHintToUse, null, null); + } } } else { if (possibleProviders.contains(uaaLoginHint.getOrigin())) { @@ -101,13 +102,31 @@ public Authentication authenticate(Authentication authentication) throws Authent if (loginHintToUse != null) { zoneAwareAuthzAuthenticationManager.setLoginHint(authentication, loginHintToUse); } - if (loginHintToUse == null || loginHintToUse.getOrigin() == null || loginHintToUse.getOrigin().equals(OriginKeys.UAA) || loginHintToUse.getOrigin().equals(OriginKeys.LDAP)) { + if (identityProvider == null || loginHintToUse == null || loginHintToUse.getOrigin() == null || loginHintToUse.getOrigin().equals(OriginKeys.UAA) || loginHintToUse.getOrigin().equals(OriginKeys.LDAP)) { return zoneAwareAuthzAuthenticationManager.authenticate(authentication); } else { - return oidcPasswordGrant(authentication, (OIDCIdentityProviderDefinition)externalOAuthProviderProvisioning.retrieveByOrigin(loginHintToUse.getOrigin(), IdentityZoneHolder.get().getId()).getConfig()); + return oidcPasswordGrant(authentication, identityProvider.getConfig()); } } + private IdentityProvider retrieveOidcPasswordIdp(UaaLoginHint loginHint, String defaultOrigin, List allowedProviders) { + IdentityProvider idp = null; + String useOrigin = loginHint != null && loginHint.getOrigin() != null ? loginHint.getOrigin() : defaultOrigin; + if (useOrigin != null && !useOrigin.equalsIgnoreCase(OriginKeys.UAA) && !useOrigin.equalsIgnoreCase(OriginKeys.LDAP)) { + try { + IdentityProvider retrievedByOrigin = externalOAuthProviderProvisioning.retrieveByOrigin(useOrigin, + IdentityZoneHolder.get().getId()); + if (retrievedByOrigin != null && retrievedByOrigin.isActive() && retrievedByOrigin.getOriginKey().equals(useOrigin) + && providerSupportsPasswordGrant(retrievedByOrigin) && (allowedProviders == null || allowedProviders.contains(useOrigin))) { + idp = retrievedByOrigin; + } + } catch (EmptyResultDataAccessException e) { + // ignore + } + } + return idp; + } + private UaaLoginHint getUaaLoginHintForChainedAuth(List allowedProviders) { UaaLoginHint loginHintToUse = null; if (allowedProviders.size() == 1) { @@ -239,9 +258,11 @@ private List getAllowedProviders() { if (clientAuth == null) { throw new BadCredentialsException("No client authentication found."); } - String clientId = clientAuth.getName(); - ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId, IdentityZoneHolder.get().getId()); - return (List)clientDetails.getAdditionalInformation().get(ClientConstants.ALLOWED_PROVIDERS); + List allowedProviders = null; + if (clientAuth.getPrincipal() instanceof UaaClient uaaClient && uaaClient.getAdditionalInformation() != null) { + allowedProviders = (List) uaaClient.getAdditionalInformation().get(ClientConstants.ALLOWED_PROVIDERS); + } + return allowedProviders; } @Override diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClient.java b/server/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClient.java index 41a5e491b10..b18338f17be 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClient.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/client/UaaClient.java @@ -48,7 +48,7 @@ public boolean isAllowPublic() { } } - private Map getAdditionalInformation() { + public Map getAdditionalInformation() { return this.additionalInformation; } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManagerTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManagerTest.java index c1bf8e884fc..a652fa4e401 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManagerTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/authentication/manager/PasswordGrantAuthenticationManagerTest.java @@ -12,6 +12,7 @@ import org.cloudfoundry.identity.uaa.authentication.UaaAuthenticationDetails; import org.cloudfoundry.identity.uaa.authentication.UaaLoginHint; import org.cloudfoundry.identity.uaa.authentication.event.IdentityProviderAuthenticationFailureEvent; +import org.cloudfoundry.identity.uaa.client.UaaClient; import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.extensions.PollutionPreventionExtension; import org.cloudfoundry.identity.uaa.impl.config.RestTemplateConfig; @@ -28,7 +29,6 @@ import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthCodeToken; import org.cloudfoundry.identity.uaa.provider.oauth.ExternalOAuthProviderConfigurator; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; -import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,6 +36,7 @@ import org.mockito.ArgumentCaptor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -45,7 +46,6 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.cloudfoundry.identity.uaa.oauth.provider.ClientDetails; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; @@ -79,7 +79,6 @@ class PasswordGrantAuthenticationManagerTest { private IdentityProviderProvisioning identityProviderProvisioning; private RestTemplateConfig restTemplateConfig; private ExternalOAuthAuthenticationManager externalOAuthAuthenticationManager; - private MultitenantClientServices clientDetailsService; private ExternalOAuthProviderConfigurator externalOAuthProviderConfigurator; private ApplicationEventPublisher eventPublisher; @@ -87,7 +86,7 @@ class PasswordGrantAuthenticationManagerTest { private IdentityProvider uaaProvider; private IdentityProvider ldapProvider; private OIDCIdentityProviderDefinition idpConfig; - private ClientDetails clientDetails; + private UaaClient uaaClient; @BeforeEach void setUp() throws Exception { @@ -95,7 +94,6 @@ void setUp() throws Exception { identityProviderProvisioning = mock(IdentityProviderProvisioning.class); restTemplateConfig = mock(RestTemplateConfig.class); externalOAuthAuthenticationManager = mock(ExternalOAuthAuthenticationManager.class); - clientDetailsService = mock(MultitenantClientServices.class); externalOAuthProviderConfigurator = mock(ExternalOAuthProviderConfigurator.class); idp = mock(IdentityProvider.class); @@ -103,6 +101,7 @@ void setUp() throws Exception { when(idp.getOriginKey()).thenReturn("oidcprovider"); when(idp.getConfig()).thenReturn(idpConfig); when(idp.getType()).thenReturn(OriginKeys.OIDC10); + when(idp.isActive()).thenReturn(true); when(idpConfig.isPasswordGrantEnabled()).thenReturn(true); when(idpConfig.getTokenUrl()).thenReturn(new URL("http://localhost:8080/uaa/oauth/token")); when(idpConfig.getRelyingPartyId()).thenReturn("identity"); @@ -121,11 +120,11 @@ void setUp() throws Exception { Authentication clientAuth = mock(Authentication.class); when(clientAuth.getName()).thenReturn("clientid"); SecurityContextHolder.getContext().setAuthentication(clientAuth); - clientDetails = mock(ClientDetails.class); - when(clientDetails.getAdditionalInformation()).thenReturn(mock(Map.class)); - when(clientDetailsService.loadClientByClientId("clientid", "uaa")).thenReturn(clientDetails); + uaaClient = mock(UaaClient.class); + when(clientAuth.getPrincipal()).thenReturn(uaaClient); + when(uaaClient.getAdditionalInformation()).thenReturn(mock(Map.class)); - instance = new PasswordGrantAuthenticationManager(zoneAwareAuthzAuthenticationManager, identityProviderProvisioning, restTemplateConfig, externalOAuthAuthenticationManager, clientDetailsService, externalOAuthProviderConfigurator); + instance = new PasswordGrantAuthenticationManager(zoneAwareAuthzAuthenticationManager, identityProviderProvisioning, restTemplateConfig, externalOAuthAuthenticationManager, externalOAuthProviderConfigurator); IdentityZoneHolder.clear(); eventPublisher = mock(ApplicationEventPublisher.class); instance.setApplicationEventPublisher(eventPublisher); @@ -144,6 +143,8 @@ void testPasswordGrantNoLoginHint() { instance.authenticate(auth); verify(zoneAwareAuthzAuthenticationManager, times(1)).authenticate(auth); + verify(externalOAuthProviderConfigurator, times(0)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(1)).retrieveActive(any()); } @Test @@ -182,6 +183,8 @@ void testOIDCPasswordGrant() { ArgumentCaptor tokenArgumentCaptor = ArgumentCaptor.forClass(ExternalOAuthCodeToken.class); verify(externalOAuthAuthenticationManager, times(1)).authenticate(tokenArgumentCaptor.capture()); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(0)).retrieveActive(any()); HttpEntity httpEntity = httpEntityArgumentCaptor.getValue(); assertNotNull(httpEntity); @@ -234,6 +237,8 @@ void testOIDCPasswordGrantWithForwardHeader() { ArgumentCaptor tokenArgumentCaptor = ArgumentCaptor.forClass(ExternalOAuthCodeToken.class); verify(externalOAuthAuthenticationManager, times(1)).authenticate(tokenArgumentCaptor.capture()); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(0)).retrieveActive(any()); HttpEntity httpEntity = httpEntityArgumentCaptor.getValue(); assertNotNull(httpEntity); @@ -305,6 +310,22 @@ void testOIDCPasswordGrantProviderNotFound() { } } + @Test + void testOIDCPasswordGrantProviderNotFoundInDB() { + UaaLoginHint loginHint = mock(UaaLoginHint.class); + when(loginHint.getOrigin()).thenReturn("oidcprovider2"); + Authentication auth = mock(Authentication.class); + when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(loginHint); + when(externalOAuthProviderConfigurator.retrieveByOrigin(any(), any())).thenThrow(new EmptyResultDataAccessException(1)); + + try { + instance.authenticate(auth); + fail(); + } catch (ProviderConfigurationException e) { + assertEquals("The origin provided in the login_hint does not match an active Identity Provider, that supports password grant.", e.getMessage()); + } + } + @Test void testOIDCPasswordGrantProviderTypeNotOidc() { IdentityProvider localIdp = mock(IdentityProvider.class); @@ -315,6 +336,7 @@ void testOIDCPasswordGrantProviderTypeNotOidc() { when(localIdp.getType()).thenReturn(OriginKeys.SAML); when(identityProviderProvisioning.retrieveActive("uaa")).thenReturn(Arrays.asList(uaaProvider, ldapProvider, localIdp)); + when(externalOAuthProviderConfigurator.retrieveByOrigin("oidcprovider", "uaa")).thenReturn(localIdp); UaaLoginHint loginHint = mock(UaaLoginHint.class); when(loginHint.getOrigin()).thenReturn("oidcprovider"); Authentication auth = mock(Authentication.class); @@ -335,9 +357,11 @@ void testOIDCPasswordGrantProviderDoesNotSupportPassword() { when(localIdp.getOriginKey()).thenReturn("oidcprovider"); when(localIdp.getConfig()).thenReturn(idpConfig); when(localIdp.getType()).thenReturn(OriginKeys.OIDC10); + when(localIdp.isActive()).thenReturn(true); when(idpConfig.isPasswordGrantEnabled()).thenReturn(false); when(identityProviderProvisioning.retrieveActive("uaa")).thenReturn(Arrays.asList(uaaProvider, ldapProvider, localIdp)); + when(externalOAuthProviderConfigurator.retrieveByOrigin("oidcprovider", "uaa")).thenReturn(localIdp); UaaLoginHint loginHint = mock(UaaLoginHint.class); when(loginHint.getOrigin()).thenReturn("oidcprovider"); Authentication auth = mock(Authentication.class); @@ -358,6 +382,7 @@ void testOIDCPasswordGrantProviderNoRelyingPartyCredentials() { when(localIdp.getOriginKey()).thenReturn("oidcprovider"); when(localIdp.getConfig()).thenReturn(idpConfig); when(localIdp.getType()).thenReturn(OriginKeys.OIDC10); + when(localIdp.isActive()).thenReturn(true); when(idpConfig.isPasswordGrantEnabled()).thenReturn(true); when(identityProviderProvisioning.retrieveActive("uaa")).thenReturn(Arrays.asList(uaaProvider, ldapProvider, localIdp)); @@ -514,6 +539,8 @@ void testOIDCPasswordGrantWithPrompts() { ArgumentCaptor tokenArgumentCaptor = ArgumentCaptor.forClass(ExternalOAuthCodeToken.class); verify(externalOAuthAuthenticationManager, times(1)).authenticate(tokenArgumentCaptor.capture()); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(0)).retrieveActive(any()); HttpEntity httpEntity = httpEntityArgumentCaptor.getValue(); assertNotNull(httpEntity); @@ -547,7 +574,7 @@ void testUaaPasswordGrant_allowedProvidersOnlyUaa() { when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInformation = new HashMap<>(); additionalInformation.put(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("uaa")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInformation); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInformation); instance.authenticate(auth); @@ -564,7 +591,7 @@ void testUaaPasswordGrant_allowedProvidersOnlyLdap() { when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInformation = new HashMap<>(); additionalInformation.put(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("ldap")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInformation); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInformation); instance.authenticate(auth); @@ -581,7 +608,7 @@ void testUaaPasswordGrant_allowedProvidersUaaAndLdap() { when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInformation = new HashMap<>(); additionalInformation.put(ClientConstants.ALLOWED_PROVIDERS, Arrays.asList("uaa","ldap")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInformation); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInformation); instance.authenticate(auth); @@ -608,7 +635,7 @@ void testPasswordGrant_NoLoginHintWithDefaultUaa() { when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInformation = new HashMap<>(); additionalInformation.put(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("uaa")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInformation); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInformation); IdentityZoneHolder.get().getConfig().setDefaultIdentityProvider("uaa"); instance.authenticate(auth); @@ -643,6 +670,8 @@ void testOIDCPasswordGrant_NoLoginHintWithDefaultOIDC() { ArgumentCaptor tokenArgumentCaptor = ArgumentCaptor.forClass(ExternalOAuthCodeToken.class); verify(externalOAuthAuthenticationManager, times(1)).authenticate(tokenArgumentCaptor.capture()); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(0)).retrieveActive(any()); HttpEntity httpEntity = httpEntityArgumentCaptor.getValue(); assertNotNull(httpEntity); @@ -688,6 +717,8 @@ void testOIDCPasswordGrant_LoginHintOidcOverridesDefaultUaa() { verify(rt, times(1)).exchange(eq("http://localhost:8080/uaa/oauth/token"), eq(HttpMethod.POST), any(HttpEntity.class),eq(new ParameterizedTypeReference>(){})); verify(externalOAuthAuthenticationManager, times(1)).authenticate(any(ExternalOAuthCodeToken.class)); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(0)).retrieveActive(any()); } @Test @@ -698,7 +729,7 @@ void testOIDCPasswordGrant_LoginHintUaaOverridesDefaultOidc() { when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInformation = new HashMap<>(); additionalInformation.put(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("uaa")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInformation); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInformation); IdentityZoneHolder.get().getConfig().setDefaultIdentityProvider("oidcprovider"); instance.authenticate(auth); @@ -717,7 +748,7 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedSingleIdpOIDC() { when(auth.getPrincipal()).thenReturn("marissa"); when(auth.getCredentials()).thenReturn("koala"); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("oidcprovider")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); RestTemplate rt = mock(RestTemplate.class); when(restTemplateConfig.nonTrustingRestTemplate()).thenReturn(rt); @@ -732,6 +763,8 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedSingleIdpOIDC() { verify(rt, times(1)).exchange(eq("http://localhost:8080/uaa/oauth/token"), eq(HttpMethod.POST), any(HttpEntity.class),eq(new ParameterizedTypeReference>(){})); verify(externalOAuthAuthenticationManager, times(1)).authenticate(any(ExternalOAuthCodeToken.class)); verify(zoneAwareAuthzAuthenticationManager, times(0)).authenticate(any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(1)).retrieveActive(any()); } @Test @@ -741,7 +774,7 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedSingleIdpDoesNotSupportPa when(auth.getPrincipal()).thenReturn("marissa"); when(auth.getCredentials()).thenReturn("koala"); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("oidcprovider")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); IdentityProvider localIdp = mock(IdentityProvider.class); OIDCIdentityProviderDefinition idpConfig = mock(OIDCIdentityProviderDefinition.class); when(localIdp.getOriginKey()).thenReturn("oidcprovider"); @@ -765,7 +798,7 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedSingleIdpUAA() { Authentication auth = mock(Authentication.class); when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Collections.singletonList("uaa")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); instance.authenticate(auth); @@ -782,12 +815,14 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedChainedAuth() { Authentication auth = mock(Authentication.class); when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Arrays.asList("uaa", "ldap")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); instance.authenticate(auth); verify(zoneAwareAuthzAuthenticationManager, times(1)).authenticate(auth); verify(zoneAwareAuthzAuthenticationManager, times(0)).setLoginHint(any(), any()); + verify(externalOAuthProviderConfigurator, times(1)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(1)).retrieveActive(any()); } @Test @@ -796,7 +831,7 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedMultipleIdpsWithUaa() { Authentication auth = mock(Authentication.class); when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Arrays.asList("uaa", "oidcprovider")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); instance.authenticate(auth); @@ -813,7 +848,7 @@ void testOIDCPasswordGrant_NoLoginHintDefaultNotAllowedMultipleIdpsOnlyOIDC() { Authentication auth = mock(Authentication.class); when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(null); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Arrays.asList("oidcprovider", "oidcprovider2")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); IdentityProvider localIdp = mock(IdentityProvider.class); OIDCIdentityProviderDefinition idpConfig = mock(OIDCIdentityProviderDefinition.class); @@ -841,6 +876,8 @@ void testPasswordGrant_NoLoginHintNoDefaultTriesChainedAuth() { verify(zoneAwareAuthzAuthenticationManager, times(1)).authenticate(auth); verify(zoneAwareAuthzAuthenticationManager, times(0)).setLoginHint(any(), any()); + verify(externalOAuthProviderConfigurator, times(0)).retrieveByOrigin(any(), any()); + verify(identityProviderProvisioning, times(1)).retrieveActive(any()); } @Test @@ -850,7 +887,7 @@ void testOIDCPasswordGrant_LoginHintProviderNotAllowed() { Authentication auth = mock(Authentication.class); when(zoneAwareAuthzAuthenticationManager.extractLoginHint(auth)).thenReturn(loginHint); Map additionalInfo = Collections.singletonMap(ClientConstants.ALLOWED_PROVIDERS, Arrays.asList("uaa", "oidcprovider")); - when(clientDetails.getAdditionalInformation()).thenReturn(additionalInfo); + when(uaaClient.getAdditionalInformation()).thenReturn(additionalInfo); try { instance.authenticate(auth); diff --git a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml index 87664c17e94..c2e6763c55c 100755 --- a/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml +++ b/uaa/src/main/webapp/WEB-INF/spring/oauth-endpoints.xml @@ -696,7 +696,6 @@ -