From 48988bde844b45d11cf6d68c168168ca77b3e44c Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Thu, 13 Aug 2009 23:55:25 +0000 Subject: [PATCH] SEC-935: Support for OpenID attribute exchange and changes to namespace syntax to allow simple configuration of attributes to request. --- .../security/config/Elements.java | 2 + .../HttpSecurityBeanDefinitionParser.java | 29 +++++ ...terceptMethodsBeanDefinitionDecorator.java | 5 +- .../security/config/spring-security-3.0.rnc | 17 ++- .../security/config/spring-security-3.0.xsd | 21 ++++ ...HttpSecurityBeanDefinitionParserTests.java | 36 +++++- ...ptMethodsBeanDefinitionDecoratorTests.java | 3 + .../security/openid/OpenID4JavaConsumer.java | 110 +++++++++++++----- .../security/openid/OpenIDAttribute.java | 93 +++++++++++++++ .../openid/OpenIDAuthenticationProvider.java | 21 +++- .../openid/OpenIDAuthenticationToken.java | 34 ++++-- .../security/openid/OpenIDConsumer.java | 6 - .../security/openid/MockOpenIDConsumer.java | 16 --- .../OpenIDAuthenticationProviderTests.java | 12 +- .../OpenIDAuthenticationTokenTests.java | 38 ------ .../WEB-INF/applicationContext-security.xml | 7 +- 16 files changed, 334 insertions(+), 116 deletions(-) create mode 100644 openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java delete mode 100644 openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationTokenTests.java diff --git a/config/src/main/java/org/springframework/security/config/Elements.java b/config/src/main/java/org/springframework/security/config/Elements.java index aec3391352..950f62438b 100644 --- a/config/src/main/java/org/springframework/security/config/Elements.java +++ b/config/src/main/java/org/springframework/security/config/Elements.java @@ -32,6 +32,8 @@ public abstract class Elements { public static final String LOGOUT = "logout"; public static final String FORM_LOGIN = "form-login"; public static final String OPENID_LOGIN = "openid-login"; + public static final String OPENID_ATTRIBUTE_EXCHANGE = "attribute-exchange"; + public static final String OPENID_ATTRIBUTE = "openid-attribute"; public static final String BASIC_AUTH = "http-basic"; public static final String REMEMBER_ME = "remember-me"; public static final String ANONYMOUS = "anonymous"; diff --git a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java index 105ddbd88c..e6449ec511 100644 --- a/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java +++ b/config/src/main/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParser.java @@ -142,6 +142,8 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProcessingFilter"; 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"; + static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute"; static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter"; static final String EXPRESSION_FIMDS_CLASS = "org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource"; @@ -1004,6 +1006,33 @@ public class HttpSecurityBeanDefinitionParser implements BeanDefinitionParser { parser.parse(openIDLoginElt, pc); openIDFilter = parser.getFilterBean(); openIDEntryPoint = parser.getEntryPointBean(); + + Element attrExElt = DomUtils.getChildElementByTagName(openIDLoginElt, Elements.OPENID_ATTRIBUTE_EXCHANGE); + + if (attrExElt != null) { + // Set up the consumer with the required attribute list + BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS); + ManagedList attributes = new ManagedList (); + for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) { + String name = attElt.getAttribute("name"); + String type = attElt.getAttribute("type"); + String required = attElt.getAttribute("required"); + String count = attElt.getAttribute("count"); + BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS); + attrBldr.addConstructorArgValue(name); + attrBldr.addConstructorArgValue(type); + if (StringUtils.hasLength(required)) { + attrBldr.addPropertyValue("required", Boolean.valueOf(required)); + } + + if (StringUtils.hasLength(count)) { + attrBldr.addPropertyValue("count", Integer.parseInt(count)); + } + attributes.add(attrBldr.getBeanDefinition()); + } + consumerBldr.addConstructorArgValue(attributes); + openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition()); + } } if (openIDFilter != null) { diff --git a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java index 1f90ee935e..5fe39f2172 100644 --- a/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java +++ b/config/src/main/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecorator.java @@ -88,8 +88,9 @@ class InternalInterceptMethodsBeanDefinitionDecorator extends AbstractIntercepto mappings.put(methodName, SecurityConfig.createList(tokens)); } - // TODO: Use a bean for the metadata source - interceptor.addPropertyValue("securityMetadataSource", new MapBasedMethodSecurityMetadataSource(mappings)); + BeanDefinition metadataSource = new RootBeanDefinition(MapBasedMethodSecurityMetadataSource.class); + metadataSource.getConstructorArgumentValues().addGenericArgumentValue(mappings); + interceptor.addPropertyValue("securityMetadataSource", metadataSource); return interceptor.getBeanDefinition(); } diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc index ef94159029..abbc14e401 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc @@ -360,8 +360,23 @@ form-login.attlist &= openid-login = ## Sets up form login for authentication with an Open ID identity - element openid-login {form-login.attlist, user-service-ref?, empty} + element openid-login {form-login.attlist, user-service-ref?, attribute-exchange?} +attribute-exchange = + element attribute-exchange {openid-attribute+} + +openid-attribute = + element openid-attribute {openid-attribute.attlist} + +openid-attribute.attlist &= + attribute name {xsd:token} +openid-attribute.attlist &= + attribute type {xsd:token} +openid-attribute.attlist &= + attribute required {boolean}? +openid-attribute.attlist &= + attribute count {xsd:int}? + filter-chain-map = ## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap diff --git a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd index 568361d691..35bee32393 100644 --- a/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd +++ b/config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd @@ -735,6 +735,9 @@ identity + + + @@ -1104,6 +1107,24 @@ + + + + + + + + + + + + + + + + + + Used to explicitly configure a FilterChainProxy instance with a diff --git a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java index 8ee7e304d3..3ec1b806f1 100644 --- a/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java +++ b/config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java @@ -6,10 +6,10 @@ import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_ import static org.springframework.security.config.http.HttpSecurityBeanDefinitionParser.*; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.ArrayList; import java.util.regex.Pattern; import javax.servlet.Filter; @@ -36,6 +36,8 @@ import org.springframework.security.config.BeanIds; import org.springframework.security.config.PostProcessedMockUserDetailsService; import org.springframework.security.config.util.InMemoryXmlApplicationContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.openid.OpenID4JavaConsumer; +import org.springframework.security.openid.OpenIDAttribute; import org.springframework.security.openid.OpenIDAuthenticationProcessingFilter; import org.springframework.security.openid.OpenIDAuthenticationProvider; import org.springframework.security.util.FieldUtils; @@ -51,12 +53,12 @@ import org.springframework.security.web.access.intercept.FilterInvocationSecurit import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousProcessingFilter; import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.security.web.authentication.RememberMeServices; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter; -import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.RememberMeServices; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter; import org.springframework.security.web.authentication.WebAuthenticationDetails; import org.springframework.security.web.authentication.concurrent.ConcurrentSessionFilter; import org.springframework.security.web.authentication.logout.LogoutFilter; @@ -959,6 +961,32 @@ public class HttpSecurityBeanDefinitionParserTests { "", appContext); } + @SuppressWarnings("unchecked") + @Test + public void openIDWithAttributeExchangeConfigurationIsParsedCorrectly() throws Exception { + setContext( + "" + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + AUTH_PROVIDER_XML); + OpenIDAuthenticationProcessingFilter apf = (OpenIDAuthenticationProcessingFilter) getFilter(OpenIDAuthenticationProcessingFilter.class); + + OpenID4JavaConsumer consumer = (OpenID4JavaConsumer) FieldUtils.getFieldValue(apf, "consumer"); + List attributes = (List) FieldUtils.getFieldValue(consumer, "attributesToFetch"); + assertEquals(2, attributes.size()); + assertEquals("nickname", attributes.get(0).getName()); + assertEquals("http://schema.openid.net/namePerson/friendly", attributes.get(0).getType()); + assertFalse(attributes.get(0).isRequired()); + assertTrue(attributes.get(1).isRequired()); + assertEquals(2, attributes.get(1).getCount()); + } + + private void setContext(String context) { appContext = new InMemoryXmlApplicationContext(context); } diff --git a/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java b/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java index c58f56ea92..fe385d9654 100644 --- a/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java +++ b/config/src/test/java/org/springframework/security/config/method/InterceptMethodsBeanDefinitionDecoratorTests.java @@ -40,7 +40,10 @@ public class InterceptMethodsBeanDefinitionDecoratorTests { @Test public void targetDoesntLoseApplicationListenerInterface() { + assertEquals(1, appContext.getBeansOfType(ApplicationListener.class).size()); + assertEquals(1, appContext.getBeanNamesForType(ApplicationListener.class).length); appContext.publishEvent(new AuthenticationSuccessEvent(new TestingAuthenticationToken("user", ""))); + assertTrue(target instanceof ApplicationListener); } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java b/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java index d6b4bf15de..93ba7e1983 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenID4JavaConsumer.java @@ -14,51 +14,63 @@ */ package org.springframework.security.openid; -import org.openid4java.association.AssociationException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.openid4java.association.AssociationException; import org.openid4java.consumer.ConsumerException; import org.openid4java.consumer.ConsumerManager; import org.openid4java.consumer.VerificationResult; - import org.openid4java.discovery.DiscoveryException; import org.openid4java.discovery.DiscoveryInformation; import org.openid4java.discovery.Identifier; - import org.openid4java.message.AuthRequest; +import org.openid4java.message.Message; import org.openid4java.message.MessageException; +import org.openid4java.message.MessageExtension; import org.openid4java.message.ParameterList; - -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; +import org.openid4java.message.ax.AxMessage; +import org.openid4java.message.ax.FetchRequest; +import org.openid4java.message.ax.FetchResponse; /** - * * @author Ray Krueger + * @version $Id$ */ public class OpenID4JavaConsumer implements OpenIDConsumer { + private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName(); + //~ Instance fields ================================================================================================ + protected final Log logger = LogFactory.getLog(getClass()); + private final ConsumerManager consumerManager; + private List attributesToFetch = Collections.emptyList(); //~ Constructors =================================================================================================== - public OpenID4JavaConsumer(ConsumerManager consumerManager) { - this.consumerManager = consumerManager; - } - public OpenID4JavaConsumer() throws ConsumerException { - this(new ConsumerManager()); + this.consumerManager = new ConsumerManager(); } - //~ Methods ======================================================================================================== + public OpenID4JavaConsumer(List attributes) throws ConsumerException { + this(new ConsumerManager(), attributes); + } - public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { - return beginConsumption(req, identityUrl, returnToUrl, returnToUrl); + public OpenID4JavaConsumer(ConsumerManager consumerManager, List attributes) + throws ConsumerException { + this.consumerManager = consumerManager; + this.attributesToFetch = Collections.unmodifiableList(attributes); } + //~ Methods ======================================================================================================== + @SuppressWarnings("unchecked") public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl, String realm) throws OpenIDConsumerException { @@ -71,31 +83,37 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { } DiscoveryInformation information = consumerManager.associate(discoveries); - HttpSession session = req.getSession(true); - session.setAttribute(DiscoveryInformation.class.getName(), information); + req.getSession().setAttribute(DISCOVERY_INFO_KEY, information); AuthRequest authReq; try { authReq = consumerManager.authenticate(information, returnToUrl, realm); + if (!attributesToFetch.isEmpty()) { + FetchRequest fetchRequest = FetchRequest.createFetchRequest(); + for (OpenIDAttribute attr : attributesToFetch) { + fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount()); + } + authReq.addExtension(fetchRequest); + } } catch (MessageException e) { - throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); + throw new OpenIDConsumerException("Error processing ConsumerManager authentication", e); } catch (ConsumerException e) { - throw new OpenIDConsumerException("Error processing ConumerManager authentication", e); + throw new OpenIDConsumerException("Error processing ConsumerManager authentication", e); } return authReq.getDestinationUrl(true); } - public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) - throws OpenIDConsumerException { + @SuppressWarnings("unchecked") + public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException { + final boolean debug = logger.isDebugEnabled(); // extract the parameters from the authentication response // (which comes in as a HTTP request from the OpenID provider) ParameterList openidResp = new ParameterList(request.getParameterMap()); // retrieve the previously stored discovery information - DiscoveryInformation discovered = (DiscoveryInformation) request.getSession() - .getAttribute(DiscoveryInformation.class.getName()); + DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY); // extract the receiving URL from the HTTP request StringBuffer receivingURL = request.getRequestURL(); @@ -118,16 +136,46 @@ public class OpenID4JavaConsumer implements OpenIDConsumer { throw new OpenIDConsumerException("Error verifying openid response", e); } + // fetch the attributesToFetch of the response + Message authSuccess = verification.getAuthResponse(); + List attributes = new ArrayList(this.attributesToFetch.size()); + + if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) { + if (debug) { + logger.debug("Extracting attributes retrieved by attribute exchange"); + } + try { + MessageExtension ext = authSuccess.getExtension(AxMessage.OPENID_NS_AX); + if (ext instanceof FetchResponse) { + FetchResponse fetchResp = (FetchResponse) ext; + for (OpenIDAttribute attr : attributesToFetch) { + List values = fetchResp.getAttributeValues(attr.getName()); + if (!values.isEmpty()) { + OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), attr.getType(), values); + fetched.setRequired(attr.isRequired()); + attributes.add(fetched); + } + } + } + } catch (MessageException e) { + attributes.clear(); + throw new OpenIDConsumerException("Attribute retrievel failed", e); + } + if (debug) { + logger.debug("Retrieved attributes" + attributes); + } + } + // examine the verification result and extract the verified identifier Identifier verified = verification.getVerifiedId(); - if (verified != null) { - return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), - "some message"); - } else { + if (verified == null) { return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, - discovered.getClaimedIdentifier().getIdentifier(), - "Verification status message: [" + verification.getStatusMsg() + "]"); + discovered.getClaimedIdentifier().getIdentifier(), + "Verification status message: [" + verification.getStatusMsg() + "]", attributes); } + + return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), + "some message", attributes); } } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java new file mode 100644 index 0000000000..1e8343c180 --- /dev/null +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAttribute.java @@ -0,0 +1,93 @@ +package org.springframework.security.openid; + +import java.util.List; + +import org.springframework.util.Assert; + +/** + * Represents an OpenID subject identity attribute. + *

+ * Can be used for configuring the OpenID4JavaConsumer with the attributes which should be requested during a + * fetch request, or to hold values for an attribute which are returned during the authentication process. + * + * @author Luke Taylor + * @version $Id$ + * @since 3.0 + */ +public class OpenIDAttribute { + private final String name; + private final String typeIdentifier; + private boolean required = false; + private int count = 1; + + private final List values; + + public OpenIDAttribute(String name, String type) { + this.name = name; + this.typeIdentifier = type; + this.values = null; + } + + public OpenIDAttribute(String name, String type, List values) { + Assert.notEmpty(values); + this.name = name; + this.typeIdentifier = type; + this.values = values; + } + + /** + * The attribute name + */ + public String getName() { + return name; + } + + /** + * The attribute type Identifier (a URI). + */ + public String getType() { + return typeIdentifier; + } + + /** + * The "required" flag for the attribute when used with an authentication request. Defaults to "false". + */ + public boolean isRequired() { + return required; + } + + public void setRequired(boolean required) { + this.required = required; + } + + /** + * The requested count for the attribute when it is used as part of an authentication + * request. Defaults to 1. + */ + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + /** + * The values obtained from an attribute exchange. + */ + public List getValues() { + Assert.notNull(values, "Cannot read values from an authentication request attribute"); + return values; + } + + public String toString() { + StringBuilder result = new StringBuilder("["); + result.append(name); + if (values != null) { + result.append(":"); + result.append(values.toString()); + } + result.append("]"); + return result.toString(); + } +} diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java index d7720bf436..440327e7f7 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationProvider.java @@ -63,14 +63,12 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini OpenIDAuthenticationToken response = (OpenIDAuthenticationToken) authentication; OpenIDAuthenticationStatus status = response.getStatus(); - // handle the various possibilites + // handle the various possibilities if (status == OpenIDAuthenticationStatus.SUCCESS) { - // Lookup user details UserDetails userDetails = userDetailsService.loadUserByUsername(response.getIdentityUrl()); - return new OpenIDAuthenticationToken(userDetails.getAuthorities(), response.getStatus(), - response.getIdentityUrl()); + return createSuccessfulAuthentication(userDetails, response); } else if (status == OpenIDAuthenticationStatus.CANCELLED) { throw new AuthenticationCancelledException("Log in cancelled"); @@ -89,6 +87,21 @@ public class OpenIDAuthenticationProvider implements AuthenticationProvider, Ini return null; } + /** + * Handles the creation of the final Authentication object which will be returned by the provider. + *

+ * The default implementation just creates a new OpenIDAuthenticationToken from the original, but with the + * UserDetails as the principal and including the authorities loaded by the UserDetailsService. + * + * @param userDetails the loaded UserDetails object + * @param auth the token passed to the authenticate method, containing + * @return the token which will represent the authenticated user. + */ + protected Authentication createSuccessfulAuthentication(UserDetails userDetails, OpenIDAuthenticationToken auth) { + return new OpenIDAuthenticationToken(userDetails, userDetails.getAuthorities(), + auth.getIdentityUrl(), auth.getAttributes()); + } + /** * Used to load the authorities for the authenticated OpenID user. */ diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java index b2e18986b1..9a2368e591 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDAuthenticationToken.java @@ -30,29 +30,39 @@ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { //~ Instance fields ================================================================================================ private final OpenIDAuthenticationStatus status; + private final Object principal; private final String identityUrl; private final String message; + private final List attributes; //~ Constructors =================================================================================================== - public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message) { + public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, + String message, List attributes) { super(new ArrayList(0)); + this.principal = identityUrl; this.status = status; this.identityUrl = identityUrl; this.message = message; + this.attributes = attributes; setAuthenticated(false); } /** - * Created by the OpenIDAuthenticationProvider on successful authentication. - * Do not use directly + * Created by the OpenIDAuthenticationProvider on successful authentication. + * + * @param principal usually the UserDetails returned by the the configured UserDetailsService + * used by the OpenIDAuthenticationProvider. * */ - public OpenIDAuthenticationToken(List authorities, OpenIDAuthenticationStatus status, String identityUrl) { + public OpenIDAuthenticationToken(Object principal, List authorities, + String identityUrl, List attributes) { super(authorities); - this.status = status; + this.principal = principal; + this.status = OpenIDAuthenticationStatus.SUCCESS; this.identityUrl = identityUrl; this.message = null; + this.attributes = attributes; setAuthenticated(true); } @@ -76,14 +86,24 @@ public class OpenIDAuthenticationToken extends AbstractAuthenticationToken { } /** - * Returns the identityUrl value. + * Returns the principal value. + * * @see org.springframework.security.core.Authentication#getPrincipal() */ public Object getPrincipal() { - return identityUrl; + return principal; } public OpenIDAuthenticationStatus getStatus() { return status; } + + public List getAttributes() { + return attributes; + } + + @Override + public String toString() { + return "[" + super.toString() + ", attributes : " + attributes +"]"; + } } diff --git a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java index 6bfb8e4823..ef5262d2de 100644 --- a/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java +++ b/openid/src/main/java/org/springframework/security/openid/OpenIDConsumer.java @@ -26,12 +26,6 @@ import javax.servlet.http.HttpServletRequest; */ public interface OpenIDConsumer { - /** - * @deprecated Use {@link #beginConsumption(javax.servlet.http.HttpServletRequest, String, String, String)} - */ - public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) - throws OpenIDConsumerException; - /** * Given the request, the claimedIdentity, the return to url, and a realm, lookup the openId authentication * page the user should be redirected to. diff --git a/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java b/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java index aa724c4ac8..b41ab064f1 100644 --- a/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java +++ b/openid/src/test/java/org/springframework/security/openid/MockOpenIDConsumer.java @@ -22,8 +22,6 @@ import javax.servlet.http.HttpServletRequest; /** - * DOCUMENT ME! - * * @author Robin Bramley, Opsera Ltd */ public class MockOpenIDConsumer implements OpenIDConsumer { @@ -54,17 +52,6 @@ public class MockOpenIDConsumer implements OpenIDConsumer { return redirectUrl; } - /* (non-Javadoc) - * @see org.springframework.security.ui.openid.OpenIDConsumer#beginConsumption(javax.servlet.http.HttpServletRequest, java.lang.String) - */ - public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) - throws OpenIDConsumerException { - throw new UnsupportedOperationException("This method is deprecated, stop using it"); - } - - /* (non-Javadoc) - * @see org.springframework.security.ui.openid.OpenIDConsumer#endConsumption(javax.servlet.http.HttpServletRequest) - */ public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException { return token; @@ -79,9 +66,6 @@ public class MockOpenIDConsumer implements OpenIDConsumer { this.redirectUrl = redirectUrl; } - /* (non-Javadoc) - * @see org.springframework.security.ui.openid.OpenIDConsumer#setReturnToUrl(java.lang.String) - */ public void setReturnToUrl(String returnToUrl) { // TODO Auto-generated method stub } diff --git a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java index ef4100f968..29c69f338a 100644 --- a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java +++ b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationProviderTests.java @@ -46,7 +46,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, ""); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, "" ,null); assertFalse(preAuth.isAuthenticated()); @@ -65,7 +65,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, ""); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, "", null); assertFalse(preAuth.isAuthenticated()); @@ -84,7 +84,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, ""); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, "", null); assertFalse(preAuth.isAuthenticated()); @@ -103,7 +103,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, ""); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, "", null); assertFalse(preAuth.isAuthenticated()); @@ -122,7 +122,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider(); provider.setUserDetailsService(new MockUserDetailsService()); - Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, ""); + Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, "", null); assertFalse(preAuth.isAuthenticated()); @@ -132,7 +132,7 @@ public class OpenIDAuthenticationProviderTests extends TestCase { assertTrue(postAuth instanceof OpenIDAuthenticationToken); assertTrue(postAuth.isAuthenticated()); assertNotNull(postAuth.getPrincipal()); - assertEquals(preAuth.getPrincipal(), postAuth.getPrincipal()); + assertTrue(postAuth.getPrincipal() instanceof UserDetails); assertNotNull(postAuth.getAuthorities()); assertTrue(postAuth.getAuthorities().size() > 0); assertTrue(((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS); diff --git a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationTokenTests.java b/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationTokenTests.java deleted file mode 100644 index ca2a27dab8..0000000000 --- a/openid/src/test/java/org/springframework/security/openid/OpenIDAuthenticationTokenTests.java +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited - * - * 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.openid; - -import org.springframework.security.openid.OpenIDAuthenticationStatus; -import org.springframework.security.openid.OpenIDAuthenticationToken; - -import junit.framework.TestCase; - -/** - * @author Ray Krueger - */ -public class OpenIDAuthenticationTokenTests extends TestCase { - - public void test() throws Exception { - OpenIDAuthenticationToken token = newToken(); - assertEquals(token, newToken()); - } - - private OpenIDAuthenticationToken newToken() { - return new OpenIDAuthenticationToken( - OpenIDAuthenticationStatus.SUCCESS, - "http://raykrueger.blogspot.com/", - "what is this for anyway?"); - } -} diff --git a/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml b/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml index 4851f04567..b3924120fc 100644 --- a/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml +++ b/samples/openid/src/main/webapp/WEB-INF/applicationContext-security.xml @@ -16,7 +16,12 @@ - + + + + + +