Browse Source

OpenIDConfigTests groovy->java

For the remember me test, there is some hand configuration that was
carried over from the groovy test as there isn't a way via the xml
config to achieve the same result.

For the attribute exchange test, in order to reduce the amount of
endpoint configuration, the test uses a bit of reflection to disable
the OpenID association step. This is because the xml config does not
support wiring a custom ConsumerManager, like the java configurer
does.

Issue: gh-4939
Josh Cummings 7 years ago
parent
commit
195a6943e2

+ 0 - 166
config/src/test/groovy/org/springframework/security/config/http/HttpOpenIDConfigTests.groovy

@@ -1,166 +0,0 @@
-package org.springframework.security.config.http
-
-import javax.servlet.http.HttpServletRequest
-import org.springframework.beans.factory.parsing.BeanDefinitionParsingException
-import org.springframework.mock.web.MockFilterChain
-import org.springframework.mock.web.MockHttpServletRequest
-import org.springframework.mock.web.MockHttpServletResponse
-import org.springframework.security.config.BeanIds
-import org.springframework.security.openid.OpenIDAuthenticationFilter
-import org.springframework.security.openid.OpenIDAuthenticationToken
-import org.springframework.security.openid.OpenIDConsumer
-import org.springframework.security.openid.OpenIDConsumerException
-
-import org.springframework.security.web.access.ExceptionTranslationFilter
-import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices
-import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
-
-import javax.servlet.Filter
-
-/**
- *
- * @author Luke Taylor
- */
-class OpenIDConfigTests extends AbstractHttpConfigTests {
-
-	def openIDAndFormLoginWorkTogether() {
-		xml.http() {
-			'openid-login'()
-			'form-login'()
-		}
-		createAppContext()
-
-		def etf = getFilter(ExceptionTranslationFilter)
-		def ap = etf.getAuthenticationEntryPoint();
-
-		expect:
-		ap.loginFormUrl == "/login"
-		// Default login filter should be present since we haven't specified any login URLs
-		getFilter(DefaultLoginPageGeneratingFilter) != null
-	}
-
-	def formLoginEntryPointTakesPrecedenceIfLoginUrlIsSet() {
-		xml.http() {
-			'openid-login'()
-			'form-login'('login-page': '/form-page')
-		}
-		createAppContext()
-
-		expect:
-		getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/form-page'
-	}
-
-	def openIDEntryPointTakesPrecedenceIfLoginUrlIsSet() {
-		xml.http() {
-			'openid-login'('login-page': '/openid-page')
-			'form-login'()
-		}
-		createAppContext()
-
-		expect:
-		getFilter(ExceptionTranslationFilter).authenticationEntryPoint.loginFormUrl == '/openid-page'
-	}
-
-	def multipleLoginPagesCausesError() {
-		when:
-		xml.http() {
-			'openid-login'('login-page': '/openid-page')
-			'form-login'('login-page': '/form-page')
-		}
-		createAppContext()
-		then:
-		thrown(BeanDefinitionParsingException)
-	}
-
-	def openIDAndRememberMeWorkTogether() {
-		xml.debug()
-		xml.http() {
-			interceptUrl('/**', 'denyAll')
-			'openid-login'()
-			'remember-me'()
-			'csrf'(disabled:true)
-		}
-		createAppContext()
-
-		// Default login filter should be present since we haven't specified any login URLs
-		def loginFilter = getFilter(DefaultLoginPageGeneratingFilter)
-		def openIDFilter = getFilter(OpenIDAuthenticationFilter)
-		openIDFilter.setConsumer(new OpenIDConsumer() {
-			public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm)
-					throws OpenIDConsumerException {
-				return "http://testopenid.com?openid.return_to=" + returnToUrl;
-			}
-
-			public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException {
-				throw new UnsupportedOperationException();
-			}
-		})
-		Set<String> returnToUrlParameters = new HashSet<String>()
-		returnToUrlParameters.add(AbstractRememberMeServices.DEFAULT_PARAMETER)
-		openIDFilter.setReturnToUrlParameters(returnToUrlParameters)
-		assert loginFilter.openIDrememberMeParameter != null
-
-		MockHttpServletRequest request = new MockHttpServletRequest(method:'GET');
-		MockHttpServletResponse response = new MockHttpServletResponse();
-
-		when: "Initial request is made"
-		Filter fc = appContext.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN)
-		request.setServletPath("/something.html")
-		fc.doFilter(request, response, new MockFilterChain())
-		then: "Redirected to login"
-		response.getRedirectedUrl().endsWith("/login")
-		when: "Login page is requested"
-		request.setServletPath("/login")
-		request.setRequestURI("/login")
-		response = new MockHttpServletResponse()
-		fc.doFilter(request, response, new MockFilterChain())
-		then: "Remember-me choice is added to page"
-		response.getContentAsString().contains(AbstractRememberMeServices.DEFAULT_PARAMETER)
-		when: "Login is submitted with remember-me selected"
-		request.servletPath = "/login/openid"
-		request.setParameter(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "http://hey.openid.com/")
-		request.setParameter(AbstractRememberMeServices.DEFAULT_PARAMETER, "on")
-		response = new MockHttpServletResponse();
-		fc.doFilter(request, response, new MockFilterChain());
-		String expectedReturnTo = request.getRequestURL().append("?")
-										.append(AbstractRememberMeServices.DEFAULT_PARAMETER)
-										.append("=").append("on").toString();
-		then: "return_to URL contains remember-me choice"
-		response.getRedirectedUrl() == "http://testopenid.com?openid.return_to=" + expectedReturnTo
-	}
-
-	def openIDWithAttributeExchangeConfigurationIsParsedCorrectly() {
-		xml.http() {
-			'openid-login'() {
-				'attribute-exchange'() {
-					'openid-attribute'(name: 'nickname', type: 'http://schema.openid.net/namePerson/friendly')
-					'openid-attribute'(name: 'email', type: 'http://schema.openid.net/contact/email', required: 'true',
-							'count': '2')
-				}
-			}
-		}
-		createAppContext()
-
-		List attributes = getFilter(OpenIDAuthenticationFilter).consumer.attributesToFetchFactory.createAttributeList('http://someid')
-
-		expect:
-		attributes.size() == 2
-		attributes[0].name == 'nickname'
-		attributes[0].type == 'http://schema.openid.net/namePerson/friendly'
-		!attributes[0].required
-		attributes[1].required
-		attributes[1].getCount() == 2
-	}
-
-	def 'SEC-2919: DefaultLoginGeneratingFilter should not be present if login-page="/login"'() {
-		when:
-		xml.http() {
-			'openid-login'('login-page':'/login')
-		}
-		createAppContext()
-
-		then:
-		getFilter(DefaultLoginPageGeneratingFilter) == null
-	}
-
-}

