Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring OAuth2 issues

I was converting xml based configuration (from source ) to java configuration. I have placed both the files below, it was working with xml configuration but cannot authenticate after changing to java configuration. Can anyone shed some ideas how to fix it?

authentication-managers.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sec="http://www.springframework.org/schema/security"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/security
                      http://www.springframework.org/schema/security/spring-security.xsd">

    <bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder"/>

    <sec:authentication-manager alias="userAuthenticationManager">
        <sec:authentication-provider user-service-ref="userService">
            <sec:password-encoder ref="passwordEncoder"/>
        </sec:authentication-provider>
    </sec:authentication-manager>

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


    <bean id="client-details-user-service" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
        <constructor-arg ref="client-details-service" />
    </bean>

</beans>

endpoint-configuration.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/security
                      http://www.springframework.org/schema/security/spring-security.xsd">



    <http pattern="/v1.0/users" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"
          xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/v1.0/users" method="POST" access="IS_AUTHENTICATED_FULLY"/>
        <anonymous enabled="false"/>
        <http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
        <access-denied-handler ref="oauthAccessDeniedHandler"/>
    </http>


    <!-- REST API Endpoints -->
    <http pattern="/v1.0/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
          xmlns="http://www.springframework.org/schema/security">
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
        <access-denied-handler ref="oauthAccessDeniedHandler"/>
    </http>


</beans>

Security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <context:component-scan base-package="com.porterhead.oauth2.configuration"/>


    <!-- Access voters -->
    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
          xmlns="http://www.springframework.org/schema/beans">
        <property name="decisionVoters">
            <list>
                <ref bean="roleVoter"/>
            </list>
        </property>
    </bean>

    <bean id="roleHierarchy"
          class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
        <property name="hierarchy">
            <value>
                ROLE_ADMIN > ROLE_USER
                ROLE_USER > ROLE_GUEST
            </value>
        </property>
    </bean>

    <bean id="roleVoter" class="com.porterhead.security.HierarchicalJsr250Voter">
        <constructor-arg ref="roleHierarchy" />
    </bean>

    <sec:global-method-security jsr250-annotations="enabled" access-decision-manager-ref="accessDecisionManager"/>

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

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

</beans>

Oauth2 config

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
       xmlns:sec="http://www.springframework.org/schema/security"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                      http://www.springframework.org/schema/beans/spring-beans.xsd
                      http://www.springframework.org/schema/security/oauth2
                      http://www.springframework.org/schema/security/spring-security-oauth2.xsd
                      http://www.springframework.org/schema/security
                      http://www.springframework.org/schema/security/spring-security.xsd">


    <oauth:authorization-server client-details-service-ref="client-details-service" token-services-ref="tokenServices">
        <oauth:refresh-token/>
        <oauth:password/>
    </oauth:authorization-server>

    <oauth:resource-server id="resourceServerFilter" token-services-ref="tokenServices"/>

    <bean id="clientCredentialsTokenEndpointFilter"
          class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
        <property name="authenticationManager" ref="clientAuthenticationManager"/>
    </bean>

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

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

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


    <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="client-details-service"/>
    </bean>

    <bean id="corsFilter" class="com.porterhead.filter.spring.SpringCrossOriginResourceSharingFilter"/>

    <bean id="oauthRestEntryPoint" class="com.porterhead.security.OAuthRestEntryPoint"/>

    <!-- The token endpoint See org.springframework.security.oauth2.provider.endpoint.TokenEndpoint-->
    <http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager"
          xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false"/>
        <http-basic entry-point-ref="oauthRestEntryPoint" />
        <access-denied-handler ref="oauthAccessDeniedHandler"/>
        <custom-filter ref="corsFilter" after="LAST"/>
    </http>


</beans>

JAVA Based configuration after conversion

oauth2 config

@Configuration
@ComponentScan
@EnableResourceServer
@Import(SecurityConfig.class)
//@ImportResource({
//  "classpath:META-INF/spring/oauth/client-details.xml"
//})
public class OAuth2ServerConfig {

    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2Config extends
            AuthorizationServerConfigurerAdapter {


        @Autowired
        private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter(){
            ClientCredentialsTokenEndpointFilter clientFilter = new ClientCredentialsTokenEndpointFilter();
            return clientFilter;
        }

        @Autowired
        private ClientDetailsService clientDetailsService;

        @Autowired
        public OAuth2AccessTokenRepository oAuth2AccessTokenRepository;

        @Autowired
        public OAuth2RefreshTokenRepository oAuth2RefreshTokenRepository;

        @Bean
        public DefaultTokenServices tokenServices(){
            final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setReuseRefreshToken(true);
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setClientDetailsService(clientDetailsService);
            return defaultTokenServices;
        }

        @Bean
        public OAuth2RepositoryTokenStore tokenStore() {
            return new OAuth2RepositoryTokenStore(oAuth2AccessTokenRepository,
                    oAuth2RefreshTokenRepository);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer)
                throws Exception {
            oauthServer.tokenKeyAccess(
                    "isAnonymous || hasAuthority('ROLE_TRUSTED_CLIENT')")
                    .realm("test");
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients)
                throws Exception {
            clients.withClientDetails(clientDetailsService);
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints.tokenServices(tokenServices())
                    .setClientDetailsService(clientDetailsService);
        }
    }

}

