Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: Separate Resource Server and Authorization Server

  1. #11
    Join Date
    Jul 2012
    Posts
    22

    Default

    Thanks. I switched to the jdbc token store implementation and was able to separate out the auth / resource server for sparklr / tonr.

    I am running into something odd, though. I am running each webapp in a different app server instance on separate ports. This works fine. I have further modified things so that each app is running at the root context ('/') on the app server. This is working for the resource server (sparklr) and client app (tonr), but when I change the context for the authorization service, things start breaking. I have changed the access token and user authorization urls in tonr to point to the authorization on the root context, but for some reason when I get redirected from the authorization service back to tonr, I seem to lose the session and I am asked to log back in to tonr (and don't have a valid token for sparklr either). This only occurs if I switch from any web context (/authorization, /authservice, etc) on the authorization service to '/'. Any ideas what might be happening?

  2. #12
    Join Date
    Jun 2005
    Posts
    4,241

    Default

    I don't think it's possible to say specifically what's wrong without more information, but it sounds like a generic Spring Securit config issue. The cloudfoundry UAA runs on / (as well as /uaa) if you want to look at an example. I never tried it with sparklr2.

  3. #13
    Join Date
    Jul 2012
    Posts
    22

    Default More details

    I've spent some more time characterizing this issue, so I can provide a few more details and hopefully resolve it.

    The error that I get on the client side, after authorizing the client application in the authorizationservice (/oauth/authorize), I get this exception when the oauth resttemplate makes the request to the resource server:

    Code:
    HTTP ERROR 500
    
    Problem accessing /service/myservice. Reason:
    
        Possible CSRF detected - state parameter was present but no state could be found
    Caused by:
    
    error="invalid_request", error_description="Possible CSRF detected - state parameter was present but no state could be found"
    	at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getParametersForTokenRequest(AuthorizationCodeAccessTokenProvider.java:199)
    	at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:161)
    	at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:120)
    	at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:100)
    	at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:194)
    	at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:148)
    	at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:89)
    	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:434)
    	at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:122)
    	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:415)
    	at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:213)
            at com.acme.prototype.oauth.client.impl.ServiceImpl.getIds(ServiceImpl.java:35)
            at com.acme.prototype.oauth.client.mvc.ClientController.photos(ClientController.java:38)
    The other thing I noticed is that the code stored by my authorizationcodeservices impl is never removed.

    Attached is the spring configuration for the AuthorizationService which was originally based on the sparklr demo spring-servlet.xml.txt

    Let me know if there is anything else that might help figure out what is happening.

  4. #14
    Join Date
    Jun 2005
    Posts
    4,241

    Default

    The code is never consumed on the server because the CSRF protection kicks in and prevents the client from using it. CSRF protection is a clientside feature so we'd have to see your client configuration to get an idea what that's about. I would guess that maybe you aren't managing the state of the OAuth2RestTemplate. The best way is to use the <oauth:rest-template/> DSL convenience.

  5. #15
    Join Date
    Jul 2012
    Posts
    22

    Default

    Here is the client spring context configuration. Note that I am using oauth:rest-template. The only difference between the working configuration and the one that triggers the CSRF protection is that the auth server is at the root context ('/').

    Code:
    <?xml version="1.0" encoding="UTF-8" ?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:sec="http://www.springframework.org/schema/security"
    	xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:context="http://www.springframework.org/schema/context"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    		http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
    		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
    
    	<http access-denied-page="/login.jsp?authorization_error=true" xmlns="http://www.springframework.org/schema/security" entry-point-ref="casEntryPoint">
            <intercept-url pattern="/j_spring_cas_security_check" access="ROLE_USER" />
    		<intercept-url pattern="/service/**" access="ROLE_USER"/>
            <intercept-url pattern="/login.jsp" access="ROLE_USER" />
    		<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    
    		<logout logout-success-url="/index.jsp" logout-url="/logout.do" />
    		<anonymous />
    		<custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
            <custom-filter position="CAS_FILTER" ref="casFilter" />
    	</http>
    
    	<!--apply the oauth client context -->
    	<oauth:client id="oauth2ClientFilter" />
    
    	<!--define an oauth 2 resource for service -->
    	<oauth:resource id="service" type="authorization_code" client-id="client" client-secret="secret"
    		access-token-uri="https://localhost:8105/oauth/token" user-authorization-uri="https://localhost:8105/oauth/authorize" scope="service_read,service_write" />
    
    	<!--define an oauth 2 resource for trusted client on service -->
    	<oauth:resource id="trusted" type="client_credentials" client-id="my-client-with-registered-redirect"
    		access-token-uri="https://localhost:8105/oauth/token" scope="trust" />
    
    	<mvc:default-servlet-handler />
    
    	<mvc:annotation-driven>
    		<mvc:message-converters>
    			<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
    		</mvc:message-converters>
    	</mvc:annotation-driven>
    
    	<bean id="contentViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    		<property name="mediaTypes">
    			<map>
    				<entry key="json" value="application/json" />
    			</map>
    		</property>
    		<property name="defaultViews">
    			<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
    		</property>
    	</bean>
    
    	<!--Basic application beans. -->
    	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="prefix" value="/WEB-INF/jsp/" />
    		<property name="suffix" value=".jsp" />
    	</bean>
    
    	<bean id="serviceClientController" class="com.acme.prototype.oauth.client.mvc.ClientController">
    		<property name="service" ref="service" />
    	</bean>
    
    	<bean id="service" class="com.acme.prototype.oauth.client.impl.ServiceImpl">
    		<property name="trustedMessageURL" value="http://localhost:8084/accounts/trusted/message" />
            <property name="serviceListURL" value="http://localhost:8084/service?format=xml" />
            <property name="serviceURLPattern" value="http://localhost:8084/service/%s" />
    		<property name="serviceRestTemplate">
    			<oauth:rest-template resource="service"  />
    		</property>
    		<property name="trustedClientRestTemplate">
    			<oauth:rest-template resource="trusted" />
    		</property>
    	</bean>
            
        <bean id="userDetailsServiceRestTemplate" class="org.springframework.web.client.RestTemplate"/>
        
        <bean id="userDetailsServiceClient" class="com.acme.oauth2.UserDetailsServiceClient" xmlns="http://www.springframework.org/schema/beans">
            <constructor-arg>
                <ref local="userDetailsServiceRestTemplate"/>
            </constructor-arg>
            <constructor-arg>
                <value>http://localhost:8103</value>
            </constructor-arg>
        </bean>
    
        <bean id="userDetailsService" class="com.acme.oauth2.AcmeUserDetailsService">
            <constructor-arg>
                <ref local="userDetailsServiceClient"/>
            </constructor-arg>
        </bean>
        
        
        <!-- CAS SSO Configuration -->
        <bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
            <property name="service" value="http://localhost:8080/j_spring_cas_security_check"/>
            <property name="sendRenew" value="false"/>
        </bean>
        
        <bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
          <property name="filterProcessesUrl">
            <value>/j_spring_cas_security_check</value>
          </property>
          <property name="authenticationManager" ref="authenticationManager"/>
            <property name="authenticationFailureHandler">
                <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                    <property name="defaultFailureUrl" value="/casfailed.jsp"/>
                </bean>
            </property>
            <property name="authenticationSuccessHandler">
                <bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
                    <property name="defaultTargetUrl" value="/"/>
                </bean>
            </property>
        </bean>
    
        <bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
            <property name="loginUrl" value="https://localhost:8104/login"/>
            <property name="serviceProperties" ref="serviceProperties"/>
        </bean>
        
        <authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
            <authentication-provider ref="casAuthenticationProvider" />
        </authentication-manager>
    
        <bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
          <property name="userDetailsService" ref="userDetailsService"/>
          <property name="serviceProperties" ref="serviceProperties" />
          <property name="ticketValidator">
            <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
              <constructor-arg index="0" value="https://localhost:8104/" />
              </bean>
          </property>
          <property name="key" value="ServiceClient"/>
        </bean>
    
    </beans>

  6. #16
    Join Date
    Jul 2012
    Posts
    22

    Default

    I finally figured this out. In my dev environment I am running the resource server, the authorization server and the client web application on separate ports on the same machine in different jetty instances. When I login to the client app (at localhost:8080/), it sets the session cookie for the root context. When I hit the authorization server (at localhost:8105) it sets another cookie for the root context, which clobbers the one that the client web app sets. After access confirmation when I am redirected back to the client web app the previous session is lost and the CSRF protection gets triggered. When I run the authorization server at a different context besides the root, the client web app cookie doesn't get clobbered. If I access my client web application at a different address (besides localhost), I am also able to avoid the issue. So problem solved and something to watch out for I guess if any others are running with similar dev configurations.

  7. #17
    Join Date
    Jul 2012
    Posts
    22

    Default

    Just a quick follow-up on this issue in case it helps someone else. Instead of using a different address, the session cookie name can be changed from the default (usually jsessionid) on the authorization server.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •