Spring Security Concurrency Control not working in Spring 4.0.4 - spring

I try to implement concurrency-control in Spring security 4.0.4 I use form-login for auth. Here is my security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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-4.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd ">
<security:http auto-config="true" >
<security:custom-filter ref="myFilter" before="FORM_LOGIN_FILTER"/>
<security:intercept-url pattern="/Welcome**" access="hasRole('ROLE_USER')" />
<security:intercept-url pattern="/admin**" access="hasRole('ADMINISTRATOR')"/>
<security:intercept-url pattern="/Welcome**" access="isAuthenticated()"/>
<security:intercept-url pattern="/hello" access="isAuthenticated()"/>
<security:intercept-url pattern="/logout" access="isAnonymous()"/>
<security:intercept-url pattern="/student" access="hasRole('STUDENT')"/>
<security:intercept-url pattern="/failurl" access="hasRole('STUDENT1')"/>
<security:session-management invalid-session-url="/access" session-fixation-protection="newSession" >
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" expired-url="/access"/>
</security:session-management>
<security:logout logout-success-url="/access" delete-cookies="JSESSIONID" />
<security:form-login login-processing-url="/j_spring_security_check"
login-page="/access"
default-target-url="/hello"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/fail"
/>
<security:logout logout-url="/j_spring_security_logout" logout-success-url="/logout"/>
<security:csrf />
</security:http>
<bean id="myFilter" class="com.www.sec.MyFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider>
<!-- <security:password-encoder hash="sha-256"/> -->
<security:jdbc-user-service data-source-ref="dataSource"
users-by-username-query=
"select username,password,enabled from user_details where username=?"
authorities-by-username-query=
"select username,user_role from user_role where username =?" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
Listener:
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
when we run it in different browsers, log in in both but I have 2 sessions active. It seems that concurrency control doesn't work.
How to implement concurrency control with using form-login?

Related

Request Matcher not resolved while migrating spring security from 3 to 4

I am migrating my spring security from 3.1.4 to 4.1.5. I am using RequestMatcher in my security config to filter out urls.I updated RequestMatcher to the correct package as suggested in Migration document to org.springframework.security.web.util.matcher.RequestMatcher.
I am pointing request-matcher-ref in to point the a custom class which implements RequestMatcher. But i am getting the following error in intellij - Cannot resolve required base class 'org.springframework.security.web.util.RequestMatcher'.
How to resolve this issue.
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:security="http://www.springframework.org/schema/security"
xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<security:debug/>
<bean id="preflightRequestMatcher" class="com.genesyslab.rcs.security.RequestMethodMatcher">
<constructor-arg index="0" value="OPTIONS"/>
<constructor-arg index="1" value="true"/>
</bean>
<bean id="regularRequestMatcher" class="com.genesyslab.rcs.security.RequestMethodMatcher">
<constructor-arg index="0" value="OPTIONS"/>
<constructor-arg index="1" value="false"/>
</bean>
<security:http auto-config="false" create-session="never" request-matcher-ref="preflightRequestMatcher" >
<security:intercept-url pattern="/**" access="ROLE_ANONYMOUS, IS_AUTHENTICATED_FULLY"/>
<security:http-basic />
</security:http>
<security:http pattern="/contact-centers/*/user-recordings/*/play/**" security="none" auto-config="false" create-session="always"/>
<security:http pattern="/contact-centers/*/user-screen-recordings/*/play/**" security="none" auto-config="false" create-session="always"/>
<security:http auto-config="false" create-session="always" request-matcher-ref="regularRequestMatcher">
<security:intercept-url pattern="/loginsession" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/logoutsession" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/keepalivesession" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/recordings/**" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/contact-centers/*/recordings/**" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/screen-recordings/**" access="IS_AUTHENTICATED_FULLY" />
<security:intercept-url pattern="/certificates" access="ROLE_RECORD_KEY_READ,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/certificatepems" access="ROLE_RECORD_KEY_READ,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/checkcertificate" access="ROLE_RECORD_KEY_UPLOAD,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/checkkey" access="ROLE_RECORD_KEY_UPLOAD,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/addcertificateandkey" access="ROLE_RECORD_KEY_UPLOAD,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/removecertificateandkey" access="ROLE_RECORD_KEY_UPLOAD,ROLE_DEFAULT_USER" />
<security:intercept-url pattern="/version" access="ROLE_ANONYMOUS, IS_AUTHENTICATED_FULLY" />
<!-- All URLs should be covered above, it's error if we match this one -->
<security:intercept-url pattern="/**" access="ROLE_NOMATCH" />
<security:session-management>
<security:concurrency-control max-sessions="999999" error-if-maximum-exceeded="false"/>
</security:session-management>
<security:http-basic />
</security:http>
<security:authentication-manager>
<security:authentication-provider ref='rcsAuthenticationProvider'/>
</security:authentication-manager>
RequestMethodMatcher.java
import lombok.AllArgsConstructor;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.servlet.http.HttpServletRequest;
#AllArgsConstructor
public class RequestMethodMatcher implements RequestMatcher
{
final private String method;
final private boolean matchIfEqual;
#Override
public boolean matches(HttpServletRequest request) {
return method.equalsIgnoreCase(request.getMethod()) == matchIfEqual;
}
}

Multiple spring security configuration not working

In my application i want to have separate spring security implementation based on url patterns.
Eg. /rest/ ** will have its own authentication provider(basic auth) and
/web/ ** will have its own authentication provider(form login).
please find below configuration i have done
<?xml version="1.0"?>
<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.xsd">
<!-- config for rest services using basic auth-->
<http pattern="/rest/**">
<intercept-url pattern="/MyAppRestServices" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<http-basic />
</http>
<!-- AUTHENTICATION MANAGER FOR CUSTOM AUTHENTICATION PROVIDER -->
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<!-- config for web using form login-->
<http pattern="/web/**">
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')" />
<form-login/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="nimda" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
In above config first config is working fine ie restservice with basic auth but web with form login config is not working. its not even intercepting the url ?
Please let me know whats wrong with above config ?
Kindly refer below working configuration for web authentication::
<?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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http pattern="/css/**" security="none" />
<http pattern="/images/**" security="none" />
<http pattern="/js/**" security="none" />
<http auto-config="false" authentication-manager-ref="dev" use-expressions="true" disable-url-rewriting="true">
<intercept-url pattern="/admin/login" access="permitAll" />
<intercept-url pattern="/admin/*" access="isAuthenticated()" />
<form-login
login-page="/admin/login"
default-target-url="/admin/workbench"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/admin/login"
/>
<logout logout-success-url="/admin/login" logout-url="/j_spring_security_logout" invalidate-session="true" delete-cookies="JSESSIONID" />
</http>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<!-- STATIC USER -->
<authentication-manager id="dev" alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="abc" password="pwd" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>

Keycloak and Spring Security

Can anyone please show me how to migrate keycloak and spring security. I already follow step in http://keycloak.github.io/docs/userguide/keycloak-server/html/ch08.html#spring-security-adapter. but it dint work. Do i need to write my own provider?
my original spring-security.xml
<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"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd"
>
<http use-expressions="true">
<intercept-url pattern="/index" access="isAuthenticated()" />
<intercept-url pattern="/tasks" access="isAuthenticated()" />
<intercept-url pattern="/dashboard" access="isAuthenticated()" />
<intercept-url pattern="/resetPassword" access="isAuthenticated()" />
<intercept-url pattern="/settings/**" access="isAuthenticated()" />
<intercept-url pattern="/" access="isAuthenticated()" />
<intercept-url pattern="/sam/**" access="hasRole('mym_security_permission-002')" />
<intercept-url pattern="/admin/**" access="hasRole('mym_security_permission-005')" />
<intercept-url pattern="/committee/**" access="isAuthenticated()" />
<intercept-url pattern="/member/**" access="isAuthenticated()" />
<intercept-url pattern="/attachment/download/**" access="isAuthenticated()" />
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login"
login-processing-url="/perform_login"
authentication-failure-url="/login?error"
authentication-success-handler-ref="customAuthenticationSuccessHandler"
username-parameter="username"
password-parameter="password"
always-use-default-target="true"
/>
<!--success-handler-ref="customLogoutSuccessHandler" -->
<logout
logout-url="/perform_logout"
delete-cookies="true"
invalidate-session="true"
/>
<!-- enable csrf protection -->
<csrf/>
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
</http>
<authentication-manager alias="authenticationManager" erase-credentials="false">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
</beans:beans>
i change this xml to xml that provided by keycloak user guide. And i put keycloak.json in web-inf.
After i make the configuration on keycloak. i try to access my page then error page like below will appear:
We're sorry ...
Invalid parameter: redirect_uri
return url:http://localhost:8080/auth/realms/Meeting/protocol/openid-connect/auth?response_type=code&client_id=mym-apps&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2FApp%2Fsso%2Flogin&state=0%2Fd21c7ae9-b041-43e5-8135-8150e9895ee5&login=true
i already resolved this problem. I just fix my “valid redirect URIs” to http://localhost:8080/app/* and /app/*
please add web orgins in keycloak client

Max Concurrent sessions doesn't apply to same browser

i have configured max sessions to be 1 and set error-if-maximum-exceeded=true
i noticed two issues:
1- session-authentication-error-url doesn't work if there's authentication-failure-handler-ref configured, the authentication-failure-handler-ref takes precedence and then you will have to handle SessionAuthenticationException there and make needed logic.
2- if i have open session in chrome and try to login in firefox i get the SessionAuthenticationException but if i tried to login again in chrome (which already has an open session) i get login successful and doesn't get the SessionAuthenticationException
should i prevent the user from seeing login page if he's already authenticated ?
if that's correct, please advise how to do that.
i usually check for authenticated user as follows:
if(!SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals("anonymousUser")){
// logged in user
}
here's my current configuration:
1- 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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
2- applicationSecurity.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<bean id="passwordEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<constructor-arg value="256"/>
</bean>
<bean id="saltSource"
class="org.springframework.security.authentication.dao.ReflectionSaltSource">
<property name="userPropertyToUse" value="username" />
</bean>
<bean id="customUserDetailsService"
class="com.myapp.faces.web.services.CustomUserDetailsService" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder ref="passwordEncoder">
<security:salt-source ref="saltSource" />
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="loginSuccessHandler" class="com.myapp.faces.web.services.LoginSuccessHandler">
<property name="defaultTargetUrl" value="/dashboard"/>
</bean>
<bean id="loginFailureHandler" class="com.myapp.faces.web.services.LoginFailureHandler" />
<security:http use-expressions="true" auto-config="true" >
<security:intercept-url pattern="/j_spring_security_check" access="permitAll" />
<security:intercept-url pattern="/faces/javax.faces.resource/**" access="permitAll"/>
<security:intercept-url pattern="/xmlhttp/**" access="permitAll" />
<security:intercept-url pattern="/resources/**" access="permitAll" />
<security:intercept-url pattern="**/faces/javax.faces.resource/**" access="permitAll" />
<security:intercept-url pattern="**/xmlhttp/**" access="permitAll" />
<security:intercept-url pattern="**/resources/**" access="permitAll" />
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login
login-processing-url="/j_spring_security_check"
login-page="/login"
authentication-failure-handler-ref="loginFailureHandler"
authentication-success-handler-ref="loginSuccessHandler" />
<security:logout />
<security:session-management session-authentication-error-url="/login?error=3">
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/>
</security:session-management>
</security:http>
</beans>
I personally do it this way.
#RequestMapping(method=RequestMethod.GET)
public String login(Authentication authentication)
{
if((authentication != null) && authentication.isAuthenticated())
{
return "redirect:dashboard";
}
return viewResolver.getView(ViewConstants.LOGIN_PAGE);
}
The method above is used for requesting the login page.
I don't think there is a way to do it using only configuration though. I may be wrong.
EDIT :
Check this link

Spring XML using <bean>

This is a pretty simple question, I'm following a tutorial and I'm up to the point where I'm adding a passwordEncoder to my spring security, I have the following XML...
<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.1.xsd">
<http pattern="/static/**" security="none" />
<http use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/*" access="isAuthenticated()" />
<!-- <intercept-url pattern="/secure/extreme/**" access="hasRole('supervisor')"
/> -->
<!-- <intercept-url pattern="/listAccounts.html" access="isAuthenticated()"
/> -->
<!-- <intercept-url pattern="/post.html" access="hasAnyRole('supervisor','teller')"
/> -->
<!-- <intercept-url pattern="/*" access="denyAll" /> -->
<form-login />
<logout invalidate-session="true" logout-success-url="/"
logout-url="/logout" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
</beans:beans>
The problem is the <bean class="org.spr.. line just at the bottom is erroring saying security namespace does not allow
I do understand this, but is there a way I can use the reference without having to add <security: to everything else?
In your XML declaration you are declaring that "security:" is the default namespace:
xmlns="http://www.springframework.org/schema/security"
you have to preface all the elements not found in the security namespace with their prefix... in this case bean is in beans namespace... so you would need to say, beans:bean
This declaration:
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
should be:
<beans:bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

Resources