SEC-1460: Added AxFetchListFactory which matches OpenID identifiers to lists of attributes to use in a fetch-request.

This allows different configurations to be used based on the identity-provider (google, yahoo etc). The default implementation iterates through a map of regex patterns to attribute lists. The namespace has also been extended to support this facility, with the "identifier-match" attribute being added to the attribute-exchange element. Multiple attribute-exchange elements can now be defined, each matching a different identifier.
This commit is contained in:
Luke Taylor 2010-04-20 23:44:58 +01:00
parent 3af75afec1
commit 2f025fba6c
9 changed files with 211 additions and 44 deletions

View File

@ -18,6 +18,7 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.authentication.AnonymousAuthenticationProvider;
@ -52,8 +53,9 @@ final class AuthenticationConfigBuilder {
static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter"; static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter";
static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider"; static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider";
static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer"; private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute"; static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute";
private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"; static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
private static final String ATT_AUTO_CONFIG = "auto-config"; private static final String ATT_AUTO_CONFIG = "auto-config";
@ -192,11 +194,48 @@ final class AuthenticationConfigBuilder {
openIDFilter = parser.getFilterBean(); openIDFilter = parser.getFilterBean();
openIDEntryPoint = parser.getEntryPointBean(); openIDEntryPoint = parser.getEntryPointBean();
Element attrExElt = DomUtils.getChildElementByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE); List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE);
if (attrExElt != null) { if (!attrExElts.isEmpty()) {
// Set up the consumer with the required attribute list // Set up the consumer with the required attribute list
BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS); BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS);
BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS);
ManagedMap<String, ManagedList<BeanDefinition>> axMap = new ManagedMap<String, ManagedList<BeanDefinition>>();
for (Element attrExElt : attrExElts) {
String identifierMatch = attrExElt.getAttribute("identifier-match");
if (!StringUtils.hasText(identifierMatch)) {
if (attrExElts.size() > 1) {
pc.getReaderContext().error("You must supply an identifier-match attribute if using more" +
" than one " + Elements.OPENID_ATTRIBUTE_EXCHANGE + " element", attrExElt);
}
// Match anything
identifierMatch = ".*";
}
axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt));
}
axFactory.addConstructorArgValue(axMap);
consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition());
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
}
}
if (openIDFilter != null) {
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
// Required by login page filter
openIDFilterId = pc.getReaderContext().generateBeanName(openIDFilter);
pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, openIDFilterId));
injectRememberMeServicesRef(openIDFilter, rememberMeServicesId);
createOpenIDProvider();
}
}
private ManagedList<BeanDefinition> parseOpenIDAttributes(Element attrExElt) {
ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> (); ManagedList<BeanDefinition> attributes = new ManagedList<BeanDefinition> ();
for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) { for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
String name = attElt.getAttribute("name"); String name = attElt.getAttribute("name");
@ -215,21 +254,8 @@ final class AuthenticationConfigBuilder {
} }
attributes.add(attrBldr.getBeanDefinition()); attributes.add(attrBldr.getBeanDefinition());
} }
consumerBldr.addConstructorArgValue(attributes);
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
}
}
if (openIDFilter != null) { return attributes;
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", allowSessionCreation);
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
// Required by login page filter
openIDFilterId = pc.getReaderContext().generateBeanName(openIDFilter);
pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, openIDFilterId));
injectRememberMeServicesRef(openIDFilter, rememberMeServicesId);
createOpenIDProvider();
}
} }
private void createOpenIDProvider() { private void createOpenIDProvider() {

View File

@ -371,10 +371,15 @@ form-login.attlist &=
openid-login = openid-login =
## Sets up form login for authentication with an Open ID identity ## Sets up form login for authentication with an Open ID identity
element openid-login {form-login.attlist, user-service-ref?, attribute-exchange?} element openid-login {form-login.attlist, user-service-ref?, attribute-exchange*}
attribute-exchange = attribute-exchange =
element attribute-exchange {openid-attribute+} ## Sets up an attribute exchange configuration to request specified attributes from the OpenID identity provider. When multiple elements are used, each must have an identifier-attribute attribute. Each configuration will be matched in turn against the supplied login identifier until a match is found.
element attribute-exchange {attribute-exchange.attlist, openid-attribute+}
attribute-exchange.attlist &=
## A regular expression which will be compared against the claimed identity, when deciding which attribute-exchange configuration to use during authentication.
attribute identifier-match {xsd:token}?
openid-attribute = openid-attribute =
element openid-attribute {openid-attribute.attlist} element openid-attribute {openid-attribute.attlist}

View File

@ -627,7 +627,7 @@
<xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation> <xs:documentation>Sets up form login for authentication with an Open ID identity</xs:documentation>
</xs:annotation><xs:complexType> </xs:annotation><xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element minOccurs="0" ref="security:attribute-exchange"/> <xs:element minOccurs="0" maxOccurs="unbounded" ref="security:attribute-exchange"/>
</xs:sequence> </xs:sequence>
<xs:attributeGroup ref="security:form-login.attlist"/> <xs:attributeGroup ref="security:form-login.attlist"/>
<xs:attribute name="user-service-ref" type="xs:token"> <xs:attribute name="user-service-ref" type="xs:token">
@ -902,11 +902,21 @@
</xs:attribute> </xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
<xs:element name="attribute-exchange"><xs:complexType> <xs:element name="attribute-exchange"><xs:annotation>
<xs:documentation>Sets up an attribute exchange configuration to request specified attributes from the OpenID identity provider. When multiple elements are used, each must have an identifier-attribute attribute. Each configuration will be matched in turn against the supplied login identifier until a match is found. </xs:documentation>
</xs:annotation><xs:complexType>
<xs:sequence> <xs:sequence>
<xs:element maxOccurs="unbounded" ref="security:openid-attribute"/> <xs:element maxOccurs="unbounded" ref="security:openid-attribute"/>
</xs:sequence> </xs:sequence>
<xs:attributeGroup ref="security:attribute-exchange.attlist"/>
</xs:complexType></xs:element> </xs:complexType></xs:element>
<xs:attributeGroup name="attribute-exchange.attlist">
<xs:attribute name="identifier-match" type="xs:token">
<xs:annotation>
<xs:documentation>A regular expression which will be compared against the claimed identity, when deciding which attribute-exchange configuration to use during authentication.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup>
<xs:element name="openid-attribute"><xs:complexType> <xs:element name="openid-attribute"><xs:complexType>
<xs:attributeGroup ref="security:openid-attribute.attlist"/> <xs:attributeGroup ref="security:openid-attribute.attlist"/>
</xs:complexType></xs:element> </xs:complexType></xs:element>

View File

@ -46,6 +46,7 @@ import org.springframework.security.openid.OpenIDAuthenticationProvider;
import org.springframework.security.openid.OpenIDAuthenticationToken; import org.springframework.security.openid.OpenIDAuthenticationToken;
import org.springframework.security.openid.OpenIDConsumer; import org.springframework.security.openid.OpenIDConsumer;
import org.springframework.security.openid.OpenIDConsumerException; import org.springframework.security.openid.OpenIDConsumerException;
import org.springframework.security.openid.RegexBasedAxFetchListFactory;
import org.springframework.security.util.FieldUtils; import org.springframework.security.util.FieldUtils;
import org.springframework.security.web.FilterChainProxy; import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.FilterInvocation;
@ -1152,7 +1153,6 @@ public class HttpSecurityBeanDefinitionParserTests {
assertEquals("/openid_login", ap.getLoginFormUrl()); assertEquals("/openid_login", ap.getLoginFormUrl());
} }
@SuppressWarnings("unchecked")
@Test @Test
public void openIDWithAttributeExchangeConfigurationIsParsedCorrectly() throws Exception { public void openIDWithAttributeExchangeConfigurationIsParsedCorrectly() throws Exception {
setContext( setContext(
@ -1168,7 +1168,8 @@ public class HttpSecurityBeanDefinitionParserTests {
OpenIDAuthenticationFilter apf = getFilter(OpenIDAuthenticationFilter.class); OpenIDAuthenticationFilter apf = getFilter(OpenIDAuthenticationFilter.class);
OpenID4JavaConsumer consumer = (OpenID4JavaConsumer) FieldUtils.getFieldValue(apf, "consumer"); OpenID4JavaConsumer consumer = (OpenID4JavaConsumer) FieldUtils.getFieldValue(apf, "consumer");
List<OpenIDAttribute> attributes = (List<OpenIDAttribute>) FieldUtils.getFieldValue(consumer, "attributesToFetch"); RegexBasedAxFetchListFactory axFactory = (RegexBasedAxFetchListFactory) FieldUtils.getFieldValue(consumer, "attributesToFetchFactory");
List<OpenIDAttribute> attributes = axFactory.createAttributeList("https://anyopenidprovider.com/");
assertEquals(2, attributes.size()); assertEquals(2, attributes.size());
assertEquals("nickname", attributes.get(0).getName()); assertEquals("nickname", attributes.get(0).getName());
assertEquals("http://schema.openid.net/namePerson/friendly", attributes.get(0).getType()); assertEquals("http://schema.openid.net/namePerson/friendly", attributes.get(0).getType());

View File

@ -0,0 +1,25 @@
package org.springframework.security.openid;
import java.util.List;
/**
* A strategy which can be used by an OpenID consumer implementation, to dynamically determine
* the attribute exchange information based on the OpenID identifier.
* <p>
* This allows the list of attributes for a fetch request to be tailored for different OpenID providers, since they
* do not all support the same attributes.
*
* @author Luke Taylor
* @since 3.1
*/
public interface AxFetchListFactory {
/**
* Builds the list of attributes which should be added to the fetch request for the
* supplied OpenID identifier.
*
* @param identifier the claimed_identity
* @return the attributes to fetch for this identifier
*/
List<OpenIDAttribute> createAttributeList(String identifier);
}

View File

@ -0,0 +1,14 @@
package org.springframework.security.openid;
import java.util.Collections;
import java.util.List;
/**
* @author Luke Taylor
* @since 3.1
*/
public class NullAxFetchListFactory implements AxFetchListFactory {
public List<OpenIDAttribute> createAttributeList(String identifier) {
return Collections.emptyList();
}
}

View File

@ -41,31 +41,50 @@ import org.openid4java.message.ax.FetchResponse;
/** /**
* @author Ray Krueger * @author Ray Krueger
* @author Luke Taylor
*/ */
public class OpenID4JavaConsumer implements OpenIDConsumer { public class OpenID4JavaConsumer implements OpenIDConsumer {
private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName(); private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName();
private static final String ATTRIBUTE_LIST_KEY = "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST";
//~ Instance fields ================================================================================================ //~ Instance fields ================================================================================================
protected final Log logger = LogFactory.getLog(getClass()); protected final Log logger = LogFactory.getLog(getClass());
private final ConsumerManager consumerManager; private final ConsumerManager consumerManager;
private List<OpenIDAttribute> attributesToFetch = Collections.emptyList(); private final AxFetchListFactory attributesToFetchFactory;
//~ Constructors =================================================================================================== //~ Constructors ===================================================================================================
public OpenID4JavaConsumer() throws ConsumerException { public OpenID4JavaConsumer() throws ConsumerException {
this.consumerManager = new ConsumerManager(); this.consumerManager = new ConsumerManager();
this.attributesToFetchFactory = new NullAxFetchListFactory();
} }
/**
* @deprecated use the {@link AxFetchListFactory} version instead.
*/
@Deprecated
public OpenID4JavaConsumer(List<OpenIDAttribute> attributes) throws ConsumerException { public OpenID4JavaConsumer(List<OpenIDAttribute> attributes) throws ConsumerException {
this(new ConsumerManager(), attributes); this(new ConsumerManager(), attributes);
} }
public OpenID4JavaConsumer(ConsumerManager consumerManager, List<OpenIDAttribute> attributes) @Deprecated
public OpenID4JavaConsumer(ConsumerManager consumerManager, final List<OpenIDAttribute> attributes)
throws ConsumerException { throws ConsumerException {
this.consumerManager = consumerManager; this.consumerManager = consumerManager;
this.attributesToFetch = Collections.unmodifiableList(attributes); this.attributesToFetchFactory = new AxFetchListFactory() {
private List<OpenIDAttribute> fetchAttrs = Collections.unmodifiableList(attributes);
public List<OpenIDAttribute> createAttributeList(String identifier) {
return fetchAttrs;
}
};
}
public OpenID4JavaConsumer(AxFetchListFactory attributesToFetchFactory) throws ConsumerException {
this.consumerManager = new ConsumerManager();
this.attributesToFetchFactory = attributesToFetchFactory;
} }
//~ Methods ======================================================================================================== //~ Methods ========================================================================================================
@ -88,9 +107,18 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
try { try {
authReq = consumerManager.authenticate(information, returnToUrl, realm); authReq = consumerManager.authenticate(information, returnToUrl, realm);
logger.debug("Looking up attribute fetch list for identifier: " + identityUrl);
List<OpenIDAttribute> attributesToFetch = attributesToFetchFactory.createAttributeList(identityUrl);
if (!attributesToFetch.isEmpty()) { if (!attributesToFetch.isEmpty()) {
req.getSession().setAttribute(ATTRIBUTE_LIST_KEY, attributesToFetch);
FetchRequest fetchRequest = FetchRequest.createFetchRequest(); FetchRequest fetchRequest = FetchRequest.createFetchRequest();
for (OpenIDAttribute attr : attributesToFetch) { for (OpenIDAttribute attr : attributesToFetch) {
if (logger.isDebugEnabled()) {
logger.debug("Adding attribute " + attr.getType() + " to fetch request");
}
fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount()); fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount());
} }
authReq.addExtension(fetchRequest); authReq.addExtension(fetchRequest);
@ -113,7 +141,10 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
// retrieve the previously stored discovery information // retrieve the previously stored discovery information
DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY); DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY);
List<OpenIDAttribute> attributesToFetch = (List<OpenIDAttribute>) request.getSession().getAttribute(ATTRIBUTE_LIST_KEY);
request.getSession().removeAttribute(DISCOVERY_INFO_KEY); request.getSession().removeAttribute(DISCOVERY_INFO_KEY);
request.getSession().removeAttribute(ATTRIBUTE_LIST_KEY);
// extract the receiving URL from the HTTP request // extract the receiving URL from the HTTP request
StringBuffer receivingURL = request.getRequestURL(); StringBuffer receivingURL = request.getRequestURL();
@ -136,9 +167,20 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
throw new OpenIDConsumerException("Error verifying openid response", e); throw new OpenIDConsumerException("Error verifying openid response", e);
} }
List<OpenIDAttribute> attributes = new ArrayList<OpenIDAttribute>();
// examine the verification result and extract the verified identifier
Identifier verified = verification.getVerifiedId();
if (verified == null) {
Identifier id = discovered.getClaimedIdentifier();
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE,
id == null ? "Unknown" : id.getIdentifier(),
"Verification status message: [" + verification.getStatusMsg() + "]", attributes);
}
// fetch the attributesToFetch of the response // fetch the attributesToFetch of the response
Message authSuccess = verification.getAuthResponse(); Message authSuccess = verification.getAuthResponse();
List<OpenIDAttribute> attributes = new ArrayList<OpenIDAttribute>(this.attributesToFetch.size());
if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
if (debug) { if (debug) {
@ -166,16 +208,6 @@ public class OpenID4JavaConsumer implements OpenIDConsumer {
} }
} }
// examine the verification result and extract the verified identifier
Identifier verified = verification.getVerifiedId();
if (verified == null) {
Identifier id = discovered.getClaimedIdentifier();
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE,
id == null ? "Unknown" : id.getIdentifier(),
"Verification status message: [" + verification.getStatusMsg() + "]", attributes);
}
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(),
"some message", attributes); "some message", attributes);
} }

