mardi 31 mars 2015

Can access spring oauth2 protected resource without access token

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>

Aucun commentaire:

Enregistrer un commentaire