Announcement Announcement Module
Collapse
No announcement yet.
OAUTH Realm header issue with OAuth 1.0.0.RC1 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OAUTH Realm header issue with OAuth 1.0.0.RC1

    I'm still very new to STS and OAUTH both, but I'm running into a problem here that I can't find documentation on. I'm pretty sure it's a configuration issue, but I haven't found a good example yet.

    I've setup the OAUTH 1.0a SPARKLR/TONR example from [OAuth 1.0.0.RC1] on APACHE 6.0 with a 2 Legged Fetch example as suggested by this blog:

    http://bmocanu.ro/coding/409/client-...ring-security/

    I've got the example working with standard form post variables. My problem lies within making a post where the OAUTH variables are contained within the HTTP header (our 3rd party client is sending them that way). The same post works fine on POJO Google OAUTH code.

    Code:
    OAuth realm="http://localhost:8080/sparklr/photos?format=json",oauth_consumer_key="tonr-consumer-key",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1344436362",oauth_nonce="3838847075661",oauth_version="1.0",oauth_signature="s1LT1WHMLjfEF4oaVc59Sam591Q%3D"
    The problem I'm running into is that as the post goes through the Spring filters I get the following message:
    Response realm name {0} does not match system realm name of {1}

    Code:
    [DEBUG] FilterChainProxy - /photos?format=json at position 13 of 14 in additional filter chain; firing Filter: 'ProtectedResourceProcessingFilter'
    [DEBUG] ProtectedResourceProcessingFilter - OAuth parameters parsed: oauth_signature=Xs/zXES7LH5Ms2OV/fKl6Sf5mNI= realm=http://localhost:8080/sparklr/photos?format=json oauth_nonce=1907532289857 oauth_version=1.0 oauth_consumer_key=tonr-consumer-key oauth_signature_method=HMAC-SHA1 oauth_timestamp=1344434430 
    [DEBUG] ProtectedResourceProcessingFilter - Consumer details loaded for tonr-consumer-key: [email protected]24c2849
    [DEBUG] ProtectedResourceProcessingFilter - org.springframework.security.oauth.provider.InvalidOAuthParametersException: Response realm name {0} does not match system realm name of {1}
    [DEBUG] HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
    [DEBUG] ExceptionTranslationFilter - Chain processed normally

    The OAUTH headers are all parsed correctly, but the [realmName] for the [ProtectedResourceProcessingFilter] is NULL.

    If I then add the following to the SPRING-SERVLET.XML
    Code:
    ...
    	<bean id="ProtectedResourceProcessingFilter"
    		class="org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter">
    		
    		<property name="authenticationEntryPoint" ref="OAuthProcessingFilterEntryPoint"/>
    		<property name="allowAllMethods" value="true"/>
    		
    	</bean>
     
    	<bean id="OAuthProcessingFilterEntryPoint"
    		class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint">
    		<property name="realmName" value="sparklr" />
    	</bean>
    ...
    The [realmName] is no longer NULL, but I get the following error:

    Code:
    [ERROR] DispatcherServlet - Context initialization failed <org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ProtectedResourceProcessingFilter' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A consumer details service is required.>org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ProtectedResourceProcessingFilter' defined in ServletContext resource [/WEB-INF/spring-servlet.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: A consumer details service is required.
    Any help is appreciated, and please let me know if you need additional information.

    FULL applicationContext.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans:beans xmlns="http://www.springframework.org/schema/security"
      xmlns:beans="http://www.springframework.org/schema/beans"
      xmlns:oauth="http://www.springframework.org/schema/security/oauth"
      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
                  http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
                  http://www.springframework.org/schema/security/oauth http://www.springframework.org/schema/security/spring-security-oauth-1.0.xsd">
    
      <http auto-config='true' access-denied-page="/login.jsp" realm="sparklr">
        <intercept-url pattern="/xml/photos" access="ROLE_USER" />
        <intercept-url pattern="/json/photos" access="ROLE_USER" />
        <intercept-url pattern="/photo/**" access="ROLE_USER" />
        <intercept-url pattern="/oauth/**" access="ROLE_USER" />
        <intercept-url pattern="/request_token_authorized.jsp" access="ROLE_USER" />
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    
        <form-login authentication-failure-url="/login.jsp" default-target-url="/index.jsp" login-page="/login.jsp" login-processing-url="/login.do"/>
        <logout logout-success-url="/index.jsp" logout-url="/logout.do"/>
      </http>
    
      <authentication-manager>
        <authentication-provider>
          <user-service id="userDetailsService">
            <user name="marissa" password="koala" authorities="ROLE_USER" />
            <user name="paul" password="emu" authorities="ROLE_USER" />
          </user-service>
        </authentication-provider>
      </authentication-manager>
    
      <oauth:provider consumer-details-service-ref="consumerDetails"
                      token-services-ref="tokenServices"
                      request-token-url="/oauth/request_token"
                      authenticate-token-url="/oauth/authorize"
                      user-approval-url="/oauth/confirm_access"
                      access-granted-url="/request_token_authorized.jsp"
                      access-token-url="/oauth/access_token"
                      require10a="false"
                      />
    
      <oauth:consumer-details-service id="consumerDetails">
        <oauth:consumer name="Tonr.com" 
        				key="tonr-consumer-key" 
        				secret="SHHHHH!!!!!!!!!!" 
        				resourceName="Your Photos" 
        				resourceDescription="Your photos that you have uploaded to sparklr.com."
        				requiredToObtainAuthenticatedToken="false"
        				authorities="ROLE_CONSUMER"
        />
        <oauth:consumer name="iGoogle" key="www.google.com" secret="classpath:/org/springframework/security/oauth/examples/sparklr/certs/igoogle.cert" typeOfSecret="rsa-cert" resourceName="Your Photos" resourceDescription="Your photos that you have uploaded to sparklr.com."/>
      </oauth:consumer-details-service>
    
      <oauth:token-services id="tokenServices"/>
    
    </beans:beans>

  • #2
    The BeanCreationException has all the detail you need I think - you haven't provided a consumerDetailsService to the ProtectedResourceProcessingFilter. Am I missing something?

    Comment


    • #3
      Ok, I guess that makes sense, but what would be the proper way to set that up? And why do I not have to provide a consumerDetailsService when it is a simple form post? like I said, I'm still a little new to this.

      Comment


      • #4
        Ok, I did figure out how to add the consumerDetailService, but now it's throwing the error
        Response realm name {0} does not match system realm name of {1}

        realmName is showing as NULL for the ProtectedResourceProcessingFilter.

        Code:
        [DEBUG] ProtectedResourceProcessingFilter - OAuth parameters parsed: oauth_signature=eAspYV55P4F/EZtTer3jhyT3qYo= realm=/sparklr oauth_nonce=101785948706955 oauth_version=1.0 oauth_consumer_key=tonr-consumer-key oauth_signature_method=HMAC-SHA1 oauth_timestamp=1344971480 
        [DEBUG] ProtectedResourceProcessingFilter - Consumer details loaded for tonr-consumer-key: [email protected]14a8f44
        [DEBUG] ProtectedResourceProcessingFilter - org.springframework.security.oauth.provider.InvalidOAuthParametersException: Response realm name {0} does not match system realm name of {1}
        What needs to be changed or added?

        SPRING-SERVLET.XML snippet
        Code:
        ....
        	<bean id="ProtectedResourceProcessingFilter"
        		class="org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter">
        		<property name="authenticationEntryPoint" ref="OAuthProcessingFilterEntryPoint"/>
        		<property name="tokenServices" ref="tokenServices" />
        		<property name="consumerDetailsService" ref="consumerDetails" />
        		<property name="allowAllMethods" value="true"/>
        		
        	</bean>
        	<bean id="OAuthProcessingFilterEntryPoint"
        		class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint">
        		<property name="realmName" value="sparklr" />
        	</bean>
        ....

        Comment


        • #5
          I'd have to check, but I think the bean names are significant in the OAuth filter chain, and yours are unconventional in that they start with an upper case letter. Maybe you are setting up 2 filters and only the one with null realm is on the chain at runtime? I think they also need to be "oauth*". You can check by looking at the source code for the bean definition parsers, and if you get it working we can soup up the documentation to make it clearer.

          Comment


          • #6
            Changed to lowercase,
            Code:
            	<bean id="ProtectedResourceProcessingFilter" class="org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter">
            		<property name="authenticationEntryPoint" ref="oAuthProcessingFilterEntryPoint"/>
            		<property name="allowAllMethods" value="true"/>
            		<property name="tokenServices" ref="tokenServices" />
            		<property name="consumerDetailsService" ref="consumerDetailsService" />
            	</bean>
            
            	<bean id="oAuthProviderProcessingFilter" class="org.springframework.security.oauth.provider.filter.oAuthProcessingFilter">
            		<property name="authenticationEntryPoint" ref="oAuthProcessingFilterEntryPoint"/>
            	</bean> 
            	<bean id="oAuthProcessingFilterEntryPoint" class="org.springframework.security.oauth.provider.oAuthProcessingFilterEntryPoint">
            		<property name="realmName" value="twolegged" />
            		 
            	</bean>
            but yields

            Cannot find class [org.springframework.security.oauth.provider.filter .oAuthProcessingFilter]

            Cannot find class [org.springframework.security.oauth.provider.oAuthP rocessingFilterEntryPoint]


            which make sense since each bean starts with a capital "O".

            If I hit the OAuthProcessingFilterEntryPoint directly, the realmName does get populated properly, so there is something in the bean configuration for ProtectedResourceProcessingFilter that I'm not setting up properly.

            I guess the question is: since ProtectedResourceProcessingFilter extends the abstract bean OAuthProcessingFilter which has the dependency on the OAuthProcessingFilterEntryPoint which contains the variable realmName, what is the proper syntax in the SERVLET.XML to set the value for realmName in relation to the ProtectedResourceProcessingFilter?

            Thanks for sticking with me on this! I've had to reverse engineer a lot of projects in my time, this one has been very challenging! I'll keep digging.

            Comment


            • #7
              I think you might need to mug up on your basic Spring config skills. The class names are not lower cased, but the bean names usually are be convention (and I have a feeling it is mandatory in this case). If you read my last comment carfully you will see it is not just the first letter in this case either.
              Last edited by Dave Syer; Aug 16th, 2012, 06:01 AM.

              Comment


              • #8
                Try this (and make sure it comes *after* the <oauth:provider/> configuration), or something like it:

                Code:
                <bean id="oauthProtectedResourceFilter" class="org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter">
                		<property name="authenticationEntryPoint" ref="entryPoint"/>
                		<property name="allowAllMethods" value="true"/>
                		<property name="tokenServices" ref="tokenServices" />
                		<property name="consumerDetailsService" ref="consumerDetailsService" />
                	</bean>
                	<bean id="entryPoint" class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint">
                		<property name="realmName" value="twolegged" />
                	</bean>
                I don't know where you got the other filter bean from in your second example. What was it supposed to do?
                Last edited by Dave Syer; Aug 16th, 2012, 06:07 AM. Reason: spelling

                Comment


                • #9
                  I placed your sample (properly after the oauthrovider) in the servlet.xml and got the same results. I had another programmer look at it with me, and we determined that this entry is just creating a different instance of ProtectedResourceProcessingFilter . So yes, I believe you are correct when saying we are running 2 separate instances.

                  For instance:
                  Code:
                  org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter@5492de02
                  
                  org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter@5ecfe500
                  The inbound posts are hitting the ProtectedResourceProcessingFilter that is initialized by the DefaultSecurityFilterChain and not the one initialized in the servlet.xml.

                  I also I agree that it has to be the camel-case-first-letter-lower-case bean name. But, I've tried different variations on the bean names with no luck. I've setup a trap on the DefaultBeanDefinitionDocumentReader to try to figure out what it is, but I think there may be some other connection here that I'm missing.

                  thoughts?

                  Comment


                  • #10
                    The bean ids are registered by OAuthProviderBeanDefinitionParser. You can look at what it is registering and override the pieces that you need to, and you shouldn't get duplicate beans if they both have the same id, as long as they are in the same application context (are they?). In fact you should see a log message telling you that the bean has been overridden.

                    Comment


                    • #11
                      Ok that was the hint I needed....
                      Code:
                      public class OAuthProviderBeanDefinitionParser implements BeanDefinitionParser {
                      ....
                          List<BeanMetadataElement> filterChain = ConfigUtils.findFilterChain(parserContext, element.getAttribute("filter-chain-ref"));
                          int index = insertIndex(filterChain);
                          parserContext.getRegistry().registerBeanDefinition("oauthRequestTokenFilter", requestTokenFilterBean.getBeanDefinition());
                          filterChain.add(index++, new RuntimeBeanReference("oauthRequestTokenFilter"));
                          parserContext.getRegistry().registerBeanDefinition("oauthAuthenticateTokenFilter", authenticateTokenFilterBean.getBeanDefinition());
                          filterChain.add(index++, new RuntimeBeanReference("oauthAuthenticateTokenFilter"));
                          parserContext.getRegistry().registerBeanDefinition("oauthAccessTokenFilter", accessTokenFilterBean.getBeanDefinition());
                          filterChain.add(index++, new RuntimeBeanReference("oauthAccessTokenFilter"));
                          parserContext.getRegistry().registerBeanDefinition("oauthProtectedResourceFilter", protectedResourceFilterBean.getBeanDefinition());
                          filterChain.add(index++, new RuntimeBeanReference("oauthProtectedResourceFilter"));
                      ...
                      Why are these hardcoded?

                      Modified the applicationContext.xml to

                      Code:
                       <bean  id="oauthProtectedResourceFilter" class="org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter">
                      		<beans:property name="authenticationEntryPoint" ref="oauthAuthenticationEntryPoint"/>
                      		<beans:property name="allowAllMethods" value="true"/>
                      		<beans:property name="tokenServices" ref="tokenServices" />
                      		<beans:property name="consumerDetailsService" ref="consumerDetails" />
                      	</bean >
                        	
                      <bean  id="oauthAuthenticationEntryPoint"  class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint">
                      		<beans:property name="realmName" value="oauth" />
                      	</bean>
                      Which is basically the same as what you posted. I think the difference was that I moved the bean to the application context, instead of the servlet context. But I could be wrong.


                      Upon debugging the server we get the following as you mentioned:
                      Code:
                      [INFO] HttpSecurityBeanDefinitionParser - Checking sorted filter chain: [Root bean: class [org.springframework.security.web.context.SecurityContextPersistenceFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 300, Root bean: class [org.springframework.security.web.authentication.logout.LogoutFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 400, <org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0>, order = 800, Root bean: class [org.springframework.security.web.authentication.www.BasicAuthenticationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1200, Root bean: class [org.springframework.security.web.savedrequest.RequestCacheAwareFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1300, Root bean: class [org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1400, Root bean: class [org.springframework.security.web.authentication.AnonymousAuthenticationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1700, Root bean: class [org.springframework.security.web.session.SessionManagementFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1800, Root bean: class [org.springframework.security.web.access.ExceptionTranslationFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1900, <org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0>, order = 2000]
                      [INFO] DefaultListableBeanFactory - Overriding bean definition for bean 'oauthProtectedResourceFilter': replacing [Root bean: class [org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.springframework.security.oauth.provider.filter.ProtectedResourceProcessingFilter]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in ServletContext resource [/WEB-INF/applicationContext.xml]]
                      The realmName is no longer null for that bean.

                      Is there documentation on this any place that I have missed? I may have read it, or maybe I've read too much!

                      Appreciate your help!

                      Comment


                      • #12
                        I think the documentation on this feature (the overridable beans) is missing in Spring Security OAuth. If you raise a JIRA with some specific details and a link to this thread it will help get that fixed. Send a pull request for the wiki if you want to fix it yourself. It is taking advantage of a standard Spring feature which should be documented, but is hardly ever used in practice, so might not be easy to find.

                        The bean names have to be hard coded, otherwise you wouldn't know how to override them. Framework beans generally are either hardcoded (but usually with more unique names) or auto-generated. I'm not sure I like the way that OAuth parsers are implemented in this way, but there doesn't seem to be a lot of demand to change it. Again, feel free if you have ideas to make a contribution.

                        Comment

                        Working...
                        X