Announcement Announcement Module
Collapse
No announcement yet.
oauth 2 An Authentication object was not found in the SecurityContext Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • oauth 2 An Authentication object was not found in the SecurityContext

    Hi,

    I'm trying to replicate the OAuth 2.0 authentication sparklr example in my application, when i run a test end call /app/oauth/token resurce I get 401 error: An Authentication object was not found in the SecurityContext.

    I try to change /app/* with /* in web.xml it work fine. I can not understand what could be the problem

    My security context
    Code:
    	<http pattern="/app/oauth/token" create-session="never" authentication-manager-ref="clientAuthenticationManager"xmlns="http://www.springframework.org/schema/security">
    		<intercept-url pattern="/app/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    		<anonymous enabled="false" />
    		<http-basic />
    		<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
    		<access-denied-handler ref="oauthAccessDeniedHandler" />
    	</http>
    	<http access-denied-page="/app/pub/login.htm" xmlns="http://www.springframework.org/schema/security">
    		<intercept-url pattern="/app/oauth/**" access="ROLE_USER" />
    		<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    		<form-login authentication-failure-url="/app/pub/login.htm?login_error=1" login-page="/app/pub/login.htm" authentication-success-handler-ref="roleBasedTargetUrl" login-processing-url="/app/pub/login/login_security_check.do" />
    		<logout logout-success-url="/app/pub/home.htm" invalidate-session="true"   		logout-url="/app/secure/logout"/>
    		<anonymous />
    	</http>
    
    	<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAuthenticationEntryPoint">
    		<property name="realmName" value="FantaGameBE" />
    	</bean>
    
    	<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAccessDeniedHandler" />
    	<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.filter.ClientCredentialsTokenEndpointFilter">
    		<property name="authenticationManager" ref="clientAuthenticationManager" />
    	</bean>
    
    	<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
    		<constructor-arg>
    			<list>
    				<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
    				<bean class="org.springframework.security.access.vote.RoleVoter" />
    				<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
    			</list>
    		</constructor-arg>
    	</bean>
    
    	<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    		<authentication-provider user-service-ref="clientDetailsUserService" />
    	</authentication-manager>
    
        <authentication-manager xmlns="http://www.springframework.org/schema/security">
        	<authentication-provider ref="authenticationProvider"/>
        </authentication-manager>
        
        <bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
            <property name="passwordEncoder">
                <bean class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" >
                	<constructor-arg value="256"/>
                </bean>
            </property>
            <property name="saltSource" ref="saltSource"/>
            <property name="userDetailsService" ref="userDetailsService" />
        </bean>
        <bean id="userDetailsService" 	class="com.fantagame.be.application.security.UserDetailsServiceImp"/>
         <bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
    		<property name="userPropertyToUse" value="getNick" />
    	</bean>
    
    	<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    		<constructor-arg ref="clientDetails" />
    	</bean>
    
    	<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
    
    	<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.RandomValueTokenServices">
    		<property name="tokenStore" ref="tokenStore" />
    		<property name="supportRefreshToken" value="true" />
    	</bean>
    
    	<bean id="userApprovalHandler" class="com.fantagame.be.application.security.oauth.SparklrUserApprovalHandler">
    		<property name="autoApproveClients">
    			<set>
    				<value>my-less-trusted-autoapprove-client</value>
    			</set>
    		</property>
    		<property name="tokenServices" ref="tokenServices" />
    	</bean>
    
    	<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"user-approval-handler-ref="userApprovalHandler" user-approval-page="oauth/confirm_access" >
    		<oauth:authorization-code />
    		<oauth:implicit />
    		<oauth:refresh-token />
    		<oauth:client-credentials />
    		<oauth:password />
    	</oauth:authorization-server>
    
    	<oauth:resource-server id="resourceServerFilter" resource-id="fantagame" token-services-ref="tokenServices" />
    
    	<oauth:client-details-service id="clientDetails">
    		<oauth:client client-id="my-trusted-client" 							authorized-grant-types="password,authorization_code,refresh_token,implicit"	authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" />
    		<oauth:client client-id="my-trusted-client-with-secret" 				authorized-grant-types="password,authorization_code,refresh_token,implicit" authorities="ROLE_CLIENT" secret="somesecret" />
    		<oauth:client client-id="my-less-trusted-client" 						authorized-grant-types="authorization_code,implicit"	authorities="ROLE_CLIENT" />
    		<oauth:client client-id="my-less-trusted-autoapprove-client" 			authorized-grant-types="implicit" 		authorities="ROLE_CLIENT" />
    		<oauth:client client-id="my-client-with-registered-redirect" 			authorized-grant-types="authorization_code,client_credentials" 	authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read,trust" />
    		<oauth:client client-id="my-untrusted-client-with-registered-redirect" 	authorized-grant-types="authorization_code" authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" />
    		<oauth:client client-id="tonr" resource-ids="sparklr" 					authorized-grant-types="authorization_code" authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
    	</oauth:client-details-service>
    
    	<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="false">
    		<sec:expression-handler ref="oauthExpressionHandler" />
    	</sec:global-method-security>
    
    	<oauth:expression-handler id="oauthExpressionHandler" />
    
    	<bean id="adminController" class="com.fantagame.be.business.controller.AdminController">
    		<property name="userApprovalHandler" ref="userApprovalHandler" />
    	</bean>
    	<bean id="accessConfirmationController" class="com.fantagame.be.business.controller.AccessConfirmationController">
    		<property name="clientDetailsService" ref="clientDetails" />
    	</bean>
    	<bean id="loadRSAKey" 			class="com.fantagame.be.application.security.LoadRSAPrivateKey">
    		<property name="path" value="classpath:privateKey.ky"/>
    	</bean>	
    	<bean id="roleBasedTargetUrl" 	class="com.fantagame.be.application.security.RoleBasedTargetUrl" />
    	<bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler" />
    this my web.xml
    Code:
    <listener>
            <listener-class>
                org.springframework.web.context.ContextLoaderListener
            </listener-class>
       </listener>
       
      	<servlet>
    		<servlet-name>FantaGameBE</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<init-param>
    			<param-name>contextConfigLocation</param-name>
    			<param-value></param-value>			
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	
    	<context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/web-application-context.xml
            </param-value>
        </context-param>
     
     	<servlet-mapping>
        	<servlet-name>FantaGameBE</servlet-name>
        	<url-pattern>/app/*</url-pattern>
     	</servlet-mapping>
    
    	<!-- Datasource connection -->
    	<resource-ref>
    		<description>Fantagame DataSource connection</description>
    		<res-ref-name>jdbc/fantagameDB</res-ref-name>
    		<res-type>javax.sql.DataSource</res-type>
    		<res-auth>Container</res-auth>
    	 </resource-ref>
    
    <!-- Log4J Configuration 	-->
    	<listener>
      		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    	</listener>
    	
    	<context-param>
      		<param-name>log4jConfigLocation</param-name>
      		<param-value>/WEB-INF/classes/log4j.xml</param-value>
    	</context-param>
    	
    <!-- Internationalization	-->
    	 <filter>
    	    <filter-name>encoding-filter</filter-name>
    	    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    	    <init-param>
    	        <param-name>encoding</param-name>
    	        <param-value>UTF-8</param-value>
    	    </init-param>
    	</filter>
    	
    	<filter-mapping>
    	    <filter-name>encoding-filter</filter-name>
    	    <url-pattern>/app/*</url-pattern>
    	</filter-mapping>
    	
    		<filter>
    		<filter-name>springSecurityFilterChain</filter-name>
    		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    		<init-param>
    			<param-name>contextAttribute</param-name>
    			<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.FantaGameBE</param-value>
    		</init-param>
    	</filter>
    
    	<filter-mapping>
    		<filter-name>springSecurityFilterChain</filter-name>
    		<url-pattern>/app/*</url-pattern>
    	</filter-mapping>
    How can i resolve this problem ?

    Thnaks a lot
    Last edited by cybertop; Mar 3rd, 2012, 04:22 PM. Reason: Resolve

  • #2
    I resolved the problem by extending AbstractAuthenticationProcessingFilter and set my resource /app/oauth/token.

    Thanks

    Comment


    • #3
      Normally you would want the troken endpoint to be secured with <http-basic/>. The sparklr sample does this and your original config looked fine. It looks like you are changing the default endpoint urls (adding "/app" at the start), so maybe that was a mistake, since you didn't add that to the <authorization-server/> or add the extra filter in web.xml?

      Comment


      • #4
        Originally posted by Dave Syer View Post
        Normally you would want the troken endpoint to be secured with <http-basic/>. The sparklr sample does this and your original config looked fine. It looks like you are changing the default endpoint urls (adding "/app" at the start), so maybe that was a mistake, since you didn't add that to the <authorization-server/> or add the extra filter in web.xml?

        I have not added additional filters in web.xml, and configuration is not changed, I just used as clientCredentialsTokenEndpointFilter a class implemented by me that extends AbstractEndpointFilter where i add "/app" to the URL path.

        Comment


        • #5
          Originally posted by Dave Syer View Post
          Normally you would want the troken endpoint to be secured with <http-basic/>. The sparklr sample does this and your original config looked fine. It looks like you are changing the default endpoint urls (adding "/app" at the start), so maybe that was a mistake, since you didn't add that to the <authorization-server/> or add the extra filter in web.xml?
          Dave,

          I'm currently working with the oauth2 sample code from the latest code available on github (commit cad240aa6141be3ccf777e4de958e30430e2f7c9, Thu Mar 1 11:29:45 2012 +0000) and I'm also seeing this same error. This is with NO modifications to the code, i.e. running sparklr2 and tonr2 directly off the Maven builds (I did deploy from the target/*2-1.0.0-SNAPSHOT folders directly to the Tomcat webapps folder instead of from the war files; I just did "cp -R target/sparklr2-1.0.0-SNAPSHOT /Library/Tomcat6/Home/webapps"). I was unable to see the photos in the app, so I figured something was wrong.

          I looked through the configuration in IntelliJ and it indicated that the create-session="stateless" setting was invalid. The log and notes about this are attached in stateless.zip.

          I changed this to be create-session="never", since this was the setting in the code under the 1.0.0.M6 tag (although in that tag there create-session attribute is only specified for the /oauth/token configuration, whereas in the latest rev it's set for three total configurations). I had better luck seeing the photos, and what happened internally was clearly a lot different. For example, just loading the login page when create-session was set to stateless generated about 65 lines of logging output. When it was set to never, it generated 277 lines of logging output.

          So with that, sparklr2 worked, but I still ran into issues with calling back into sparklr2 from tonr2. Issues as in, it didn't work.

          I've included the log files along with some notes for each of them indicating what operations happened where in the log files, so, e.g., "Initialization goes up to line 615. Lines 616 to 754 shows the load of the login page." This helps show at which point in the application lifecycle the various errors are occurring.

          At this point, I'll keep messing around with the sample apps and try to get them working, but it'd be SUPER handy to have the sample code fully functional to get a grok on how to get this integrated.

          For system stuff, I'm seeing pretty much identical behavior on both Windows 7 64-bit with the 1.6 JVM and Tomcat 6, as well as on OS X 10.6.8 64-bit with JVM 1.6 and Tomcat 6.

          If there's any other information I can give, I'd be more than happy to provide it.

          Update: Just to remove this as another variable, when I run the apps using the mvn tomcat:run method, I get exactly the same results for the different scenarios.
          Last edited by rherrick; Mar 7th, 2012, 02:49 PM.

          Comment


          • #6
            Ah, it looks like I'm seeing the same thing as they're seeing in this thread. After more than a couple of people having the same problems, especially across multiple platforms, you're past having some "unlucky" developers and are solidly in the realm of something going wrong with the code. Especially because this is with the sample code, where it should be pretty easy to figure out what's going wrong.

            Like I said, I'd be happy to try whatever you might need to help get to the bottom of this issue, but there's definitely an issue outside of a few people being "unlucky".

            Comment


            • #7
              Solution to at least some of these issues found here.

              Comment


              • #8
                So is this accurate?

                * the samples do work out of the box but not on Chrome (I use Firefox so I never see a problem)
                * the problem with Chrome browser needs to be fixed in Spring Web (where's the JIRA ID?)

                Comment


                • #9
                  Originally posted by Dave Syer View Post
                  So is this accurate?

                  * the samples do work out of the box but not on Chrome (I use Firefox so I never see a problem)
                  * the problem with Chrome browser needs to be fixed in Spring Web (where's the JIRA ID?)
                  Dave,

                  I believe that's correct. In fact, the samples would not work on any browser where the Accept header did not have an appropriate MIME type for the images. In this case, when I view the site in Opera, the header that seems to make everything OK is actually image/png, which I guess is acceptable for rendering the BufferedImage type. And indeed when I inspect the image it says that it's a PNG, so I guess it's just all in how the browser decides to render the image and not what the actual image source is.

                  So, this would happen for any browser where the Accept header did not have an appropriate MIME type for the images and this appears to mean both Chrome and Safari on Mac and at least Chrome on Windows. IE and FF both appear to work on Windows. I don't have FF on Mac or Safari on Windows to test those out, but I think that the general issue is enough just on those few that fail to justify the fix on the Spring Web side.

                  As for the JIRA ID, here's the bug I found. The issue is really in the AnnotationMethodHandlerAdapter class in the private writeWithMessageConverters() method. It goes through the list of accepted media types and never matches */* if that's the only media type accepted. I've actually used the solution proposed by Shawn Clark with the EnhancedBufferedImageHttpMessageConverter class and that's working for me, but it'd be nice to just have the framework work properly!

                  Comment


                  • #10
                    Thanks for the JIRA reference. I also added https://jira.springsource.org/browse/SECOAUTH-219 and fixed the samples to (hopefully) work with Chrome.

                    Comment


                    • #11
                      Indeed it is an old thread, yet I do get the same problem. I'm sure from a different reason that the guys before me ...
                      I work on RC2a, successfuly get a code (after calling /authorize), but when I make the call to /token I get 401. Breakpoint in TokenEndpoint never stops (of course).
                      (Dave - I did a small "hack" in order to keep working even though I work with anonymous token (have raised a ticked in Jira) so I extended AuthorizationCodeResourceDetails and my isClientOnly() returns true so this way I do get the redirect to the /authorize. Can this cause my problem? I doubt...)
                      Where the problem can be? definitions of the oAuth provider or the client?

                      my XML of the oAuth provider:

                      Code:
                         <!-- Protect the /oauth/token url to allow only registered clients -->
                      <security:http pattern="/oauth/token"  authentication-manager-ref="clientAuthenticationManager"        >
                              <!--<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />-->
                              <security:intercept-url pattern="/oauth/token" access="ROLE_CLIENT" requires-channel="https"/>
                              <security:anonymous enabled="false" />
                              <security:http-basic />
                      </security:http>
                      
                      <security:authentication-manager id="clientAuthenticationManager">
                              <security:authentication-provider user-service-ref="clientDetailsUserService" />
                      </security:authentication-manager>
                      
                      <bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
                              <constructor-arg ref="clientDetails" />
                      </bean>
                      
                      <bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
                      	<constructor-arg ref="dataSource" />
                      </bean
                      >

                      Comment


                      • #12
                        Originally posted by OhadR View Post
                        successfuly get a code (after calling /authorize), but when I make the call to /token I get 401. Breakpoint in TokenEndpoint never stops (of course).
                        A 401 means you didn't authenticate the call to the token endpoint. Did you send a basic header with the client id and secret? Did you get the secret wrong? The error seems to be in the client, but you only showed the config for the server.

                        I doubt this is related to your hack (but you are doing something very dangerous there, and I would exercise caution if I were you before using it in production).

                        Comment


                        • #13
                          Originally posted by Dave Syer View Post
                          A 401 means you didn't authenticate the call to the token endpoint. Did you send a basic header with the client id and secret? Did you get the secret wrong? The error seems to be in the client, but you only showed the config for the server.
                          I use OAuth2AccessTokenSupport.retrieveToken(). I see that this method "prepares" the parameters for the call, as well as the headers... then it calls using RestTemplate to /oauth/token.
                          what am I missing?

                          Originally posted by Dave Syer View Post
                          you are doing something very dangerous there, and I would exercise caution if I were you before using it in production
                          I use this hack since I have no choice, till this issue is resloved... (my client is "anonymous" etc). I'd be happy to get rid of my work-around and use the highway.

                          Comment


                          • #14
                            Originally posted by OhadR View Post
                            I see that this method "prepares" the parameters for the call, as well as the headers... then it calls using RestTemplate to /oauth/token.
                            Does it set the Authorization header with the correct client id and secret? What does the server say in its logs when it denies access?

                            Comment


                            • #15
                              Actually, the retrieveToekn() method get HttpHeaders and I see that it comes empty - but the client_id and client_secret comes in the "form" parameter (which is a Map of attributes). So regarding your question - the headers are empty (but I count on oAuth-Spring files, I do nothing "by myself")
                              in RestTemplate#doExecute():
                              the url is https://ohad.sealdoc.com/butke-up/oauth/token
                              method is POST
                              requestCallback - contains empty headers, and the form Map contains all the data (including client id+secret)

                              I see nothing in the server's log, only in the client
                              WARN web.client.RestTemplate - POST request for "https://ohad.sealdoc.com/butke-up/oauth/token" resulted in 401 (Unauthorized); invoking error handler

                              Comment

                              Working...
                              X