Spring oauth2 ver 2.0.7, 404 error on endpoint /oauth/token - spring

I got problem when try to integrate our web app with Spring oauth2
the end point /oauth/token is mapped for both GET and POST method
o.s.s.o.p.e.FrameworkEndpointHandlerMapping- Mapped "{[/oauth/token],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.getAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
o.s.s.o.p.e.FrameworkEndpointHandlerMapping- Mapped "{[/oauth/token],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map<java.lang.String, java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException
when access: https://192.168.70.19:8072/oauth/token?grant_type=password&client_id=7CA42EA39288EC73212716FC6A51B8A2&username=admin&password=switch
**server return:**Bad client credentials
its ok, however when I add the client_secret
https://192.168.70.19:8072/oauth/token?grant_type=password&client_id=7CA42EA39288EC73212716FC6A51B8A2&client_secret=client_secret&username=admin&password=switch
server return 404 error (as I know this should happen when the API is not mapped only)
Some of my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
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">
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder" />
<property name="targetMethod" value="setStrategyName" />
<property name="arguments">
<list>
<value>MODE_INHERITABLETHREADLOCAL</value>
</list>
</property>
</bean>
<bean id="authenticationEntryPoint"
class="com.alu.ov.ngnms.appserver.login.AuthenticationEntryPoint">
<constructor-arg name="loginUrl" value="/login.html" />
</bean>
<bean name="customUserDetailsAuthenticationProvider" class="com.alu.ov.ngnms.appserver.login.CustomUserDetailsAuthenticationProvider">
<property name="aaaServerRepository" ref="AAAServerRepository"></property>
</bean>
<security:authentication-manager alias="authenticationManager"
erase-credentials="false">
<security:authentication-provider ref="customUserDetailsAuthenticationProvider" />
</security:authentication-manager>
<bean id="checkTokenEndPoint"
class="org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint">
<constructor-arg name="resourceServerTokenServices" ref="tokenServices"/>
</bean>
<bean id="customAccessDeniedHandler"
class="com.alu.ov.ngnms.appserver.login.CustomAccessDeniedHandler"></bean>
<security:http pattern="/oauth/token" create-session="stateless" entry-point-ref="authenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager">
<security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<security:anonymous enabled="false" />
<security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="customAccessDeniedHandler" />
</security:http>
<security:http use-expressions="true" entry-point-ref="authenticationEntryPoint" create-session="never">
<!-- for all users (login & non-login) -->
<security:intercept-url pattern="/favicon.ico" access="permitAll" />
<security:intercept-url pattern="/bower_components/**" access="permitAll"/>
<security:intercept-url pattern="/locales/**" access="permitAll"/>
<security:intercept-url pattern="/ov_components/**" access="permitAll"/>
<security:intercept-url pattern="/scripts/**" access="permitAll"/>
<security:intercept-url pattern="/styles/**" access="permitAll"/>
<security:intercept-url pattern="/template/**" access="permitAll" />
<security:intercept-url pattern="/webstart/classes/**" access="permitAll" />
<security:intercept-url pattern="/assets/**" access="permitAll" />
<!-- only for non-login users -->
<security:intercept-url pattern="/login.html" access="!isAuthenticated()" />
<security:intercept-url pattern="/upgrade.html" access="!isAuthenticated()" />
<security:intercept-url pattern="/api/login" access="!isAuthenticated()" />
<!-- for all login users -->
<!-- only for admin user & no-license OV -->
<security:intercept-url pattern="/noLicense.html" access="hasAnyRole('ROLE_ADMIN_NO_LICENSE')" />
<security:intercept-url pattern="/**" access="isAuthenticated() and !hasRole('ROLE_ADMIN_NO_LICENSE')" />
<security:access-denied-handler ref="customAccessDeniedHandler"/>
<!-- Add filter to extract access token from request and perform authentication -->
<security:custom-filter ref="customOAuth2AuthenProcessingFilter" before="PRE_AUTH_FILTER" />
<security:expression-handler ref="oauthWebExpressionHandler" />
</security:http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<security:global-method-security authentication-manager-ref="authenticationManager" pre-post-annotations="enabled"
secured-annotations="enabled">
</security:global-method-security>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<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="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices" >
<property name="tokenStore" ref="mongoDBTokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
<!-- Access token & Refresh token will be expired in 1 year 1 second after being granted -->
<property name="accessTokenValiditySeconds" value="31536001"></property>
<property name="refreshTokenValiditySeconds" value="31536001"></property>
</bean>
<bean id="ovTokenExtractor" class="com.alu.ov.ngnms.appserver.login.OVTokenExtractor"></bean>
<bean id="oauth2AuthenticationManager" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager">
<property name="tokenServices" ref="tokenServices"></property>
</bean>
<bean id="customOAuth2AuthenProcessingFilter" class="org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter">
<property name="authenticationEntryPoint" ref="authenticationEntryPoint"></property>
<property name="authenticationManager" ref="oauth2AuthenticationManager"></property>
<property name="tokenExtractor" ref="ovTokenExtractor"></property>
</bean>
<bean id="clientDetails" class="com.alu.ov.ngnms.appserver.token.CustomClientDetailsService"/>
<security: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 -->
<security:expression-handler ref="oauthExpressionHandler" />
</security:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
</beans>
--------EDIT 1--------
added web.xml:
<servlet>
<servlet-name>atmoSpring</servlet-name>
<servlet-class>org.atmosphere.cpr.MeteorServlet</servlet-class>
<init-param>
<!-- When MeteorServlet is used, this is the parameter that will be looked
and all requests will be delegated to this servlet, Of course, since we are
using, Spring MVC, we delegate to DispatcherServlet -->
<param-name>org.atmosphere.servlet</param-name>
<param-value>org.springframework.web.servlet.DispatcherServlet</param-value>
</init-param>
<!-- Bunch of Atmosphere specific properties -->
<init-param>
<param-name>org.atmosphere.cpr.broadcasterClass</param-name>
<param-value>org.atmosphere.cpr.DefaultBroadcaster</param-value>
</init-param>
<!-- Set Atmosphere to use the container native Comet support. -->
<init-param>
<param-name>org.atmosphere.useNative</param-name>
<param-value>true</param-value>
</init-param>
<!-- Force Atmosphere to use stream when writing bytes. -->
<init-param>
<param-name>org.atmosphere.useStream</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>org.atmosphere.interceptor.SSEAtmosphereInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.interceptor.SSEAtmosphereInterceptor.contentType</param-name>
<param-value>text/event-stream</param-value>
</init-param>
<!-- Use this interceptor to prevent firewall/proxies from canceling the
connection after a specific idle time -->
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor</param-name>
<param-value>org.atmosphere.interceptor.HeartbeatInterceptor</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.interceptor.HeartbeatInterceptor.heartbeatFrequencyInSeconds</param-name>
<param-value>30</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.useWebSocketAndServlet3</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.AtmosphereInterceptor.disableDefaults</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.broadcasterCacheClass</param-name>
<param-value>org.atmosphere.cache.UUIDBroadcasterCache</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.broadcaster.shareableThreadPool</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.cpr.sessionSupport</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>atmoSpring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/webContext.xml</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
<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>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ASYNC</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<filter>
<filter-name>cacheControlFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>cacheControlFilterChain</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<!-- Session Listener for Webstart -->
<listener>
<listener-class>com.alu.ov.ngnms.appserver.controller.SessionListener</listener-class>
</listener>

