concurrent session management not working while setting sessionManagement().maximumSessions(1) allowing 2 sessions per user - spring

I want a user to login only once and i am using the below mentioned code . It is working but allowing same user to login twice(creating 2 different sessions) and then in 3rd login attempt it is giving error message.##
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic()
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry()) ;
}
private SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("u")
.password("{noop}p") // Spring Security 5 requires specifying the password storage format
.roles("USER");
}

Related

Spring security - How to use role based authentication for different domains?

There is a project with Spring boot back-end on running on localhost:8080 and 2 front-end angular applications on localhost:4200 (User website) and localhost:4201(Admin website).How can i configure spring security so that it allows only users with role - ROLE_USER,ROLE_ADMIN in User website and users with role -ROLE_ADMIN should have access to Admin Website.
Currently both users are able to access both wesbite.Is there any way to restrict certain domains rather restricting paths(URLs) to users.
Current config -
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
Environment env;
#Autowired
UserSecurityService useSecurityService;
private BCryptPasswordEncoder passwordEncoder() {
return SecurityUtility.passwordEncoder();
}
private static final String[] PUBLIC_MATHCES= {
"/css/**",
"/js/**",
"/images/**",
"/book/**",
"/user/**",
"/media/**"
};
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(useSecurityService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(PUBLIC_MATHCES).permitAll()
.anyRequest().authenticated()
.and();
http.csrf().disable()
.cors()
.and()
.httpBasic();
}
#Bean
public HttpSessionIdResolver httpSessionStrategy() {
return HeaderHttpSessionIdResolver.xAuthToken();
}
}
suppose all of your configurations configured properly, then you can make use of the role restriction mechanism as the below sample :
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorize - > {
authorize
.antMatchers("/h2-console/**").permitAll() //do not use in production!
.antMatchers("/css/**", "/js/**", "/images/**", "/book/**", "/user/**", "/media/**").permitAll()
.antMatchers("/website/find", "/main*").permitAll()
.antMatchers(HttpMethod.GET, "/userweb/v1/data/**").permitAll()
.mvcMatchers(HttpMethod.DELETE, "/userweb/v1/info/**").hasRole("ADMIN")
.mvcMatchers(HttpMethod.GET, "/userweb/v1/item/{upc}").permitAll()
.mvcMatchers("/admin/main").hasAnyRole("USER", "ADMIN")
.mvcMatchers(HttpMethod.GET, "/user/api/v1/normal")
.hasAnyRole("USER", "ADMIN", "FOO");
})
.authorizeRequests()
.anyRequest().authenticated()
.and()
.cors()
.and()
.httpBasic()
.and().csrf().disable();
}

Whitelist Multipart file upload in Spring Security

This is my first post on stackoverflow. Please bear with me. I am having an issue allowing files to be uploaded without needing authorization as it is part of a registration process. I have added the path to my upload in the antMatchers.permitAll() but Spring still throws a 401 Unauthorized when I try to do an upload. Can somebody please assist me? I have been struggling with this for a while now.
This is my security config
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/v0/business-registration", "/api/v0/business-registration/file","/api/v0/admin/register", "/api/v0/admin/login")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}

How to disable multiple logins for same user in spring security + spring boot

I have the below spring configuration :-
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint((request, response,
authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,
"/api/v2/customers/**").permitAll()
.antMatchers(HttpMethod.OPTIONS,
"/oauth/**").permitAll()
.antMatchers(HttpMethod.GET, "/saml/**").permitAll()
.antMatchers(HttpMethod.GET,
"/api/internal/v2/**").permitAll()
.antMatchers("/**").authenticated()
.antMatchers("/api/admin/**").authenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(SR);
}
I was expecting sessionManagement().maximumSessions(1) to disable multiple login for the same user. It is working, but first user logout the application, so i am trying login in another browser but it showing This account is already using by someone.
Try this. you are not clearing/ closing the previous session properly.
#EnableWebMvcSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/expired").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/expired")
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());
}
#Bean
public SessionRegistry sessionRegistry() {
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
// Register HttpSessionEventPublisher
#Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}
}
Missing is .expiredUrl("/expired").maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry());

Control Multiple session for Same User

