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:
parent
3af75afec1
commit
2f025fba6c
|
@ -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() {
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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" />
|
||||||
|
|
Loading…
Reference in New Issue