+ 223 - 0
config/src/test/java/org/springframework/security/config/http/OpenIDConfigTests.java

@@ -0,0 +1,223 @@
+/*
+ * Copyright 2002-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.config.http;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.servlet.Filter;
+import javax.servlet.http.HttpServletRequest;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openid4java.consumer.ConsumerManager;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.openid.OpenID4JavaConsumer;
+import org.springframework.security.openid.OpenIDAuthenticationFilter;
+import org.springframework.security.openid.OpenIDConsumer;
+import org.springframework.security.util.FieldUtils;
+import org.springframework.security.web.FilterChainProxy;
+import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
+import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.openid4java.discovery.yadis.YadisResolver.YADIS_XRDS_LOCATION;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ * Tests usage of the &lt;openid-login&gt; element
+ *
+ * @author Luke Taylor
+ */
+public class OpenIDConfigTests {
+	private static final String CONFIG_LOCATION_PREFIX =
+			"classpath:org/springframework/security/config/http/OpenIDConfigTests";
+
+	@Autowired
+	MockMvc mvc;
+
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Test
+	public void requestWhenOpenIDAndFormLoginBothConfiguredThenRedirectsToGeneratedLoginPage()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithFormLogin")).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login"));
+
+		assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNotNull();
+	}
+
+	@Test
+	public void requestWhenOpenIDAndFormLoginWithFormLoginPageConfiguredThenFormLoginPageWins()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithFormLoginPage")).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/form-page"));
+	}
+
+	@Test
+	public void requestWhenOpenIDAndFormLoginWithOpenIDLoginPageConfiguredThenOpenIDLoginPageWins()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithOpenIDLoginPageAndFormLogin")).autowire();
+
+		this.mvc.perform(get("/"))
+				.andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/openid-page"));
+	}
+
+	@Test
+	public void configureWhenOpenIDAndFormLoginBothConfigureLoginPagesThenWiringException()
+			throws Exception {
+
+		assertThatCode(() -> this.spring.configLocations(this.xml("WithFormLoginAndOpenIDLoginPages")).autowire())
+				.isInstanceOf(BeanDefinitionParsingException.class);
+	}
+
+	@Test
+	public void requestWhenOpenIDAndRememberMeConfiguredThenRememberMePassedToIdp()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithRememberMe")).autowire();
+
+		OpenIDAuthenticationFilter openIDFilter = getFilter(OpenIDAuthenticationFilter.class);
+
+		String openIdEndpointUrl = "http://testopenid.com?openid.return_to=";
+		Set<String> returnToUrlParameters = new HashSet<>();
+		returnToUrlParameters.add(AbstractRememberMeServices.DEFAULT_PARAMETER);
+		openIDFilter.setReturnToUrlParameters(returnToUrlParameters);
+
+		OpenIDConsumer consumer = mock(OpenIDConsumer.class);
+		when(consumer.beginConsumption(any(HttpServletRequest.class), anyString(), anyString(), anyString()))
+				.then(invocation -> openIdEndpointUrl + invocation.getArgument(2));
+		openIDFilter.setConsumer(consumer);
+
+		String expectedReturnTo = new StringBuilder("http://localhost/login/openid").append("?")
+				.append(AbstractRememberMeServices.DEFAULT_PARAMETER)
+				.append("=").append("on").toString();
+
+		this.mvc.perform(get("/"))
+				.andExpect(status().isFound())
+				.andExpect(redirectedUrl("http://localhost/login"));
+
+		this.mvc.perform(get("/login"))
+				.andExpect(status().isOk())
+				.andExpect(content().string(containsString(AbstractRememberMeServices.DEFAULT_PARAMETER)));
+
+		this.mvc.perform(get("/login/openid")
+				.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "http://hey.openid.com/")
+				.param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on"))
+				.andExpect(status().isFound())
+				.andExpect(redirectedUrl(openIdEndpointUrl + expectedReturnTo));
+	}
+
+	@Test
+	public void requestWhenAttributeExchangeConfiguredThenFetchAttributesPassedToIdp()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithOpenIDAttributes")).autowire();
+
+		OpenIDAuthenticationFilter openIDFilter = getFilter(OpenIDAuthenticationFilter.class);
+		OpenID4JavaConsumer consumer = getFieldValue(openIDFilter, "consumer");
+		ConsumerManager manager = getFieldValue(consumer, "consumerManager");
+		manager.setMaxAssocAttempts(0);
+
+		try ( MockWebServer server = new MockWebServer() ) {
+			String endpoint = server.url("/").toString();
+
+			server.enqueue(new MockResponse()
+					.addHeader(YADIS_XRDS_LOCATION, endpoint));
+			server.enqueue(new MockResponse()
+					.setBody(String.format(
+							"<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>",
+							endpoint)));
+
+			this.mvc.perform(get("/login/openid")
+					.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
+					.andExpect(status().isFound())
+					.andExpect(result -> result.getResponse().getRedirectedUrl().endsWith(
+							"openid.ext1.type.nickname=http%3A%2F%2Fschema.openid.net%2FnamePerson%2Ffriendly&" +
+							"openid.ext1.if_available=nickname&" +
+							"openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&" +
+							"openid.ext1.required=email&" +
+							"openid.ext1.count.email=2"));
+		}
+	}
+
+	/**
+	 * SEC-2919
+	 */
+	@Test
+	public void requestWhenLoginPageConfiguredWithPhraseLoginThenRedirectsOnlyToUserGeneratedLoginPage()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("Sec2919")).autowire();
+
+		assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNull();
+
+		this.mvc.perform(get("/login"))
+				.andExpect(status().isOk())
+				.andExpect(content().string("a custom login page"));
+	}
+
+	@RestController
+	static class CustomLoginController {
+		@GetMapping("/login")
+		public String custom() {
+			return "a custom login page";
+		}
+	}
+
+	private <T extends Filter> T getFilter(Class<T> clazz) {
+		FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
+		return (T) filterChain.getFilters("/").stream()
+				.filter(clazz::isInstance)
+				.findFirst()
+				.orElse(null);
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
+	private static <T> T getFieldValue(Object bean, String fieldName) throws IllegalAccessException {
+		return (T) FieldUtils.getFieldValue(bean, fieldName);
+	}
+}

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-Sec2919.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/login" access="permitAll"/>
+		<intercept-url pattern="/**" access="authenticated"/>
+		<openid-login login-page="/login"/>
+	</http>
+
+	<b:bean
+		name="customLogin"
+		class="org.springframework.security.config.http.OpenIDConfigTests.CustomLoginController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 32 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithFormLogin.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<openid-login/>
+		<form-login/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 32 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithFormLoginAndOpenIDLoginPages.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<openid-login login-page="/openid-page"/>
+		<form-login login-page="/form-page"/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 32 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithFormLoginPage.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<openid-login/>
+		<form-login login-page="/form-page"/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 36 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithOpenIDAttributes.xml

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="denyAll"/>
+		<openid-login>
+			<attribute-exchange>
+				<openid-attribute name="nickname" type="http://schema.openid.net/namePerson/friendly"/>
+				<openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" count="2"/>
+			</attribute-exchange>
+		</openid-login>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 32 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithOpenIDLoginPageAndFormLogin.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<openid-login login-page="/openid-page"/>
+		<form-login/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 33 - 0
config/src/test/resources/org/springframework/security/config/http/OpenIDConfigTests-WithRememberMe.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xmlns="http://www.springframework.org/schema/security"
+		 xsi:schemaLocation="
+				http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
+				http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http use-expressions="true">
+		<intercept-url pattern="/**" access="denyAll"/>
+		<openid-login/>
+		<remember-me/>
+		<csrf disabled="true"/>
+	</http>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>