We are trying to protect our web services using spring oauth2.0. We have created a Demo project which runs fine on below-mentioned spring version:-
spring-security-web, spring-security-config :- 4.1.5.RELEASE spring-security-oauth2 :- 2.2.0.RELEASE spring framework version: 4.2.0.RELEASE
The demo application is protecting our rest services using OAUTH2.0.
But when we start our application while loading context it throws below error.
"[ERROR ] SRVE0321E: The [springSecurityFilterChain] filter did not load during start up. Filter [springSecurityFilterChain]: could not be initialized".
Did some research and all of them point to some XML based configuration? which we would like to avoid as the same code is working on Demo application so it should work on another project as well.
Any help or clue is highly appreciated !!
web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.example.web.listener.ApplicationContextListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
<url-pattern>/example</url-pattern> <!-- For my machine only -->
</servlet-mapping>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>503</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
</web-app>
JAVA CLASSES :-
1. SecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@SuppressWarnings("deprecation")
@Bean public static NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance(); }
@Bean
@Override public AuthenticationManager authenticationManagerBean() throws
Exception { return super.authenticationManagerBean(); }
}`
2. ResourceServerConfiguration.java
@Configuration
@EnableResourceServer
public class ResourceServerConfigurations extends
ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "krsna";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId("resource-client");
tokenService.setClientSecret("123456");
tokenService
.setCheckTokenEndpointUrl("http://localhost:8090/example-web/oauth/check_token");
resources.resourceId(RESOURCE_ID).tokenServices(tokenService);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.httpBasic().disable().requestMatchers().and().authorizeRequests()
.antMatchers("/**").authenticated().and().exceptionHandling()
.accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
3. SecurityWebApplicationInitializer.java
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
4. AuthorizationServerConfiguration.java
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends
AuthorizationServerConfigurerAdapter {
public static final String RESOURCE_ID = "krsna";
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory().withClient("clientapp").secret("123456")
.authorizedGrantTypes("client_credentials")
.scopes("read", "write", "trust").resourceIds(RESOURCE_ID)
.accessTokenValiditySeconds(120).and().withClient("clientcred")
.secret("123456").authorizedGrantTypes("client_credentials")
.scopes("read", "write", "trust").resourceIds(RESOURCE_ID)
.accessTokenValiditySeconds(120).and()
.withClient("resource-client").secret("123456")
.authorizedGrantTypes("client_credentials")
.scopes("read", "write", "trust").resourceIds(RESOURCE_ID)
.accessTokenValiditySeconds(120);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.tokenStore(new InMemoryTokenStore()).authenticationManager(
authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception {
oauthServer.checkTokenAccess("permitAll()");
}
}
SECURITY-CONFIG.XML
<!-- This is default url provided by spring to get the tokens(access and refresh) from OAuth -->
<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" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- This is where we tell spring security what URL should be protected
and what roles have access to them -->
<http pattern="/users/**" 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="/users/**" access="ROLE_OAUTH_CLIENT" />
<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="sample" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sample/oauthClient" />
<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>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- Here we have hard-coded user name and password details. We can replace this with a user defined service to get users
credentials from DB -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service id="userDetailsService">
<user name="raj" password="raj@1234" authorities="ROLE_OAUTH_CLIENT" />
</user-service>
</authentication-provider>
</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.store.InMemoryTokenStore" />
<!-- tokenServices bean for defining token based configurations, token validity etc -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="120" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore"/>
<property name="requestFactory" ref="requestFactory" />
</bean>
<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="sample" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="trusted client"
authorized-grant-types="password,refresh_token,client_credentials"
authorities="ROLE_OAUTH_CLIENT" scope="read,write." resource-ids="sample" secret="secret" />
<oauth:client client-id="trusted client with secret"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="somesecret" authorities="ROLE_OAUTH_CLIENT" />
</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" />
</beans>