1

Using :

  • spring-security 3.2.5
  • spring-security-oauth 2.0.7 (oauth2)
  • grant_type : authentication_code

I have no problem getting authentication_code and access token. The problem I have is that if I call a "protected" resource, I can access it with no token at all. Here is the security config of the "not-really-protected" resource :

<security:http pattern="/api/user/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

The Oauth2AuthenticationProcessingFilter is saying

No token in request, will continue chain.

I found this other post wich seems to describe the same problem, but the solution presented is to add <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />, wich I already have.

Also, tough maybe not related, the request to the protected resource receive à Set-cookie header, defining a jsessionid. It seems not normal to me since I specify create-session="never".

I expected an unauthorized call to this resource to return a 403 since I use OAuth2AccessDeniedHandler.

Can someone help me with this ?

Note that I am pretty sure that this security config is kicking in because in my protected resource(a spring-mvc controller), SecurityContextHolder.getContext().getAuthentication() returns null. If I completely disable the above security config, the same line returns an anonymous authentication.

EDIT : Detailed configuration information.

First I have the token enpoint configuration :

  <security:http pattern="/api/oauth/token" 
               create-session="stateless" 
               authentication-manager-ref="clientAuthenticationManager">
    <security:intercept-url pattern="/api/oauth/token"
                            access="IS_AUTHENTICATED_FULLY" />
    <security:anonymous enabled="false" />
    <security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <security:access-denied-handler ref="oauthAccessDeniedHandler" />
  </security:http>

Then the resource endpoint configuration (as shown at the beginning of the question) :

   <security:http pattern="/api/user/**" 
                  create-session="never" 
                  entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
     <security:anonymous enabled="false" />
     <security:intercept-url pattern="/api/user/**"
                             access="IS_AUTHENTICATED_FULLY" />
     <security:custom-filter ref="userResourceServer"
                             before="PRE_AUTH_FILTER" />
     <security:access-denied-handler ref="oauthAccessDeniedHandler" />
   </security:http>

And then the "generic" url configuration :

<security:http name="genericSecurityConfiguration" entry-point-ref="customLoginEntrypoint">
    <security:form-login authentication-failure-url="/index.jsp"
                         authentication-success-handler-ref="customAuthenticationSuccessHandler"
                         authentication-failure-handler-ref="customAuthenticationFailureHandler"
                         login-page="/index.jsp"
                         login-processing-url="/solapCore/identification2"
                         username-parameter="username"
                         password-parameter="password"
                         />
    <security:session-management invalid-session-url="/index.jsp?invalidSession=true" session-authentication-strategy-ref="sas" /> 
    <security:custom-filter position="LOGOUT_FILTER" ref="logoutFilter"/>
    <security:custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="monitoringFilter"/>
    <security:access-denied-handler ref="solapcoreAccessDeniedHandler"/>
  </security:http>

Other oauth specific configuration in the same file :

<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="oauth" />
  </bean>

  <bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="oauth/client" />
    <property name="typeName" value="Basic" />
  </bean>

  <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
    <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>

  <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="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

  <oauth:authorization-server  
    client-details-service-ref="clientDetails" 
    token-services-ref="tokenServices" 
    user-approval-handler-ref="userApprovalHandler">
    <oauth:authorization-code />
  </oauth:authorization-server>

  <oauth:resource-server id="userResourceServer" 
                         resource-id="oauth2/user"  
                         token-services-ref="tokenServices" />

  <oauth:client-details-service id="clientDetails">
    <oauth:client client-id="someClientID" 
                  authorized-grant-types="authorization_code"
                  authorities="SOME_AUTHORITY" scope="read" secret="secret" />
  </oauth:client-details-service>

 <security:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
   <security:expression-handler ref="oauthExpressionHandler" />
 </security:global-method-security>

 <oauth:expression-handler id="oauthExpressionHandler" />
 <oauth:web-expression-handler id="oauthWebExpressionHandler" />

 <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />

 <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="clientDetails" />
 </bean>

Finaly, my dispatcher servlet and filterChain configuration in web.xml :

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>
    org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
Community
  • 1
  • 1
baraber
  • 3,296
  • 27
  • 46

3 Answers3

0

i believe that you are missing "Authorization" header. you need to have value of "Bearer" in the header value.

ref:

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/BearerTokenExtractor.java

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/common/OAuth2AccessToken.java

Titi Wangsa bin Damhore
  • 7,101
  • 4
  • 31
  • 36
  • It work perfectly with the access token (Authorization header). The problem is that my resource is being called even without the token. – baraber Mar 31 '15 at 18:06
  • The url pattern is /api/* in your web.xml. Perhaps you need to remove /api prefix from you security config. – Titi Wangsa bin Damhore Apr 01 '15 at 05:21
  • I have other servlets mapped differently, so I need to narrow the url-pattern of the dispatcher servlet. But the dispatcher servlet is processing the request, so the url-pattern of the servlet should be correct otherwise I'd see 404. – baraber Apr 01 '15 at 12:37
0

The problematic part in your configuration is <security:http pattern="/api/user/**" ...>

Since the "pattern" attribute is set to /api/user/**, your intercept-url "pattern" attribute

<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />

won't have any effect unless it has the same prefix (/api/user/**).

If you're trying to use IS_AUTHENTICATED_FULLY only for the /api/user/** pattern, then the intercept-url should be

<security:http pattern="/api/user/**" ...>
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/api/user/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>

If you want to apply that rule for full application, then something like this should work:

<security:http create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
  <security:anonymous enabled="false" />
  <security:intercept-url pattern="/api/user/**" access="IS_AUTHENTICATED_FULLY" />
  <security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
  <security:custom-filter ref="userResourceServer" before="PRE_AUTH_FILTER" />
  <security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
Jigish
  • 1,764
  • 1
  • 15
  • 20
  • Thank you for trying to help me :) The problem is that I've put "/**" in intercept-url pattern because "/api/user/**" was not working (it was the first thing I tried). Also, I did not mention it in the question, but I also have a generic element below the one for /api/user/**, to catch other urls. At first I tought that could be part of the problem but even without that generic element, the problem persists : I can access the resource without any token (and also without being authenticated in any other way). Still, thank you for trying to help, it is much appreciated. – baraber Mar 31 '15 at 19:41
  • can you share your full security configuration file? it's difficult to figure out what the cause of the problem is. – Jigish Mar 31 '15 at 19:56
0

I found the cause of the problem, and it is very specific to our application.

Somewhere else in a config, we override the built-in FilterInvocationSecurityMetadataSource (using an evil bean post-processor) to add a Custom one. This have the effect to disable all <intercept-url> in config files. We did this because we migrated a legacy custom security framework to spring-security and wanted to keep url security in our already existing files.

Thanks to all that tried to help.

baraber
  • 3,296
  • 27
  • 46