Trying to implement concurrent Session Control to invalidate the prior logged-in session and logout that session and let user login on another browser, so that a single user concurrently do not have multiple logins. I have used the following HTTP configurations in Web security configurations. But it's not working.
UaaWebSecurityconfiguration.java
#Autowired
public SessionRegistry sessionRegistry;
#Bean
public SessionRegistry sessionRegistry() {
if (sessionRegistry == null) {
sessionRegistry = new SessionRegistryImpl();
}
return sessionRegistry;
}
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.csrf()
.disable()
.addFilterBefore(corsFilter, CsrfFilter.class).exceptionHandling()
.authenticationEntryPoint(problemSupport).accessDeniedHandler(problemSupport)
.and()
.rememberMe()
.key(jHipsterProperties.getSecurity().getRememberMe()
.getKey()).and().headers()
.frameOptions().disable()
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry)
.and()
.sessionFixation()
.changeSessionId()
.sessionAuthenticationStrategy(compositeSessionAuthenticationStrategy())
.and()
.authorizeRequests().antMatchers("/api/register")
.permitAll().antMatchers("/api/activate").permitAll().antMatchers("/api/authenticate")
.permitAll().antMatchers("/api/account/reset-password/init").permitAll()
.antMatchers("/api/account/reset-password/finish").permitAll()
.antMatchers("/api/profile-info").permitAll().antMatchers("/api/**").authenticated()
.antMatchers("/websocket/tracker").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/websocket/**").permitAll().antMatchers("/management/health").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.antMatchers("/v2/api-docs/**").permitAll()
.antMatchers("/swagger-resources/configuration/ui").permitAll()
.antMatchers("/swagger-ui/index.html").hasAuthority(AuthoritiesConstants.ADMIN);
}
#Bean
public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy() {
ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
strategy.setMaximumSessions(1);
return strategy;
}
#Bean
public SessionFixationProtectionStrategy sessionFixationProtectionStrategy(){
return new SessionFixationProtectionStrategy();
}
#Bean
public RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy(){
RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy = new RegisterSessionAuthenticationStrategy(sessionRegistry());
return registerSessionAuthenticationStrategy;
}
#Bean
public CompositeSessionAuthenticationStrategy compositeSessionAuthenticationStrategy(){
List<SessionAuthenticationStrategy> sessionAuthenticationStrategies = new ArrayList<>();
sessionAuthenticationStrategies.add(concurrentSessionControlAuthenticationStrategy());
sessionAuthenticationStrategies.add(sessionFixationProtectionStrategy());
sessionAuthenticationStrategies.add(registerSessionAuthenticationStrategy());
CompositeSessionAuthenticationStrategy compositeSessionAuthenticationStrategy = new CompositeSessionAuthenticationStrategy(sessionAuthenticationStrategies);
return compositeSessionAuthenticationStrategy;
}
With this configuration, a session will be created in only one browser,
and all attempts to login to the new browser will not be successful as long as the session exists.
With such a minimal configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.maximumSessions(1)
.sessionRegistry(sessionRegistry());
}
the session will be created every time, and the old session will expired

Spring Security Concurrent Session Control

I am trying to restrict user session to one at a time from anywhere. But it doesn't work. When I try to access the application with the same user on two navigator, I have access.
I noticed that when a user connects to the application on two different machines to start printing two different reports, there is an print that comes out instead of the other.
Thanks for help.
My Security config class :
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
/*#Autowired
private DataSource dataSource;*/
private AccessDeniedHandler accessDeniedHandler;
private AuthenticationSuccessHandler authenticationSuccessHandler;
private AuthenticationFailureHandler authenticationFailureHandler;
private UserDetailsService userDetailsService;
#Autowired
public SecurityConfiguration(
#Qualifier("customAccessDeneiedHandler")AccessDeniedHandler accessDeniedHandler,
#Qualifier("customSuccessHandler")AuthenticationSuccessHandler authenticationSuccessHandler,
#Qualifier("customAuthenticationFailureHandler")AuthenticationFailureHandler authenticationFailureHandler,
#Qualifier("customUserDetailsService")UserDetailsService userDetailsService) {
this.accessDeniedHandler = accessDeniedHandler;
this.authenticationSuccessHandler = authenticationSuccessHandler;
this.authenticationFailureHandler = authenticationFailureHandler;
this.userDetailsService = userDetailsService;
}
/* (non-Javadoc)
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder)
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Auto-generated method stub
//super.configure(auth);
auth.userDetailsService(userDetailsService) //auth.userDetailsService(utilisateurDetailsService)
.passwordEncoder(passwordEncoder());
}
//Authorization
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
//.antMatchers("/").permitAll()
.antMatchers("/ajouterassure", "/ajouterattributaire", "/ajouterbeneficiaire", "/ajouterpiecejustificative",
"/creerbordereauemission", "/creerbehorscoordination", "/creerbordereaupaie", "/ajouteravance",
"/creerbeavanceannuelle")
.hasAnyRole("DGA", "DGAA", "DR", "DRA", "CC", "CCA", "CI", "AS", "GUICHET", "CE", "CAP", "ADMIN") //.hasRole("ADMIN")
.antMatchers("/ajoutercentre", "/ajouteretablissementpaie", "/ajoutertypepj", "/ajoutertypedette",
"/ajoutersexe", "/ajoutersituationbeneficiaire", "/ajoutercategoriebeneficiaire",
"/ajoutercategorieattributaire", "/ajouterrevalorisation").hasAnyRole("DGA", "ADMIN") //hasAnyRole("CAP", "ADMIN")
.antMatchers("/payerdecompte").hasAnyRole("CAISSIER", "ADMIN")
.antMatchers("/ajouterutilisateur").hasAnyRole("CI", "ADMIN")
.anyRequest().authenticated()
.and()
//.httpBasic()
.formLogin()
.loginPage("/login")
//.loginProcessingUrl("/login")
.usernameParameter("identifiant")
.passwordParameter("mot_de_passe")
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
//.defaultSuccessUrl("/")
.permitAll()
.and()
.logout().permitAll()
.and()
.sessionManagement() //Session controle concurence access
.maximumSessions(1)
.expiredUrl("/login?expired")
.sessionRegistry(sessionRegistry);
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
//Session controle concurence access
//http.sessionManagement().maximumSessions(1);
}
/* (non-Javadoc)
* #see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.WebSecurity)
*/
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/resources/templates/errors/**", "/static/**", "/css/**", "/images/**", "/var/signatures/**");
//web.ignoring().antMatchers("/static/**");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
#Bean(name = "sessionRegistry")
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
#Autowired
#Lazy
private SessionRegistry sessionRegistry;
}
[Just in case someone finds it useful.]
Always add hashcode and equals methods in custom UserDetails class along with the below config in the spring security configuration class for the concurrent sessions to work.
protected void configure(HttpSecurity http) throws Exception
{
http.sessionManagement().maximumSessions(1);
}
#Bean
public HttpSessionEventPublisher httpSessionEventPublisher()
{
return new HttpSessionEventPublisher();
}
You need to just add .maxSessionsPreventsLogin(true) after maximumSessions(1) and it stop logging in from other places util session expires here. So your configure method should look like this :-
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
//.antMatchers("/").permitAll()
.antMatchers("/ajouterassure", "/ajouterattributaire", "/ajouterbeneficiaire", "/ajouterpiecejustificative",
"/creerbordereauemission", "/creerbehorscoordination", "/creerbordereaupaie", "/ajouteravance",
"/creerbeavanceannuelle")
.hasAnyRole("DGA", "DGAA", "DR", "DRA", "CC", "CCA", "CI", "AS", "GUICHET", "CE", "CAP", "ADMIN") //.hasRole("ADMIN")
.antMatchers("/ajoutercentre", "/ajouteretablissementpaie", "/ajoutertypepj", "/ajoutertypedette",
"/ajoutersexe", "/ajoutersituationbeneficiaire", "/ajoutercategoriebeneficiaire",
"/ajoutercategorieattributaire", "/ajouterrevalorisation").hasAnyRole("DGA", "ADMIN") //hasAnyRole("CAP", "ADMIN")
.antMatchers("/payerdecompte").hasAnyRole("CAISSIER", "ADMIN")
.antMatchers("/ajouterutilisateur").hasAnyRole("CI", "ADMIN")
.anyRequest().authenticated()
.and()
//.httpBasic()
.formLogin()
.loginPage("/login")
//.loginProcessingUrl("/login")
.usernameParameter("identifiant")
.passwordParameter("mot_de_passe")
.successHandler(authenticationSuccessHandler)
.failureHandler(authenticationFailureHandler)
//.defaultSuccessUrl("/")
.permitAll()
.and()
.logout().permitAll()
.and()
.sessionManagement() //Session controle concurence access
.maximumSessions(1)
.expiredUrl("/login?expired")
.sessionRegistry(sessionRegistry);
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
//Session controle concurence access
//http.sessionManagement().maximumSessions(1);
}

Resources