Spring Security - "Error: Forbidden" response from rest endpoint - spring

I'm setting up Spring Security in my project and I'm having some trouble hitting one of my rest endpoints. I receive an "Error: Forbidden" response from the server when I hit the endpoint through my client.
What I'm doing is going to the login page (I assume at this point I'm an anonymous user with ROLE_ANONYMOUS) and clicking a tab that shows me a create new account form.
When I fill out the fields and hit submit then the rest endpoint is called and the JSON data is sent to the server. In my security configuration I have posted below the endpoint url I'm using, /createUserAccount/submit, is set to work with the ROLE_ANONYMOUS and ROLE_ADMIN roles in the filterSecurityInterceptor bean xml.
Since I'm an anonymous user on the login page I thought that hitting that endpoint would work, but it's not. All the files relevant to my problem are below.
Here's my controller:
#Controller
#RequestMapping("/createUserAccount")
#SessionAttributes("userAccount")
public class CreateUserAccountController {
private final String loginViewName = "login";
private CreateUserAccountValidator validator;
private UserAccountManager userAccountManager;
#Autowired
public CreateUserAccountController(
#Qualifier("createUserAccountValidator") CreateUserAccountValidator validator,
#Qualifier("userAccountManager") UserAccountManager userAccountManager) {
this.validator = validator;
this.userAccountManager = userAccountManager;
}
#RequestMapping(value="/submit", method = RequestMethod.POST)
#ResponseBody
public GenericJsonDTO submitForm(#RequestBody UserAccount userAccount, BindingResult result, SessionStatus status){
JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard");
validator.validate(userAccount, result);
if(!result.hasErrors()) {
userAccountManager.createUserAccount(userAccount);
status.setComplete();
}
return jsonFactory.getDto();
}
}
I have my server setup so I can debug during runtime, I put a breakpoint on the line
JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard");
to see if the function is ever entered when the /createUserAccount/submit endpoint is called. The function is never entered.
Below is my security configuration. I've been starting to incorporate ACL security so the configuration file is pretty long. I think the problem is in either the http element or filterSecurityInterceptor bean configuration xml. The filterSecurityInterceptor XML is where my URI permissions are defined.
<global-method-security pre-post-annotations="enabled"
secured-annotations="enabled">
<expression-handler ref="expressionHandler" />
</global-method-security>
<http use-expressions="true">
<intercept-url pattern="/**" requires-channel="https" />
<!--<intercept-url pattern="/gravytrack/dashboard**" requires-channel="https" access="ROLE_USER"/>-->
<http-basic />
<session-management>
<concurrency-control max-sessions="10"
error-if-maximum-exceeded="true" />
</session-management>
<anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/>
</http>
<beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="passwordEncoder" />
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder ref="passwordEncoder"/>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="SELECT email, password, enabled FROM user_account
WHERE email = ?" />
</authentication-provider>
</authentication-manager>
<beans:bean id="springSecurityFilterChain"
class="org.springframework.security.web.FilterChainProxy">
<beans:constructor-arg>
<util:list>
<filter-chain pattern="/images/**" filters="" />
<filter-chain pattern="/**"
filters="securityContextPersistenceFilterWithASCFalse,
basicAuthenticationFilter,
basicExceptionTranslationFilter,
filterSecurityInterceptor" />
</util:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="securityContextPersistenceFilterWithASCFalse"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
</beans:bean>
<beans:bean id="securityContextPersistenceFilterWithASCTrue"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
</beans:bean>
<!--......................-->
<!-- basic authentication -->
<!--......................-->
<beans:bean id="basicAuthenticationFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<beans:constructor-arg name="authenticationManager">
<beans:ref bean="authenticationManager" />
</beans:constructor-arg>
<beans:constructor-arg name="authenticationEntryPoint">
<beans:ref bean="basicAuthenticationEntryPoint" />
</beans:constructor-arg>
</beans:bean>
<beans:bean id="basicAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<beans:property name="realmName" value="gravytrack.com" />
</beans:bean>
<beans:bean id="basicExceptionTranslationFilter"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<beans:constructor-arg name="authenticationEntryPoint" ref="basicAuthenticationEntryPoint" />
<beans:property name="accessDeniedHandler" ref="basicAccessDeniedHandler" />
</beans:bean>
<beans:bean id="basicAccessDeniedHandler"
class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
</beans:bean>
<!--......................-->
<!-- security -->
<!--......................-->
<beans:bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="accessDecisionManager" ref="accessDecisionManager" />
<beans:property name="securityMetadataSource">
<filter-security-metadata-source use-expressions="false">
<intercept-url pattern="/login.jsp*"
access="ROLE_ANONYMOUS,ROLE_ADMIN" />
<intercept-url pattern="/gravytrack/createUserAccount/*"
access="ROLE_ANONYMOUS,ROLE_ADMIN" />
<intercept-url pattern="/images/**"
access="ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN" />
<intercept-url pattern="/admin.htm*" access="ROLE_ADMIN" />
<intercept-url pattern="/**"
access="ROLE_USER,ROLE_ADMIN" />
</filter-security-metadata-source>
</beans:property>
</beans:bean>
<beans:bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg name="decisionVoters">
<beans:list>
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
<beans:bean
class="org.springframework.security.access.vote.AuthenticatedVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="permissionEvaluator" />
</beans:bean>
<beans:bean id="permissionEvaluator"
class="org.springframework.security.acls.AclPermissionEvaluator">
<beans:constructor-arg ref="aclService" />
</beans:bean>
<beans:bean id="aclService"
class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<beans:constructor-arg ref="dataSource" />
<beans:constructor-arg ref="lookupStrategy" />
<beans:constructor-arg ref="aclCache" />
<beans:property name="sidIdentityQuery"
value="SELECT max(id) FROM acl_sid" />
<beans:property name="classIdentityQuery"
value="SELECT max(id) FROM acl_class" />
<!--
<beans:property name="sidIdentityQuery"
value="select currval(pg_get_serial_sequence('acl_sid', 'id'))" />
<beans:property name="classIdentityQuery"
value="select currval(pg_get_serial_sequence('acl_class', 'id'))" />
-->
</beans:bean>
<beans:bean id="consoleAuditLogger" class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
<beans:bean id="lookupStrategy"
class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<beans:constructor-arg ref="dataSource" />
<beans:constructor-arg ref="aclCache" />
<beans:constructor-arg ref="aclAuthorizationStrategy" />
<beans:constructor-arg ref="consoleAuditLogger"/>
</beans:bean>
<beans:bean id="aclAuthorizationStrategy"
class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<beans:constructor-arg>
<beans:list>
<beans:bean
class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<beans:constructor-arg value="ROLE_ADMIN" />
</beans:bean>
<beans:bean
class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<beans:constructor-arg value="ROLE_ADMIN" />
</beans:bean>
<beans:bean
class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<beans:constructor-arg value="ROLE_ADMIN" />
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<beans:constructor-arg ref="consoleAuditLogger"/>
</beans:bean>
<beans:bean id="aclCache"
class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
<beans:constructor-arg>
<beans:bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<beans:property name="cacheManager">
<beans:bean
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
</beans:property>
<beans:property name="cacheName" value="aclCache" />
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg ref="permissionGrantingStrategy" />
<beans:constructor-arg ref="aclAuthorizationStrategy" />
</beans:bean>
</beans:beans>
Last but not least here's my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Log4j configuration loading -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j.xml</param-value>
</context-param>
<!-- Bootstrapping context loading -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/gravytrack-servlet.xml
/WEB-INF/gravytrack-services.xml
/WEB-INF/gravytrack-security.xml
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>gravytrack.root</param-value>
</context-param>
<!-- session management listener -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<session-config>
<!-- session times out if no activities for 30 minutes -->
<session-timeout>30</session-timeout>
</session-config>
<!-- defining the DispatcherServlet -->
<servlet>
<servlet-name>gravytrack</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>gravytrack</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<!--<servlet-mapping>-->
<!--<servlet-name>gravytrack</servlet-name>-->
<!--<url-pattern>*.html</url-pattern>-->
<!--</servlet-mapping>-->
<!-- Security entry point -->
<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>
<!-- webflow -->
<!--
<servlet-mapping>
<servlet-name>soba</servlet-name>
<url-pattern>/flow/*</url-pattern>
</servlet-mapping>
-->
<!-- defining the DefaultServlet -->
<servlet>
<servlet-name>DefaultServlet</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>DefaultServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/notfound.jsp</location>
</error-page>
<welcome-file-list>
<welcome-file>
login.jsp
</welcome-file>
</welcome-file-list>
<!-- Spring jsp tag lib -->
<jsp-config>
<taglib>
<taglib-uri>/spring</taglib-uri>
<taglib-location>/WEB-INF/tld/spring-form.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
I'm having a hard time trying to figure out what's wrong so any help is greatly appreciated.

By default Spring security enables CSRF and every POST request as it expects a csrf token.
Check the Spring CSRF documentation..
You can switchoff CSRF like this in your config to test already if it's the problem
<http auto-config="false">
<csrf disabled="true"/>
if you dont want to switchoff CSRF, you must POST the csrf tokens like this
<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" />
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>

Related

Spring with jersey and oauth security giving 404: Not Found error for REST API

I am implementing OAuth2 with spring, getting access_token but when i call Rest API along with access_token it gives 404: Not Found error.
Web.xml file
<?xml version="1.0" encoding="ISO-8859-1"?>
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
Restful Web Application
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context.xml</param-value>
<param-value>classpath:spring-security-oauth2.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.dpdocter.webservices;com.dpdocter.beans</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-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></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>
<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>
spring-secuirty-oauth2.xml file
<?xml version="1.0" encoding="UTF-8" ?>
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager" xmlns="">
<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>
<http pattern="/api/**" create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager" xmlns="">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" />
<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="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/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>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<!-- This is simple authentication manager, with a hardcoded user/password
combination. We can replace this with a user defined service to get few users
credentials from DB -->
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="java" password="java" authorities="ROLE_APP" />
</user-service>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- This defined token store, we have used inmemory tokenstore for now
but this can be changed to a user defined one -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<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="12000000" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</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="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="restapp"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp"
authorized-grant-types="authorization_code,password,refresh_token,implicit"
secret="restapp" scope="read,write,trust" authorities="ROLE_APP" />
</oauth:client-details-service>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />
Here **/api/**** is path for my REST API.
Getting Token :
http://localhost:8080/myapp/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=java&password=java
Response : {"access_token":"21e165a4-0df9-4452-9e1e-491025b6cf9b","token_type":"bearer","refresh_token":"e5afd74f-5e28-4879-b066-e672fade2ec3","expires_in":11999999,"scope":"read trust write"}
But when calling API
http://localhost:8080/myapp/api/getList?access_token=21e165a4-0df9-4452-9e1e-491025b6cf9b
Gives 404 Not found error

Application Controllers getting called before custom RememberMeAuthenticationFilter

We are trying to implement Spring security in our application. We are extending RememberMeAuthenticationFilter. But trouble is that our application Controllers are getting called before RememberMeAuthenticationFilter. Is there anyway to force RememberMeAuthenticationFilter to be called before application Controllers?
Below are my configuaations. In debug mode I could see that FilterChainProxy.VirtualFilterChain has two sets of filters - original filters and additional filters. Original filters has springSecurityFilterChain but it doesn't call custom RememberMeAuthenticationFilter. And additional filters has RememberMeAuthenticationFilter. Controller is getting called via DispatcherServlet at the end of original filters.
Web.xml
<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>
spring-security-context.xml
<http use-expressions="true" auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint" create-session="ifRequired" >
<long list of intercept-url here>
<intercept-url pattern="/**" access="permitAll" requires-channel="any"/>
<custom-filter ref="rememberMeProcessingFilter" position="REMEMBER_ME_FILTER" />
<custom-filter ref="authenticationProcessingFilter" position="FORM_LOGIN_FILTER" />
</http>
<beans:bean id="rememberMeProcessingFilter" class="uk.co.and.dealofday.security.SecurityRememberMeAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="rememberMeServices" ref="rememberMeServices" />
</beans:bean>
<beans:bean id="authenticationProcessingFilter" class="uk.co.and.dealofday.security.SecurityUsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="rememberMeServices" ref="rememberMeServices" />
<beans:property name="userService" ref="userService"/>
<beans:property name="securityHelper" ref="securityHelper" />
</beans:bean>
declare custom remember filter after custom authentication filter
<custom-filter ref="authenticationProcessingFilter" position="FORM_LOGIN_FILTER" />
<custom-filter ref="rememberMeProcessingFilter" position="REMEMBER_ME_FILTER" />

Spring Security Oauth2 Resource Owner Password flow: When I send a REST request, my user detail service always gets the client id instead of username

So I'm trying to send a request to my oauth server (with no headers): grant_type=password&username=blah&password=blah&client_id=blahblah.
I have 2 authentication-manager (one for the client and another for the user validation). The problem is, none of my authentication managers are being passing the username to verify. In both cases, they are being called with the client_id. What I want is one to verify the client and the other to verify the user.
My bean configuration is this:
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="ROLE_USER" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/api/**" create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/api" access="ROLE_USER,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
<sec:authentication-provider user-service-ref="customUserDetailService">
<sec:password-encoder ref="passwordEncoder" />
</sec:authentication-provider>
</authentication-manager>
<beans:bean id="customUserDetailService" class="com.cointraders.api.securities.UserDetailsServiceImpl" />
<beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:refresh-token />
<oauth:password authentication-manager-ref="authenticationManager" />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="api" token-services-ref="tokenServices" />
<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:bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="api/" />
</beans:bean>
<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="api" />
</beans:bean>
This is my Web.XML
<!-- 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>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My User Detail Service Class
public class UserDetailsServiceImpl extends PersonServiceImpl implements
UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserDetails details = null;
Specification<Person> specs = Specifications.where(PersonSpecification.equalsUserName(username));
Person person = this.personRepository.findOne(specs);
if(person!=null)
{
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(person.getRole().getRole().name()));
details = new User(person.getUserName(), person.getPassword(), person.getActive(), false, false, false, authorities);
}
return details;
}
}
In your <authorization-server/> you haven't set the AuthenticationManager in the <password/> grant type (so it is using the default bean name "authenticationManager" which you have mapped to the client credentials).
An additional problem is that you use <authentication-manager/> twice without giving an explicit "id=" for either, which actually has the effect of defining only one AuthenticationManager since the second one overrides the first (they both have the same id). Try using "id=" instead of "alias=".
You really need to send the client credentials in a header if you can (but you probably know that).

oauth2 spring security over RESTEasy API's

I am trying to secure my rest services by Oauth 2.0 spring security. I google for the same and got some example on it. I tried one example with the help of google and able to generate access_token. But when I am going to access my protected resource it becomes accessible without passing any access_token, instead it should show some authorization error message.
What I am missing here???
URL to receive authorization code:
http://localhost:8080/springsecurity-oauth2-POC/oauth/token?grant_type=password&client_id=my-trusted-client-with-secret&client_secret=somesecret&username=marissa&password=koala
got the token like,
{"access_token":"64ee1cf7-2445-40d8-86a5-c4900b47db9e","token_type":"bearer","refresh_token":"e7c7bce1-35db-4879-a2de-e6690f8d482d","expires_in":299969}
Resource URL
http://localhost:8080/springsecurity-oauth2-POC/resources/MyResource/getMyInfo
As it doesn't contain any token but still I am able to access it.
My spring-servlet.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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd ">
<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" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block so we can deal with authorization and error handling
separately. This isn't mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/resources/*" 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="/resources/*" access="ROLE_USER" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/logout" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/logout" method="GET" />
<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="logoutSuccessHandler" class="demo.oauth2.authentication.security.LogoutImpl" >
<property name="tokenstore" ref="tokenStore"></property>
</bean>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<!-- <property name="realmName" value="springsec/client" /> -->
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<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>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<!-- <authentication-provider user-service-ref="clientDetailsUserService" /> -->
<authentication-provider>
<user-service id="userDetailsService">
<user name="marissa" password="koala" authorities="ROLE_USER" />
<user name="paul" password="emu" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- Used for the persistenceof tokens (currently an in memory implementation) -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<!-- Used to create token and and every thing about them except for their persistence that is reposibility of TokenStore (Given here is a default implementation) -->
<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="300000"></property>
<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">
<oauth:client client-id="my-trusted-client" authorized-grant-types="password,authorization_code,refresh_token,implicit"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" access-token-validity="60" />
<oauth:client client-id="my-trusted-client-with-secret" authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" />
<oauth:client client-id="my-client-with-secret" authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read" secret="secret" />
<oauth:client client-id="my-less-trusted-client" authorized-grant-types="authorization_code,implicit"
authorities="ROLE_CLIENT" />
<oauth:client client-id="my-less-trusted-autoapprove-client" authorized-grant-types="implicit"
authorities="ROLE_CLIENT" />
<oauth:client client-id="my-client-with-registered-redirect" authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_CLIENT" redirect-uri="http://anywhere?key=value" scope="read,trust" />
<oauth:client client-id="my-untrusted-client-with-registered-redirect" authorized-grant-types="authorization_code"
authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" />
<oauth:client client-id="tonr" resource-ids="test" authorized-grant-types="authorization_code,implicit"
authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
<!--Self defined 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-details-service>
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<mvc:annotation-driven /> <!-- Declares explicit support for annotation-driven MVC controllers #RequestMapping, #Controller -->
<mvc:default-servlet-handler />
</beans>
My Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>Spring Secure REST</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>RESTService</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>RESTService</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
My Resource class contains
package demo.oauth2.authentication.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
#Path("/MyResource")
public class MyResource {
#GET
#Path("/createInfo")
public String createInfo(){
return "\n\n\t!!!Protected Resource(createInfo) Accessed !!!! Returning from Myresource createInfo\n";
}
#GET
#Path("/getMyInfo")
public String getMyInfo(){
return "\n\n\t Protected Resource(getMyInfo) Accessed !!!! Returning from Myresource getMyInfo\n";
}
#GET
#Path("/updateInfo")
public String updateMyInfo(){
return "\n\n\t Protected Resource(updateInfo) Accessed !!!! Returning from Myresource updateInfo\n";
}
}
Try double asterisk in:
<http pattern="/resources/**"
instead of
<http pattern="/resources/*"
Hope it helps.
I see you're using same code from http://www.e-zest.net/blog/rest-authentication-using-oauth-2-0-resource-owner-password-flow-protocol/ site. If yes, then you need to use following code also
<http pattern="/resources/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/resources/**" method="GET" />
<intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
I was also facing the same, issue until you don't add above xml configuration, I'm also using same code and it works for me!!
I've perform testing and attached the screen shots for your reference.
In this case, I'm not passing token value, and it gives me expected error
Now, I'm passing value of "access_token" and it's giving me protected resources.
Hope this will be help you..

Spring Security 3.0.5 Concurrency is not working

Hi I am using Spring Security 3.0.5 with Spring Framework 3.0.6. I have configured concurrency as per the documentation. It is not working. I login to the application from a browser session and then attemp to login again from another tab in the same browser - it lets me log in instead of denying the attempt.
Here is my security config file:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http auto-config="false" use-expressions="true"
access-denied-page="/jsp/accessDenied.jsp"
entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/login.jsp" filters="none" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<logout invalidate-session="true" logout-url="/logout.htm"
logout-success-url="/login.jsp?loggedout=true"/>
<custom-filter ref="authenticationFilter"
position="FORM_LOGIN_FILTER"/>
<custom-filter ref="concurrencyFilter"
position="CONCURRENT_SESSION_FILTER"/>
<session-management session-authentication-strategy-ref="sas"/>
</http>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy" ref="sas"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="customAuthenticationFailureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="customAuthenticationSuccessHandler"/>
</beans:bean>
<beans:bean id="customAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.jsp?authfailed=true"/>
</beans:bean>
<beans:bean id="customAuthenticationSuccessHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/index.jsp" />
</beans:bean>
<beans:bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.jsp"/>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"
id="passwordEncoder"/>
<user-service id="userDetailsService">
<user name="username" password="ee11cbb19052e40b07aac0ca060c23ee"
authorities="ROLE_USER, ROLE_ADMIN" />
<user name="test" password="21232f297a57a5a743894a0e4a801fc3"
authorities="ROLE_USER" />
</user-service>
<beans:bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<beans:property name="sessionRegistry" ref="sessionRegistry"/>
<beans:property name="expiredUrl" value="/login.jsp?loggedout=true" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:property name="maximumSessions" value="1" />
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
Here is my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<display-name>Spring security web application (series)</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>
<!--
- Loads the root application context of this web app at startup. - The
application context is then available via -
WebApplicationContextUtils.getWebApplicationContext(servletContext).
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher</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>springsecuritywebapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springsecuritywebapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Regards,
Nazir
Add <beans:property name="exceptionIfMaximumExceeded" value="true" /> to org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy bean definition. It will throw exception if allowed sessions are exceeded.
This will have a side effects. Suppose user logged in a browser and close the browser which clears session data. Then the user has to wait for session in server to expire before allowed to login again.I prefer your existing configuration to this unless you have explicit requirement.

Resources