Skip to content

Commit

Permalink
Merge pull request #122 from kakawait/enhancement/dynamic-proxy-callb…
Browse files Browse the repository at this point in the history
…ack-api

Revamp proxy callback api to be easily extends
  • Loading branch information
kakawait authored Sep 4, 2019
2 parents 600cfd7 + 491aa69 commit c818717
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.kakawait.spring.boot.security.cas.autoconfigure;


import com.kakawait.spring.boot.security.cas.autoconfigure.CasAuthenticationFilterConfigurer;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.junit.Test;
import org.mockito.Mockito;
Expand All @@ -12,8 +10,6 @@
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import java.util.Comparator;

import static org.assertj.core.api.Assertions.assertThat;

/**
Expand Down Expand Up @@ -48,20 +44,14 @@ public void configure_WithAnyParameters_InjectInsideCasAuthenticationFilter() {
configurer.configure(filter);

assertThat(filter)
.extracting("proxyGrantingTicketStorage", "authenticationDetailsSource", "successHandler",
"proxyFailureHandler", "requiresAuthenticationRequestMatcher")
.usingElementComparator((Comparator<Object>) (o1, o2) -> (o1 == o2) ? 0 : -1)
.containsOnly(proxyGrantingTicketStorage, serviceAuthenticationDetailsSource,
authenticationSuccessHandler, proxyAuthenticationFailureHandler, requestMatcher);

assertThat(filter)
.hasFieldOrPropertyWithValue("proxyGrantingTicketStorage", proxyGrantingTicketStorage)
.hasFieldOrPropertyWithValue("authenticationDetailsSource", serviceAuthenticationDetailsSource)
.hasFieldOrPropertyWithValue("successHandler", authenticationSuccessHandler)
.hasFieldOrPropertyWithValue("proxyFailureHandler", proxyAuthenticationFailureHandler)
.hasFieldOrPropertyWithValue("requiresAuthenticationRequestMatcher", requestMatcher)
.hasFieldOrPropertyWithValue("proxyReceptorMatcher",
new AntPathRequestMatcher("/**" + proxyReceptorUrl));

assertThat(filter)
.extracting("failureHandler")
.extracting("serviceTicketFailureHandler")
.usingElementComparator((Comparator<Object>) (o1, o2) -> (o1 == o2) ? 0 : -1)
.containsOnly(authenticationFailureHandler);
new AntPathRequestMatcher("/**" + proxyReceptorUrl))
.hasFieldOrPropertyWithValue("failureHandler.serviceTicketFailureHandler",
authenticationFailureHandler);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.kakawait.spring.boot.security.cas.autoconfigure;

import com.kakawait.spring.boot.security.cas.autoconfigure.CasAuthenticationProviderSecurityBuilder;
import com.kakawait.spring.boot.security.cas.autoconfigure.CasSecurityProperties;
import com.kakawait.spring.security.cas.authentication.DynamicProxyCallbackUrlCasAuthenticationProvider;
import org.jasig.cas.client.validation.TicketValidator;
import org.junit.Before;
Expand Down Expand Up @@ -41,7 +39,6 @@ public void build_WithDynamicResolutionMode_InstanceOfDynamicProxyCallbackUrlCas
assertThat(builder.build()).isExactlyInstanceOf(DynamicProxyCallbackUrlCasAuthenticationProvider.class);
}

@SuppressWarnings("unchecked")
@Test
public void build_AnyParameters_InjectInsideCasAuthenticationProvider() {
String key = "key";
Expand All @@ -64,10 +61,6 @@ public void build_AnyParameters_InjectInsideCasAuthenticationProvider() {
.usingElementComparator((Comparator<Object>) (o1, o2) -> (o1 == o2) ? 0 : -1)
.containsOnly(key, userDetailsService, grantedAuthoritiesMapper, statelessTicketCache, ticketValidator);

assertThat(builder.build())
.extracting("messages")
.extracting("messageSource")
.usingElementComparator((Comparator<Object>) (o1, o2) -> (o1 == o2) ? 0 : -1)
.containsOnly(messageSource);
assertThat(builder.build()).hasFieldOrPropertyWithValue("messages.messageSource", messageSource);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.kakawait.spring.boot.security.cas.autoconfigure;


import com.kakawait.spring.boot.security.cas.autoconfigure.CasSecurityAutoConfiguration;
import com.kakawait.spring.security.cas.LaxServiceProperties;
import com.kakawait.spring.security.cas.client.ticket.AttributePrincipalProxyTicketProvider;
import com.kakawait.spring.security.cas.client.ticket.ProxyTicketProvider;
Expand All @@ -22,6 +21,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.TestingAuthenticationToken;
Expand Down Expand Up @@ -54,8 +54,8 @@ public class CasSecurityAutoConfigurationTest {

@After
public void tearDown() {
if (this.context != null) {
this.context.close();
if (context != null) {
context.close();
}
}

Expand Down Expand Up @@ -155,7 +155,10 @@ public void autoConfigure_WithProxyCallbackPathAndCallbackUrl_AbsoluteProxyCallb
properties.put("security.cas.service.callback-base-url", "http://app:8081/test/");

load(properties, EmptyConfiguration.class);
assertThat(context.getBean(ProxyCallbackAndServiceAuthenticationDetailsSource.class))

ProxyCallbackAndServiceAuthenticationDetailsSource serviceAuthenticationDetailsSource =
context.getBean(ProxyCallbackAndServiceAuthenticationDetailsSource.class);
assertThat(serviceAuthenticationDetailsSource.buildDetails(new MockHttpServletRequest()))
.hasFieldOrPropertyWithValue("proxyCallbackUri", URI.create("http://app:8081/test/cas/proxy-callback"));
}

Expand All @@ -165,7 +168,10 @@ public void autoConfigure_WithProxyCallbackPathButWithoutCallbackUrl_RelativePro
properties.put("security.cas.service.paths.proxy-callback", "/cas/proxy-callback");

load(properties, EmptyConfiguration.class);
assertThat(context.getBean(ProxyCallbackAndServiceAuthenticationDetailsSource.class))

ProxyCallbackAndServiceAuthenticationDetailsSource serviceAuthenticationDetailsSource =
context.getBean(ProxyCallbackAndServiceAuthenticationDetailsSource.class);
assertThat(serviceAuthenticationDetailsSource.buildDetails(new MockHttpServletRequest()))
.hasFieldOrPropertyWithValue("proxyCallbackUri", URI.create("/cas/proxy-callback"));
}

Expand All @@ -186,9 +192,6 @@ public void autoConfigure_WithCustomSecurityPath_NoIllegalArgumentException() {
load(properties, EmptyConfiguration.class);
}

@Configuration
static class EmptyConfiguration {}

private Properties getDefaultProperties() {
Properties properties = new Properties();
properties.put("security.cas.server.base-url", CAS_SERVER_BASE_URL);
Expand Down Expand Up @@ -225,6 +228,9 @@ private void load(Properties properties, Class<?>... configs) {
this.context = context;
}

@Configuration
static class EmptyConfiguration {}

private static class DummyAuthenticationManagerConfiguration {
@Bean
AuthenticationManager authenticationManager() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.kakawait.spring.boot.security.cas.autoconfigure;

import com.kakawait.spring.boot.security.cas.autoconfigure.CasSingleSignOutFilterConfigurer;
import org.jasig.cas.client.session.SessionMappingStorage;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.Comparator;

import static org.assertj.core.api.Assertions.assertThat;

/**
Expand All @@ -33,9 +30,7 @@ public void configure_WithAnyParameters_InjectInsideSingleSignOutHandler() {
.hasFieldOrPropertyWithValue("artifactParameterName", "dummyArtifactParameterName")
.hasFieldOrPropertyWithValue("logoutParameterName", "dummyLogoutParameterName")
.hasFieldOrPropertyWithValue("relayStateParameterName", "dummyRelayStateParameterName")
.extracting("sessionMappingStorage")
.usingElementComparator((Comparator<Object>) (o1, o2) -> (o1 == o2) ? 0 : -1)
.containsOnly(sessionMappingStorage);
.hasFieldOrPropertyWithValue("sessionMappingStorage", sessionMappingStorage);
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.kakawait.spring.boot.security.cas.autoconfigure;

import com.kakawait.spring.boot.security.cas.autoconfigure.CasTicketValidatorBuilder;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
Expand Down Expand Up @@ -168,7 +167,6 @@ public void build_ServiceValidatorProtocolWithIncompatibleParameter_LogWarnMessa
}
}

@SuppressWarnings("ConstantConditions")
private CasTicketValidatorBuilder fulfilledBuilder() {
HttpURLConnectionFactory urlConnectionFactory = Mockito.mock(HttpURLConnectionFactory.class);
ProxyList proxyList = new ProxyList();
Expand All @@ -192,7 +190,6 @@ private CasTicketValidatorBuilder fulfilledBuilder() {
return builder;
}

@SuppressWarnings("ConstantConditions")
private void testBuilder(int protocolVersion) {
HttpURLConnectionFactory urlConnectionFactory = Mockito.mock(HttpURLConnectionFactory.class);
ProxyList proxyList = new ProxyList();
Expand Down Expand Up @@ -249,10 +246,10 @@ private void testBuilder(int protocolVersion) {
.containsExactly(values.toArray());

if (protocolVersion > 1) {
assertThat(ticketValidator).extracting("allowEmptyProxyChain").containsOnly(allowEmptyProxyChain);
assertThat(ticketValidator).extracting("acceptAnyProxy").containsOnly(!proxyChainsValidation);
assertThat(ticketValidator).hasFieldOrPropertyWithValue("allowEmptyProxyChain", allowEmptyProxyChain);
assertThat(ticketValidator).hasFieldOrPropertyWithValue("acceptAnyProxy", !proxyChainsValidation);
}
assertThat(ticketValidator).extracting("renew").containsOnly(renew);
assertThat(ticketValidator).hasFieldOrPropertyWithValue("renew", renew);
}

}
16 changes: 8 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,22 @@

<!-- spring managed version -->
<!-- CVE-2018-7489 -->
<jackson.version>2.8.11.1</jackson.version>
<jackson.version>2.9.9</jackson.version>

<!-- dependencies -->
<spring-boot-dependencies.version>2.0.2.RELEASE</spring-boot-dependencies.version>
<spring-boot-dependencies.version>2.1.7.RELEASE</spring-boot-dependencies.version>

<!-- provided dependencies -->
<lombok.version>1.16.18</lombok.version>
<lombok.version>1.18.8</lombok.version>

<!-- test dependencies -->
<assertj-core.version>3.9.1</assertj-core.version>
<mockito-core.version>2.18.0</mockito-core.version>
<assertj-core.version>3.13.2</assertj-core.version>
<mockito-core.version>3.0.0</mockito-core.version>

<!-- plugins -->
<jacoco-maven-plugin.version>0.8.1</jacoco-maven-plugin.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.0.0</maven-javadoc-plugin.version>
<jacoco-maven-plugin.version>0.8.4</jacoco-maven-plugin.version>
<maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version>
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
</properties>
Expand Down
4 changes: 2 additions & 2 deletions spring-security-cas-extension/pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,38 @@
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.web.servlet.support.ServletUriComponentsBuilder.*;
import static org.springframework.web.servlet.support.ServletUriComponentsBuilder.fromContextPath;

/**
* @author Thibaud Leprêtre
*/
class DefaultProxyCallbackAndServiceAuthenticationDetails implements ProxyCallbackAndServiceAuthenticationDetails {
public class DefaultProxyCallbackAndServiceAuthenticationDetails
implements ProxyCallbackAndServiceAuthenticationDetails {

private final transient ServiceProperties serviceProperties;
private static final long serialVersionUID = -88469969834244098L;

private final transient HttpServletRequest context;
private final transient ServiceProperties serviceProperties;

private final URI proxyCallbackUri;

DefaultProxyCallbackAndServiceAuthenticationDetails(ServiceProperties serviceProperties, HttpServletRequest context,
URI proxyCallbackUri) {
protected transient HttpServletRequest context;

public DefaultProxyCallbackAndServiceAuthenticationDetails(ServiceProperties serviceProperties, URI proxyCallbackUri) {
this.serviceProperties = serviceProperties;
this.context = context;
this.proxyCallbackUri = proxyCallbackUri;
}

@Override
public void setContext(HttpServletRequest context) {
this.context = context;
}

@Override
public String getProxyCallbackUrl() {
if (proxyCallbackUri == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

import org.springframework.security.cas.web.authentication.ServiceAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;

/**
* @author Thibaud Leprêtre
*/
public interface ProxyCallbackAndServiceAuthenticationDetails extends ServiceAuthenticationDetails {
String getProxyCallbackUrl();

void setContext(HttpServletRequest context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,25 @@
* @author Thibaud Leprêtre
*/
public class ProxyCallbackAndServiceAuthenticationDetailsSource extends ServiceAuthenticationDetailsSource {
private final ServiceProperties serviceProperties;

private final URI proxyCallbackUri;
private final ProxyCallbackAndServiceAuthenticationDetails serviceAuthenticationDetails;

public ProxyCallbackAndServiceAuthenticationDetailsSource(ServiceProperties serviceProperties,
ProxyCallbackAndServiceAuthenticationDetails serviceAuthenticationDetails) {
super(serviceProperties);
this.serviceAuthenticationDetails = serviceAuthenticationDetails;
}

public ProxyCallbackAndServiceAuthenticationDetailsSource(ServiceProperties serviceProperties,
URI proxyCallbackUri) {
super(serviceProperties);
this.serviceProperties = serviceProperties;
this.proxyCallbackUri = proxyCallbackUri;
serviceAuthenticationDetails =
new DefaultProxyCallbackAndServiceAuthenticationDetails(serviceProperties, proxyCallbackUri);
}

@Override
public ServiceAuthenticationDetails buildDetails(HttpServletRequest context) {
return new DefaultProxyCallbackAndServiceAuthenticationDetails(serviceProperties, context, proxyCallbackUri);
serviceAuthenticationDetails.setContext(context);
return serviceAuthenticationDetails;
}
}
Loading

0 comments on commit c818717

Please sign in to comment.