You can't define the Authorization Server endpoints in a ContextLoaderListener. I don't really know how that MeteorServlet works, but you have to get the configuration into the DispatcherServlet so it can handle the "/oauth/token" requests (the handler is created by the <authorization-server/> declaration).

I also got 404 on /servlet/oauth/token requests. In my case I had the DispatcherServlet mapped to /servlet/*, instead of /* in the web.xml file. I had to update the AuthorizationServerConfigurerAdapter to use a prefix, so that both the authorization filter and the request mapping handler adapter can handle the oauth requests (ie: /servlet/oauth/token for me)
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.prefix("/servlet").authenticationManager(authenticationManager);
}
It was also important to set the DispatcherWebApplicationContextSuffix in the AbstractSecurityWebApplicationInitializer to reference the Dispatcher servlet name from web.xml file.

Related

Spring security XML configuration not protecting URLs

I have gone through a lot of questions similar to this but I couldn't find any solution.
I am using Spring-3.0.5RELEASE and Spring-security-3.1.2RELEASE.
Actually I am adding spring security to already exixsting application.
There are no errors in creating bean or filters but the urls are not protected.
spring-security.xml looks like this:
<?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:security="http://www.springframework.org/schema/security"
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-3.1.xsd">
<security:http auto-config="true" use-expressions="true">
<!-- <intercept-url pattern="/" access="permitAll" /> -->
<security:intercept-url pattern="/index" access="permitAll" />
<security:intercept-url pattern="/admin"
access="hasRole('Admin')" />
<security:intercept-url pattern="/dashboard" access="hasRole('Admin')
or hasRole('User')" />
<security:intercept-url pattern="/setup" access="hasRole('User')" />
<!-- access denied page -->
<security:access-denied-handler error-page="/logout" />
<security:form-login
login-processing-url="/loginAuth"
login-page="/index"
default-target-url="/dashboard"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/index"/>
<!-- enable csrf protection -->
<!-- <csrf/> -->
<http-basic />
</security:http>
<!-- Select users and user_roles from database -->
<security:authentication-manager>
<security:authentication-provider>
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select customerId, passcode from Users where customerId=?"
authorities-by-username-query=
"select customerId, roleName from Role where customerId=?" />
</security:authentication-provider>
</security:authentication-manager>
</beans:beans>
There is a warning here saying: Referenced bean 'dataSource' not found. I am not sure whether this may cause the problem.
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"
version="2.5">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<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>sample</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/sample-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/spring-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
sample-servlet.xml
<context:property-placeholder location="classpath:resources/database.properties" />
<context:component-scan base-package="com.as.spark" />
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.as.spark.model.Users</value>
<value>com.as.spark.model.Role</value>
</list>
</property>
<property name="hibernateProperties">
<!-- properties -->
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
I don't want to shift to java configuration because that requires a higher version of spring.
All the pages /home, /dashboard, /admin are open to all users.
How do I check whether the filter is applied? How to protect the URL?

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

Securing REST API using Spring-security #PreAuthorize annotation and OAuth2

I'm struggling with some spring-security OAuth2 configuration.
I'm using:
Spring.version: 4.0.5.RELEASE
Spring security version: 3.2.5.RELEASE
Spring security oauth version: 2.0.2.RELEASE
Jersey version: 1.18.1
I want to secure my REST API using the PreAuthorize annotation of Spring security where I define the role that is authorized to access the method:
#Transactional
#POST
#PreAuthorize("hasRole('ROLE_ADMIN')")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response create(User user) throws BusinessException {
LOG.info("POST Request: Creation of a new user with username [{}]", user.getUsername());
UserValidator.validateUser(user);
User createdUser = userDao.create(user);
return Response.ok(createdUser).build();
}
When I call the API method with a valid bearer token for a user with role "ROLE_ADMIN", I get following exception:
09-Sep-2014 16:13:40.977 SEVERE [http-nio-8080-exec-6] com.sun.jersey.spi.container.ContainerResponse.mapMappableContainerException The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
at org.springframework.security.access.vote.UnanimousBased.decide(UnanimousBased.java:107)
at ...
When using postman, I see the following error description:
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
This is my security config:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">
<context:property-placeholder location="classpath:main.properties"/>
<sec:global-method-security pre-post-annotations="enabled" />
<oauth:expression-handler id="oauthExpressionHandler" />
<!-- Definition of the Authentication Service -->
<sec:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY"/>
<sec:anonymous enabled="false"/>
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<!-- include this only if you need to authenticate clients via request parameters -->
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
<sec:access-denied-handler ref="oauthAccessDeniedHandler"/>
</sec:http>
<!-- Protected resources -->
<sec:http auto-config="true"
entry-point-ref="oauthAuthenticationEntryPoint"/>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="dstest" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="dstest/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">
<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 in config file -->
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService"/>
</sec:authentication-manager>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider>
<sec:jdbc-user-service data-source-ref="securityDataSource"/>
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<!-- Token Store -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="securityDataSource" />
</bean>
<bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails"/>
</bean>
<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"/>
<!-- VIV -->
<property name="accessTokenValiditySeconds" value="10"/>
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore"/>
<property name="requestFactory" ref="oAuth2RequestFactory"/>
</bean>
<!-- Token management -->
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler" token-endpoint-url="/oauth/token">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="dstest"
token-services-ref="tokenServices"/>
<!-- Client Definition -->
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="healthdata-client"
authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT"
redirect-uri="/web"
scope="read,write,trust"
access-token-validity="300"
refresh-token-validity="6000"/>
</oauth:client-details-service>
</beans>
And this is my web.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<display-name>Spring MVC Application BASIC AUTH</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
/WEB-INF/rest-dispatcher-servlet.xml
/WEB-INF/security.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>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>rest-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest-dispatcher</servlet-name>
<url-pattern>/oauth/token</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Spring servlets</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>be.spring.security.api</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>be.spring;org.codehaus.jackson.jaxrs</param-value>
</init-param>
<!-- optional: JSON support apart from jaxb -->
<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>Spring servlets</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I found the solution to my problem. Web security services are configured using the element and I had to alter my protected resource definition from:
<sec:http auto-config="true"
entry-point-ref="oauthAuthenticationEntryPoint"/>
to:
<sec:http auto-config="true">
<sec:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER"/>
<sec:access-denied-handler
ref="oauthAccessDeniedHandler"/>
</sec:http>
The resourceServerFilter must be referenced in order to be picked up by the security mechanism and the before attribute had to be set to "PRE_AUTH_FILTER".
Also the access-denied-handler is needed if you want proper error handling in a JSON format in the case you can't access the service.

404 Error on /spring_security_login Spring Security 3.2 after migrating from Tomcat 6 to Tomcat 7

It's been now three days that I'm battling to make my application work again.
The pitch : I had an application using Spring Security 3.2 and running well on Tomcat 6.
I want to migrate all my apps on Tomcat 7, so that's why I'm trying that.
BUT : every time I access to the root of my app, I get a 404 error page, with /spring_security_login written in the URL.
For the /spring_security_login written, it seems partially legit, because Spring is set to create the login form on its own. But why the 404 error ?
On Tomcat 6, with the same web.xml and applicationContext-security, the site is running well.
Last but not least, my login is made through the Spring Security ldap provider, so it adds one more level of complexity...
Here is 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>MYAPP</display-name>
<!-- où se trouve la conf spring: -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-security.xml</param-value>
</context-param>
<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>
<!-- Reads request input using UTF-8 encoding -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- configuration spring -->
<servlet>
<servlet-name>myapp-webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myapp-webapp</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/myapp_database</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
And my applicationContext-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:s="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<s:global-method-security secured-annotations="disabled">
</s:global-method-security>
<s:http pattern="/styles/**" security="none"/>
<s:http pattern="/js/**" security="none"/>
<s:http pattern="/img/**" security="none"/>
<s:http pattern="/html/**" security="none"/>
<s:http pattern="/remoting/**" security="none"/>
<!-- config ldap activee use-expressions="true" -->
<s:http auto-config="true" create-session="always" access-decision-manager-ref="accessDecisionManager">
<s:intercept-url pattern="/cancelPreviousAction.do" access="P_MYAPP_RW" />
<s:intercept-url pattern="/**" access="P_MYAPP_RO" />
<s:session-management>
<s:concurrency-control max-sessions="1" />
</s:session-management>
<s:form-login />
<s:logout/>
</s:http>
<s:authentication-manager>
<s:authentication-provider ref="ldapProvider"></s:authentication-provider>
</s:authentication-manager>
<bean id="contextSource"
class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
<constructor-arg value="..." />
<property name="userDn" value="..." />
<property name="password" value="..." />
</bean>
<bean id="ldapProvider" class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource" />
<property name="userSearch">
<bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="..." />
<constructor-arg index="1" value="..." />
<constructor-arg index="2" ref="..." />
</bean>
</property>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<constructor-arg ref="contextSource" />
<constructor-arg value="..." />
<property name="rolePrefix" value="" />
<property name="searchSubtree" value="true" />
<property name="convertToUpperCase" value="false" />
</bean>
</constructor-arg>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<property name="decisionVoters">
<bean class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value=""/>
</bean>
</property>
</bean>
</beans>
Anybody has a clue ?
I though one time that it might be my Tomcat conf that would be the cause, but now when I call the root url of my app, the /spring_security_login appends itself in the url, so I think the redirection inside Spring Seuciryt works well...
NB : When I remove the spring Security filter from the web.xml file, the app works well (except the login/security part needless to say).
Thanks in advance !
In fact the problem was that under Tomcat 6, I had overrided the definition of the default servlet.
After having searched long times and long times, I tried commenting the default servlet definition... and everything worked.
So in web.xml, comment the following lines to have the same :
<!--
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.gif</url-pattern>
</servlet-mapping> -->
And it fixed everything.

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