Spring Oauth Security - Basic Access Authentication Required When Submitting Token Request

I have one problem with Spring Security OAuth 2.0.

There is a basic spring-security configuration taken from the sample:

<http pattern="/oauth/token" create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <custom-filter ref="clientCredentialsTokenEndpointFilter"
        after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<http pattern="/path/**" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/path/*" access="ROLE_USER" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

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

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

<bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.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>

<bean id="oauthAuthenticationProvider" class="my.package.OAuthAuthenticationProvider" xmlns="http://www.springframework.org/schema/beans" />

<authentication-manager id="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>

<authentication-manager alias="authenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <authentication-provider ref="oauthAuthenticationProvider" />
</authentication-manager>

<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.DefaultTokenServices">
    <property name="tokenStore" ref="tokenStore" />
    <property name="supportRefreshToken" value="true" />
    <property name="clientDetailsService" ref="clientDetails" />
</bean>

<bean id="userApprovalHandler"
    class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
    <property name="tokenServices" ref="tokenServices" />
</bean>

<!-- authorization-server aka AuthorizationServerTokenServices is an interface 
    that defines everything necessary for token management -->
<oauth:authorization-server
    client-details-service-ref="clientDetails" token-services-ref="tokenServices"
    user-approval-handler-ref="userApprovalHandler">
    <oauth:authorization-code />
    <oauth:implicit />
    <oauth:refresh-token />
    <oauth:client-credentials />
    <oauth:password />
</oauth:authorization-server>

<oauth:resource-server id="resourceServerFilter"
    resource-id="test" token-services-ref="tokenServices" />
<!-- ClientsDeailsService: Entry Point to clients database (given is in 
    memory implementation) -->
<oauth:client-details-service id="clientDetails">
    <!-- client -->
    <oauth:client client-id="the_client"
        authorized-grant-types="authorization_code,client_credentials"
        authorities="ROLE_USER" scope="read,write,trust" secret="secret" />

    <oauth:client client-id="my-trusted-client-with-secret"
        authorized-grant-types="password,authorization_code,refresh_token,implicit"
        secret="somesecret" authorities="ROLE_USER" />

</oauth:client-details-service>

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

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

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

This works when in my web.xml file it looks like this:

...
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-security.xml</param-value>
</context-param>
...
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
...
<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>
...
<servlet>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
...
<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping> 

But in this case, the "old part" of the system does not work. Therefore, I need to change the display of the servlet manager:

<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/somepath/*</url-pattern>
</servlet-mapping> 

Now the old part works, but not the Oauth Spring protection. I tried with two url templates:

<servlet-mapping>
    <servlet-name>Dispatcher Servlet</servlet-name>
    <url-pattern>/somepath/*</url-pattern>
    <url-pattern>/*</url-pattern>
</servlet-mapping> 

Then oauth works, the old part does not.

I made another attempt and changed:

<http pattern="/somepath/oauth/token" create-session="stateless"
    authentication-manager-ref="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/somepath/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <anonymous enabled="false" />
    <http-basic entry-point-ref="clientAuthenticationEntryPoint" />
    <custom-filter ref="clientCredentialsTokenEndpointFilter"
        after="BASIC_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

And now it works as follows:

, auth?

+3
2

, Spring OAuth DispatcherServlet , OAuth. (/), . one-stop-shop , ( DispatcherServlet not a ContextLoaderListener). , ( init init web.xml), ( , ).

. OAuth2 , / , , , . , , , - , ClientCredentialsTokenEndpointFilter ( ). , , , , GET ( POST), , , , POST-only ( , ).

2 Spring XML, web.xml 2. , , bean . , ( DispatcherServlet, )?

+1

, :

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .authorizeRequests()
                .antMatchers("/").permitAll()
            .and()
                .authorizeRequests().anyRequest().hasRole("USER")
            .and()
                .csrf()
                .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/**")).disable();
        // @formatter:on
    }
    ...
}

. , , 403 ( , )

0

All Articles