Security config

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private Validator validator;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new StandardPasswordEncoder();
    }
    @Bean
    public UserDetailsService userDetailsService() {
        return new UserServiceImpl(userRepository, validator, passwordEncoder());
    }

    @Autowired
    protected void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.userDetailsService(userDetailsService());
    }
    @Bean
    public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler(){
        return new OAuth2AccessDeniedHandler();
    }

    @Configuration
    @Order(1)
    public static class OAuthEndPointConfig extends WebSecurityConfigurerAdapter{


        @Autowired
        private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;

        @Autowired
        private ClientDetailsService clientDetailsService;

        @Bean
        public OAuthRestEntryPoint oauthRestEntryPoint()
        {
            return new OAuthRestEntryPoint();
        }

        @Bean
        public ClientDetailsUserDetailsService clientDetailsUserDetailsService(){
            return new ClientDetailsUserDetailsService(clientDetailsService);
        }


        @Bean
        protected AuthenticationEntryPoint authenticationEntryPoint(){
            OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
            entryPoint.setTypeName("Basic");
            entryPoint.setRealmName("test");
            return entryPoint;
        }



        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.anonymous().disable()
                .antMatcher("/oauth/token")
                .anonymous().disable().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .httpBasic().authenticationEntryPoint(oauthRestEntryPoint())
            .and()
                .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/token")).disable()
                .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
            .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

            ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
            filter.setAuthenticationManager(authenticationManagerBean());
            filter.afterPropertiesSet();
        }


    }
    @Configuration
    @Order(2)
    protected static class ResourceServerEndpointConfig extends WebSecurityConfigurerAdapter{

        @Autowired
        private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
        @Bean
        public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint(){
            OAuth2AuthenticationEntryPoint clientAuthenticationEntrypoint = new OAuth2AuthenticationEntryPoint();
            clientAuthenticationEntrypoint.setTypeName("Basic");
            return clientAuthenticationEntrypoint;
        }


        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.anonymous().disable().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
                .authenticationEntryPoint(clientAuthenticationEntryPoint())
            .and()
                .requestMatchers().antMatchers("/v1.0/users")
            .and()
                .authorizeRequests().antMatchers(HttpMethod.POST, "/v1.0/users").permitAll()
            .and()
                .csrf().disable();
        }
    }


}

Output after conversion

curl -v -X POST    -H "Content-Type: application/json"    -H "Authorization: Basic MzUzYjMwMmM0NDU3NGY1NjUwNDU2ODdlNTM0ZTdkNmE6Mjg2OTI0Njk3ZTYxNWE2NzJhNjQ2YTQ5MzU0NTY0NmM="    -d '{"user":{"emailAddress":"[email protected]"}, "password":"password"}'    'http://localhost:8080/v1.0/users'
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /v1.0/users HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Authorization: Basic MzUzYjMwMmM0NDU3NGY1NjUwNDU2ODdlNTM0ZTdkNmE6Mjg2OTI0Njk3ZTYxNWE2NzJhNjQ2YTQ5MzU0NTY0NmM=
> Content-Length: 67
>
* upload completely sent off: 67 out of 67 bytes
< HTTP/1.1 401 Unauthorized
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Cache-Control: no-store
< Pragma: no-cache
< WWW-Authenticate: Basic realm="oauth", error="unauthorized", error_description="An Authentication object was not found in the SecurityContext"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Wed, 13 May 2015 16:01:40 GMT
<
* Connection #0 to host localhost left intact
{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}Veeras-MacBook-Pro:~ veeramarni$
like image 375
user1595858 Avatar asked May 13 '15 16:05

user1595858


People also ask

Is Spring Security OAuth2 Autoconfigure deprecated?

OAuth2 Authorization Server Support. As we saw, the Spring Security OAuth stack offered the possibility of setting up an Authorization Server as a Spring Application. But the project has been deprecated, and Spring does not support its own authorization server as of now.

Is Spring cloud starter OAuth2 deprecated?

The Spring Security OAuth project has reached end of life and is no longer actively maintained by VMware, Inc. This project has been replaced by the OAuth2 support provided by Spring Security and Spring Authorization Server.

Is OAuth2 deprecated?

The first thing to note is that Spring Security OAuth 2.4. 0 officially deprecates all its classes. The second thing is that according to the Spring Security - OAuth 2.0 Features Matrix - FAQ: We are no longer planning on adding Authorization Server support to Spring Security.

Does spring security using OAuth2?

Spring Security handles the Authentication and Spring Security OAuth2 handles the Authorization. To configure and enable the OAuth 2.0 Authorization Server we have to use @EnableAuthorizationServer annotation.


1 Answers

I think the authenticationManager instance autowired in OAuth2ServerConfig initializes with the default DaoAuthenticationProvider. To use the custom beans that you have defined, inject your custom beans, configure AuthenticationManagerBuilder and expose authenticationManager as a bean in SecurityConfig like below

@Autowired
private AuthenticationManager authenticationManager;

@Autowired
@Qualifier("userDetailsManagerImpl")
private UserDetailsManager userDetailsManager;

....
....

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.parentAuthenticationManager(authenticationManager);
    auth.userDetailsService(userDetailsManager);
}

Also Inject the newly exposed bean in OAuth2ServerConfig and configure it like below

@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;

...
...

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
        throws Exception {
    endpoints.authenticationManager(authenticationManager)
    .setClientDetailsService(clientDetailsService);
    .tokenServices(tokenServices());

}

Hope this helps.

like image 104
FFL Avatar answered Sep 21 '22 07:09

FFL