View File

@ -0,0 +1,42 @@
package org.springframework.security.openid;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
*
* @author Luke Taylor
* @since 3.1
*/
public class RegexBasedAxFetchListFactory implements AxFetchListFactory {
private final Map<Pattern, List<OpenIDAttribute>> idToAttributes;
/**
* @param regexMap map of regular-expressions (matching the identifier) to attributes which should be fetched for
* that pattern.
*/
public RegexBasedAxFetchListFactory(Map<String, List<OpenIDAttribute>> regexMap) {
idToAttributes = new LinkedHashMap<Pattern, List<OpenIDAttribute>>();
for (Map.Entry<String, List<OpenIDAttribute>> entry : regexMap.entrySet()) {
idToAttributes.put(Pattern.compile(entry.getKey()), entry.getValue());
}
}
/**
* Iterates through the patterns stored in the map and returns the list of attributes defined for the
* first match. If no match is found, returns an empty list.
*/
public List<OpenIDAttribute> createAttributeList(String identifier) {
for (Map.Entry<Pattern, List<OpenIDAttribute>> entry : idToAttributes.entrySet()) {
if (entry.getKey().matcher(identifier).matches()) {
return entry.getValue();
}
}
return Collections.emptyList();
}
}

View File

@ -8,7 +8,7 @@
xmlns:b="http://www.springframework.org/schema/beans" xmlns:b="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http> <http>
<intercept-url pattern="/**" access="ROLE_USER"/> <intercept-url pattern="/**" access="ROLE_USER"/>
@ -16,11 +16,14 @@
<logout/> <logout/>
<openid-login login-page="/openidlogin.jsp" user-service-ref="registeringUserService" <openid-login login-page="/openidlogin.jsp" user-service-ref="registeringUserService"
authentication-failure-url="/openidlogin.jsp?login_error=true"> authentication-failure-url="/openidlogin.jsp?login_error=true">
<attribute-exchange> <attribute-exchange identifier-match="https://www.google.com/.*">
<openid-attribute name="email" type="http://axschema.org/contact/email" required="true" count="1"/> <openid-attribute name="email" type="http://axschema.org/contact/email" required="true" count="1"/>
<openid-attribute name="firstname" type="http://axschema.org/namePerson/first" /> <openid-attribute name="firstname" type="http://axschema.org/namePerson/first" required="true" />
<openid-attribute name="lastname" type="http://axschema.org/namePerson/last" /> <openid-attribute name="lastname" type="http://axschema.org/namePerson/last" required="true" />
<openid-attribute name="fullname" type="http://axschema.org/namePerson" /> </attribute-exchange>
<attribute-exchange identifier-match=".*yahoo.com.*">
<openid-attribute name="email" type="http://axschema.org/contact/email" required="true"/>
<openid-attribute name="fullname" type="http://axschema.org/namePerson" required="true" />
</attribute-exchange> </attribute-exchange>
</openid-login> </openid-login>
<remember-me token-repository-ref="tokenRepo"/> <remember-me token-repository-ref="tokenRepo"/>
@ -31,7 +34,16 @@
<authentication-manager alias="authenticationManager"/> <authentication-manager alias="authenticationManager"/>
<!--
A custom UserDetailsService which will allow any user to authenticate and "register" their IDs in an internal map
for use if they return to the site. This is the most common usage pattern for sites which use OpenID.
-->
<b:bean id="registeringUserService" class="org.springframework.security.samples.openid.CustomUserDetailsService" /> <b:bean id="registeringUserService" class="org.springframework.security.samples.openid.CustomUserDetailsService" />
<!--
A namespace-based UserDetailsService which will reject users who are not already defined.
This can be used as an alternative.
-->
<!-- <!--
<user-service id="userService"> <user-service id="userService">
<user name="http://luke.taylor.myopenid.com/" authorities="ROLE_SUPERVISOR,ROLE_USER" /> <user name="http://luke.taylor.myopenid.com/" authorities="ROLE_SUPERVISOR,ROLE_USER" />