Announcement Announcement Module
Collapse
No announcement yet.
Can't get AuthorizationRequest in the AccessConfirmationController Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can't get AuthorizationRequest in the AccessConfirmationController

    Hi,

    I am building a simple OAuth2 provider using spring-security-oauth 1.0.2.RELEASE. My XML configuration is:
    Code:
    	<http auto-config='true' 
    		xmlns="http://www.springframework.org/schema/security">
    		<intercept-url pattern="/**" access="ROLE_USER" />
    	</http>
    
    	<authentication-manager
    		xmlns="http://www.springframework.org/schema/security">
    		<authentication-provider>
    			<user-service>
    				<user name="a" password="a" authorities="ROLE_USER" />
    			</user-service>
    		</authentication-provider>
    	</authentication-manager>
    
    	<!-- OAuth Provider Configuration -->
    	<oauth2:authorization-server
    		client-details-service-ref="clientDetailsService" token-services-ref="tokenServices"
    		user-approval-handler-ref="userApprovalHandler">
    		<oauth2:authorization-code />
    		<oauth2:implicit />
    		<oauth2:refresh-token />
    		<oauth2:client-credentials />
    		<oauth2:password />
    	</oauth2:authorization-server>
    
    	<bean id="userApprovalHandler"
    		class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
    		<property name="tokenServices" ref="tokenServices" />
    	</bean>
    
    	<oauth2:client-details-service id="clientDetailsService">
    		<oauth2:client client-id="test-client" secret="123456"
    			authorized-grant-types="authorization_code" />
    	</oauth2:client-details-service>
    
    	<bean id="tokenServices"
    		class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    		<property name="tokenStore" ref="tokenStore" />
    		<property name="supportRefreshToken" value="true" />
    		<property name="clientDetailsService" ref="clientDetailsService" />
    	</bean>
    
    	<bean id="tokenStore"
    		class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore"></bean>
    And my access confirmation controller:
    Code:
    @Controller
    @SessionAttributes("authorizationRequest")
    public class ConfirmationController {
    
    	private ClientDetailsService clientDetailsService;
    
    	@RequestMapping("/oauth/confirm_access")
    	public ModelAndView getAccessConfirmation(Map<String, Object> model) throws Exception {
    		AuthorizationRequest clientAuth = (AuthorizationRequest) model.remove("authorizationRequest");
    		ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId());
    		model.put("auth_request", clientAuth);
    		model.put("client", client);
    		return new ModelAndView("access_confirmation", model);
    	}
    
    
    	@RequestMapping("/oauth/error")
    	public String handleError(Map<String,Object> model) throws Exception {
    		// We can add more stuff to the model here for JSP rendering.  If the client was a machine then
    		// the JSON will already have been rendered.
    		model.put("message", "There was a problem with the OAuth2 protocol");
    		return "oauth_error";
    	}
    
    	@Autowired
    	public void setClientDetailsService(ClientDetailsService clientDetailsService) {
    		this.clientDetailsService = clientDetailsService;
    	}
    }
    I also write a simple test client to test it. But I got a "java.lang.NullPointerException" in "ClientDetails client = clientDetailsService.loadClientByClientId(clientAu th.getClientId());" when I logged in the server and try to get user's authorization in the /oauth/confirm_access.

    After I searched solution for this, I add " create-session=“stateless” " in the XML configuration file, I can't even log in the server before entering the ConfirmationController.

    Any solution for this?

    Thank you very much in advance!

  • #2
    How did you get to the /oauth/confirm_access page? If you didn't go through /oauth/authorize then there will be no AuthorizationRequest in the session.

    Comment


    • #3
      Thank you, you are right!

      I configured my client rest-template resource userAuthorizationUri with "/oauth/confirm_access" wrongly. By changing it to "/oauth/authorize", it works now.

      However, I got another error after access confirmation when the client tried to get access token from the server:
      Code:
      java.lang.IllegalStateException : An OAuth 2 access token must be obtained or an exception thrown.
             at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:121)
             at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:216)
             at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:168)
             at org.springframework.security.oauth2.client.OAuth2RestTemplate.createRequest(OAuth2RestTemplate.java:89)
             at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:479)
             at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:123)
             at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:460)
      When I debugged this, I found the code of TokenEndpoint which mapped to "/oauth/token" is not even executed.

      Here is my client configuration:
      Code:
      	<http auto-config='true' xmlns="http://www.springframework.org/schema/security">
      		<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="clientContext" />
      		<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
      	</http>
      	
      	<authentication-manager
      		xmlns="http://www.springframework.org/schema/security">
      		<authentication-provider>
      			<user-service>
      				<user name="s" password="s" authorities="ROLE_USER" />
      			</user-service>
      		</authentication-provider>
      	</authentication-manager>
      	
      	<!--apply the oauth client context -->
      	<oauth2:client id="clientContext" />
      
      	<bean id="tokenServices"
      		class="org.springframework.security.oauth2.client.token.JdbcClientTokenServices">
      		<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
      	</bean>
      
      	<bean id="secureResource"
      		class="oauth.client.ExtendedBaseOAuth2ProtectedResourceDetails">
      		<property name="clientId" value="test-client" />
      		<property name="clientSecret" value="123456" />
      		<property name="accessTokenUri"
      			value="http://localhost:8080/spring-oauth-helloworld/oauth/token" />
      		<property name="userAuthorizationUri"
      			value="http://localhost:8080/spring-oauth-helloworld/oauth/authorize" />
      		<property name="clientAuthenticationScheme" value="form" />
      	</bean>
      
      	<bean id="secureResourceService" class="oauth.client.SecureResourceService">
      		<property name="secureResourceURL"
      			value="http://localhost:8080/spring-oauth-helloworld/security"></property>
      		<property name="secureResourceRestTemplate">
      			<oauth2:rest-template resource="secureResource"></oauth2:rest-template>
      		</property>
      		<property name="tokenServices" ref="tokenServices"></property>
      	</bean>
      
      	<!-- Jdbc DataSource -->
      	<bean id="dataSource"
      		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      
      		<property name="driverClassName" value="org.postgresql.Driver" />
      		<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
      		<property name="username" value="postgres" />
      		<property name="password" value="123456" />
      	</bean>
      How does this happen? I appreciate your help.

      Comment


      • #4
        I don't know what your ExtendedBaseOAuth2ProtectedResourceDetails does. If it doesn't have a grant type of "authorization_code" then your client is not authorized to use it.

        Comment


        • #5
          I made ExtendedBaseOAuth2ProtectedResourceDetails extend AuthorizationCodeResourceDetails and override isClientOnly() method, makes it return true so I don't need to login in the client side.
          Code:
          import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
          
          public class ExtendedBaseOAuth2ProtectedResourceDetails extends AuthorizationCodeResourceDetails{
          @Override
          public boolean isClientOnly() {
          	return true;
          }
          }
          I also tested it with Facebook's OAuth server, it works well and I get my Facebook profile as expected. So I suppose there is something wrong in my server side.

          Comment


          • #6
            Originally posted by readjay View Post
            I made ExtendedBaseOAuth2ProtectedResourceDetails extend AuthorizationCodeResourceDetails and override isClientOnly() method, makes it return true so I don't need to login in the client side.
            I'm not sure that makes a lot of sense since AuthorizationCodeResourceDetails is clearly not a client only protocol. If you have something that works, then don't let me stop you, but it seems like you might want to try and understand why it works and fix it another way.

            Comment

            Working...
            X