mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-31 06:38:42 +00:00 
			
		
		
		
	SEC-935: Support for OpenID attribute exchange and changes to namespace syntax to allow simple configuration of attributes to request.
This commit is contained in:
		
							parent
							
								
									5e4743d8f2
								
							
						
					
					
						commit
						48988bde84
					
				| @ -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"; | ||||
|  | ||||
| @ -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<BeanDefinition> attributes = new ManagedList<BeanDefinition> (); | ||||
|                 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) { | ||||
|  | ||||
| @ -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(); | ||||
|     } | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -735,6 +735,9 @@ | ||||
|                      identity</xs:documentation> | ||||
|                </xs:annotation> | ||||
|                <xs:complexType> | ||||
|                   <xs:sequence> | ||||
|                      <xs:element minOccurs="0" ref="security:attribute-exchange"/> | ||||
|                   </xs:sequence> | ||||
|                   <xs:attributeGroup ref="security:form-login.attlist"/> | ||||
|                   <xs:attribute name="user-service-ref" type="xs:token"> | ||||
|                      <xs:annotation> | ||||
| @ -1104,6 +1107,24 @@ | ||||
|          </xs:annotation> | ||||
|       </xs:attribute> | ||||
|    </xs:attributeGroup> | ||||
|    <xs:element name="attribute-exchange"> | ||||
|       <xs:complexType> | ||||
|          <xs:sequence> | ||||
|             <xs:element maxOccurs="unbounded" ref="security:openid-attribute"/> | ||||
|          </xs:sequence> | ||||
|       </xs:complexType> | ||||
|    </xs:element> | ||||
|    <xs:element name="openid-attribute"> | ||||
|       <xs:complexType> | ||||
|          <xs:attributeGroup ref="security:openid-attribute.attlist"/> | ||||
|       </xs:complexType> | ||||
|    </xs:element> | ||||
|    <xs:attributeGroup name="openid-attribute.attlist"> | ||||
|       <xs:attribute name="name" use="required" type="xs:token"/> | ||||
|       <xs:attribute name="type" use="required" type="xs:token"/> | ||||
|       <xs:attribute name="required" type="xs:token"/> | ||||
|       <xs:attribute name="count" type="xs:int"/> | ||||
|    </xs:attributeGroup> | ||||
|    <xs:element name="filter-chain-map"> | ||||
|       <xs:annotation> | ||||
|          <xs:documentation>Used to explicitly configure a FilterChainProxy instance with a | ||||
|  | ||||
| @ -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 { | ||||
|                 "</http>", appContext); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressWarnings("unchecked") | ||||
|     @Test | ||||
|     public void openIDWithAttributeExchangeConfigurationIsParsedCorrectly() throws Exception { | ||||
|         setContext( | ||||
|                 "<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'/>" + | ||||
|                 "      </attribute-exchange>" + | ||||
|                 "   </openid-login>" + | ||||
|                 "</http>" + | ||||
|                 AUTH_PROVIDER_XML); | ||||
|         OpenIDAuthenticationProcessingFilter apf = (OpenIDAuthenticationProcessingFilter) getFilter(OpenIDAuthenticationProcessingFilter.class); | ||||
| 
 | ||||
|         OpenID4JavaConsumer consumer = (OpenID4JavaConsumer) FieldUtils.getFieldValue(apf, "consumer"); | ||||
|         List<OpenIDAttribute> attributes = (List<OpenIDAttribute>) 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); | ||||
|     } | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -14,51 +14,63 @@ | ||||
|  */ | ||||
| package org.springframework.security.openid; | ||||
| 
 | ||||
| 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.MessageException; | ||||
| import org.openid4java.message.ParameterList; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpSession; | ||||
| 
 | ||||
| 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 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<OpenIDAttribute> attributesToFetch = Collections.emptyList(); | ||||
| 
 | ||||
|     //~ Constructors =================================================================================================== | ||||
| 
 | ||||
|     public OpenID4JavaConsumer(ConsumerManager consumerManager) { | ||||
|         this.consumerManager = consumerManager; | ||||
|     public OpenID4JavaConsumer() throws ConsumerException { | ||||
|         this.consumerManager = new ConsumerManager(); | ||||
|     } | ||||
| 
 | ||||
|     public OpenID4JavaConsumer() throws ConsumerException { | ||||
|         this(new ConsumerManager()); | ||||
|     public OpenID4JavaConsumer(List<OpenIDAttribute> attributes) throws ConsumerException { | ||||
|         this(new ConsumerManager(), attributes); | ||||
|     } | ||||
| 
 | ||||
|     public OpenID4JavaConsumer(ConsumerManager consumerManager, List<OpenIDAttribute> attributes) | ||||
|             throws ConsumerException { | ||||
|         this.consumerManager = consumerManager; | ||||
|         this.attributesToFetch = Collections.unmodifiableList(attributes); | ||||
|     } | ||||
| 
 | ||||
|     //~ Methods ======================================================================================================== | ||||
| 
 | ||||
|     public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl) throws OpenIDConsumerException { | ||||
|         return beginConsumption(req, identityUrl,  returnToUrl, returnToUrl); | ||||
|     } | ||||
| 
 | ||||
|     @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<OpenIDAttribute> attributes = new ArrayList<OpenIDAttribute>(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<String> 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); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -0,0 +1,93 @@ | ||||
| package org.springframework.security.openid; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.springframework.util.Assert; | ||||
| 
 | ||||
| /** | ||||
|  * Represents an OpenID subject identity attribute. | ||||
|  * <p> | ||||
|  * Can be used for configuring the <tt>OpenID4JavaConsumer</tt> 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<String> values; | ||||
| 
 | ||||
|     public OpenIDAttribute(String name, String type) { | ||||
|         this.name = name; | ||||
|         this.typeIdentifier = type; | ||||
|         this.values = null; | ||||
|     } | ||||
| 
 | ||||
|     public OpenIDAttribute(String name, String type, List<String> 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<String> 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(); | ||||
|     } | ||||
| } | ||||
| @ -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 <tt>Authentication</tt> object which will be returned by the provider. | ||||
|      * <p> | ||||
|      * 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. | ||||
|      */ | ||||
|  | ||||
| @ -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<OpenIDAttribute> attributes; | ||||
| 
 | ||||
|     //~ Constructors =================================================================================================== | ||||
| 
 | ||||
|     public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message) { | ||||
|     public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, | ||||
|             String message, List<OpenIDAttribute> attributes) { | ||||
|         super(new ArrayList<GrantedAuthority>(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. | ||||
|      * <b>Do not use directly</b> | ||||
|      * Created by the <tt>OpenIDAuthenticationProvider</tt> on successful authentication. | ||||
|      * | ||||
|      * @param principal usually the <tt>UserDetails</tt> returned by the the configured <tt>UserDetailsService</tt> | ||||
|      * used by the <tt>OpenIDAuthenticationProvider</tt>. | ||||
|      * | ||||
|      */ | ||||
|     public OpenIDAuthenticationToken(List<GrantedAuthority> authorities, OpenIDAuthenticationStatus status, String identityUrl) { | ||||
|     public OpenIDAuthenticationToken(Object principal, List<GrantedAuthority> authorities, | ||||
|             String identityUrl, List<OpenIDAttribute> 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 <tt>identityUrl</tt> value. | ||||
|      * Returns the <tt>principal</tt> value. | ||||
|      * | ||||
|      * @see org.springframework.security.core.Authentication#getPrincipal() | ||||
|      */ | ||||
|     public Object getPrincipal() { | ||||
|         return identityUrl; | ||||
|         return principal; | ||||
|     } | ||||
| 
 | ||||
|     public OpenIDAuthenticationStatus getStatus() { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|     public List<OpenIDAttribute> getAttributes() { | ||||
|         return attributes; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "[" + super.toString() + ", attributes : " + attributes +"]"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -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 | ||||
|     } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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?"); | ||||
|     } | ||||
| } | ||||
| @ -16,7 +16,12 @@ | ||||
|         <intercept-url pattern="/**" access="ROLE_USER"/> | ||||
|         <intercept-url pattern="/openidlogin.jsp*" filters="none"/> | ||||
|         <logout/> | ||||
|         <openid-login login-page="/openidlogin.jsp" authentication-failure-url="/openidlogin.jsp?login_error=true" /> | ||||
|         <openid-login login-page="/openidlogin.jsp" authentication-failure-url="/openidlogin.jsp?login_error=true"> | ||||
|             <attribute-exchange> | ||||
|                 <openid-attribute name="email" type="http://schema.openid.net/contact/email" required="true" count="2"/> | ||||
|                 <openid-attribute name="name" type="http://schema.openid.net/namePerson/friendly" /> | ||||
|             </attribute-exchange> | ||||
|         </openid-login> | ||||
|     </http> | ||||
| 
 | ||||
|     <authentication-manager alias="authenticationManager"/> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user