Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic discovery provider locator can't resolved principal #5988

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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,7 +1,9 @@
package org.apereo.cas.pac4j.discovery;

import org.apereo.cas.authentication.credential.BasicIdentifiableCredential;
import org.apereo.cas.authentication.principal.NullPrincipal;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalFactoryUtils;
import org.apereo.cas.authentication.principal.PrincipalResolver;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.pac4j.client.DelegatedIdentityProviders;
Expand Down Expand Up @@ -53,7 +55,7 @@ public Optional<IndirectClient> locate(final DynamicDiscoveryProviderRequest req
new TypeReference<Map<String, DelegatedAuthenticationDynamicDiscoveryProvider>>() {
});

val principal = principalResolver.resolve(new BasicIdentifiableCredential(request.getUserId()));
val principal = getPrincipal(request);
LOGGER.debug("Resolved principal to be [{}]", principal);

return mappings
Expand All @@ -72,12 +74,24 @@ public Optional<IndirectClient> locate(final DynamicDiscoveryProviderRequest req
return Optional.empty();
}

private Principal getPrincipal(final DynamicDiscoveryProviderRequest request) throws Throwable {
val userId = request.getUserId();
val resolvedPrincipal = principalResolver.resolve(new BasicIdentifiableCredential(userId));

if (resolvedPrincipal instanceof NullPrincipal) {
LOGGER.debug("No principal was resolved. Falling back to the username [{}] from the credentials.", userId);
return PrincipalFactoryUtils.newPrincipalFactory().createPrincipal(userId);
}

return resolvedPrincipal;
}

protected DelegatedAuthenticationDynamicDiscoveryProvider getMatchingProvider(
final Principal principal,
final String keyPattern,
final DelegatedAuthenticationDynamicDiscoveryProvider provider) {
val attrName = properties.getAuthn().getPac4j().getCore().getDiscoverySelection().getJson().getPrincipalAttribute();
if (StringUtils.isNotBlank(attrName)) {
if (StringUtils.isNotBlank(attrName) && principal.getAttributes().containsKey(attrName)) {
val attrValues = principal.getAttributes().get(attrName);
LOGGER.debug("Checking attribute values [{}] against [{}]", attrValues, keyPattern);
return attrValues.stream().anyMatch(value -> RegexUtils.find(keyPattern, value.toString())) ? provider : null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.apereo.cas.pac4j.discovery;

import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.PrincipalElectionStrategy;
import org.apereo.cas.authentication.principal.Principal;
import org.apereo.cas.authentication.principal.PrincipalResolver;
import org.apereo.cas.authentication.principal.resolvers.ChainingPrincipalResolver;
import org.apereo.cas.authentication.principal.resolvers.EchoingPrincipalResolver;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.pac4j.client.DelegatedIdentityProviderFactory;
import org.apereo.cas.services.RegisteredServiceTestUtils;
Expand All @@ -12,6 +14,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.pac4j.saml.client.SAML2Client;
import org.springframework.core.io.ClassPathResource;
import java.util.List;
Expand All @@ -27,17 +30,23 @@
*/
@Tag("Delegation")
class DefaultDelegatedAuthenticationDynamicDiscoveryProviderLocatorTests {

private CasConfigurationProperties properties;

@BeforeEach
public void setup() {
this.properties = new CasConfigurationProperties();
}

private DelegatedAuthenticationDynamicDiscoveryProviderLocator getLocator(final Principal principal) throws Throwable {
private DelegatedAuthenticationDynamicDiscoveryProviderLocator getLocator(final Principal principal, final List<PrincipalResolver> principalResolvers)
throws Throwable {
val producer = mock(DelegatedClientIdentityProviderConfigurationProducer.class);
val resolver = mock(PrincipalResolver.class);
when(resolver.resolve(any(Credential.class))).thenReturn(principal);

val electionStrategy = mock(PrincipalElectionStrategy.class);
val ts = ArgumentMatchers.<Principal>anyList();
when(electionStrategy.nominate(ts, any(Map.class))).thenReturn(principal);
val resolver = new ChainingPrincipalResolver(electionStrategy, properties);
resolver.setChain(principalResolvers);

val client = new SAML2Client();
val refreshableClients = new RefreshableDelegatedIdentityProviders("http://localhost:8080/cas",
Expand All @@ -53,7 +62,7 @@ private DelegatedAuthenticationDynamicDiscoveryProviderLocator getLocator(final
@Test
void verifyResourceIsUnavailable() throws Throwable {
val principal = RegisteredServiceTestUtils.getPrincipal("cas@example.org");
val locator = getLocator(principal);
val locator = getLocator(principal, List.of(new EchoingPrincipalResolver()));
val request = DelegatedAuthenticationDynamicDiscoveryProviderLocator.DynamicDiscoveryProviderRequest
.builder()
.userId(principal.getId())
Expand All @@ -65,7 +74,8 @@ void verifyResourceIsUnavailable() throws Throwable {
@Test
void verifyResourceFindUser() throws Throwable {
val principal = RegisteredServiceTestUtils.getPrincipal("cas@example.org", Map.of("cn", List.of("cas", "casuser", "cas-user")));
val locator = getLocator(principal);
val locator = getLocator(principal, List.of(new EchoingPrincipalResolver()));

val json = properties.getAuthn().getPac4j().getCore().getDiscoverySelection().getJson();
json.setLocation(new ClassPathResource("delegated-discovery.json"));
val request = DelegatedAuthenticationDynamicDiscoveryProviderLocator.DynamicDiscoveryProviderRequest
Expand All @@ -78,9 +88,8 @@ void verifyResourceFindUser() throws Throwable {

@Test
void verifyPrincipalAttribute() throws Throwable {
val principal = RegisteredServiceTestUtils.getPrincipal("cas@example.org",
Map.of("email", List.of("cas@example.net", "casuser@example.org", "casuser@yahoo.com")));
val locator = getLocator(principal);
val principal = RegisteredServiceTestUtils.getPrincipal("cas@example.org", Map.of("email", List.of("cas@example.net", "casuser@example.org", "casuser@yahoo.com")));
val locator = getLocator(principal, List.of(new EchoingPrincipalResolver()));
val json = properties.getAuthn().getPac4j().getCore().getDiscoverySelection().getJson();
json.setLocation(new ClassPathResource("delegated-discovery.json"));
json.setPrincipalAttribute("email");
Expand Down