0
votes

I've setup a consumer app, and most of the oauth workflow looks correct, but for some reason after the callback url is invoked by the provider, it tries to get an access token TWICE. The first time works

http://localhost:8080/app/ws/oauth/token [OAuth oauth_consumer_key="itd79n64zlwv5hhv", oauth_nonce="cac26978-c36c-4a8b-8f3e-3e779ff927ab", oauth_signature="5c8BM9qQoijXC2f5IXpQGtSQsys%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1458938403", oauth_token="5451cf20-7eed-4797-819c-ee2316981654", oauth_verifier="c56de555-79df-455e-ab87-f5f11b953fef", oauth_version="1.0"]

response is a 200, payload includes oauth_token=a95d6305-4261-4c1d-a9b0-43411a0c2f2c&oauth_token_secret=573702d2-70ca-412c-84e5-868e9ee07169

but then, it calls the URL again.

http://localhost:8080/app/ws/oauth/token [OAuth oauth_consumer_key="itd79n64zlwv5hhv", oauth_nonce="6c013ef9-2f3c-49dd-84fb-97db73b5fb39", oauth_signature="5RTQE5XtcqUwEFVvYQjExhH1eio%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1458938403", oauth_token="5451cf20-7eed-4797-819c-ee2316981654", oauth_verifier="c56de555-79df-455e-ab87-f5f11b953fef", oauth_version="1.0"

which causes an exception on the server since the request token has been removed and the access token has already been issued.

When stepping through the code, I can see that the OAuthConsumerContextFilter stores the access token fine after the first call.

Somehow the filter chain ends up bring it back to readResource in CoreOAuthConsumerSupport with the request token.

I built the consumer app using spring-boot.

from: applicationContext.xml

    <bean id="oscarService" class="com.mdumontier.oscar.labline.service.OscarService">
        <property name="oscarRestTemplate">
            <bean class="org.springframework.security.oauth.consumer.client.OAuthRestTemplate">
                <constructor-arg ref="oscar" />
            </bean>
        </property>

    </bean>

 <security:authentication-manager>
    <security:authentication-provider>
      <security:user-service>
        <security:user name="marissa" password="wombat" authorities="ROLE_USER" />
        <security:user name="sam" password="kangaroo" authorities="ROLE_USER" />
      </security:user-service>
    </security:authentication-provider>
  </security:authentication-manager>

<security:http auto-config='true' >

  </security:http>



 <oauth:consumer resource-details-service-ref="resourceDetails" oauth-failure-page="/oauth_error.jsp">
    <oauth:url pattern="/oscar/**" resources="oscar"/>
  </oauth:consumer>


  <oauth:resource-details-service id="resourceDetails">
    <oauth:resource id="oscar"
                    key="itd79n64zlwv5hhv"
                    secret="d3psvmrn8k1xws9x"
                    request-token-url="http://localhost:8080/app/ws/oauth/initiate"
                    user-authorization-url="http://localhost:8080/app/ws/oauth/authorize"
                    access-token-url="http://localhost:8080/app/ws/oauth/token"/>
  </oauth:resource-details-service>
1

1 Answers

0
votes

Spring Boot automatically registers any Beans which implement Filter in the main application filter chain. See: https://stackoverflow.com/a/28428154 for a bit more detail.

The oauth:consumer helper registers both OAuth filters as beans, and seems to not have been updated in a while. I couldn't even get the XML config to work properly under the latest Spring Boot. Anyway, this means that both will be run twice, and in the case of the OAuthConsumerContextFilter this is destructive since it will run outside the security sub-chain and fail every time.

To fix this you have two options.

One, hint to Spring Boot to avoid this behavior by providing a FilterRegistrationBean for each filter it's automatically picking up, like so:

@Bean
public FilterRegistrationBean registration(OAuthConsumerContextFilter filter) {
    FilterRegistrationBean registration = new FilterRegistrationBean(filter);
    registration.setEnabled(false);
    return registration;
}

Two, bypass the XML config entirely and use Java config. I've posted a complete working code sample of getting on OAuth 1 consumer in Spring Boot using Java config in this answer: https://stackoverflow.com/a/42143001/2848158

Within the Java config, you would have to either repeat the FilterRegistrationBean trick, or just not register those filters as beans in the first place but rather create and register instances directly with the Security filter chain.