Control API exposure - Spring - java

I have an application made in Spring + Vue js and I have questions regarding the exposure of endpoints on the web.
After I'm authenticated in the system, when for example I try to access localhost:8080/contracts he is bringing the response in JSON format on the screen, but I would like to block this exposure, even on account of data security.
How can I best control this? Do I do for Spring Security?
WebSecurityConfig.java
package br.com.braxxy.adm.brxmind.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import br.com.braxxy.pls.web.user.CustomUserDetailsService;
#Configuration
#EnableWebSecurity
#ComponentScan("br.com.braxxy.adm.brxmind.security")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
CustomizeAuthenticationSuccessHandler customizeAuthenticationSuccessHandler;
#Bean
public UserDetailsService mongoUserDetails() {
return new CustomUserDetailsService();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
UserDetailsService userDetailsService = mongoUserDetails();
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/img/**", "favicon.ico", "/materialize/**", "/style/**").permitAll()
.antMatchers(HttpMethod.GET, "/new-user").hasRole("ADMIN")
.antMatchers(HttpMethod.POST, "/new-user").hasRole("ADMIN")
.antMatchers("/login").permitAll()
.antMatchers("/signup").permitAll()
.and().csrf().disable().formLogin().successHandler(customizeAuthenticationSuccessHandler)
.loginPage("/login").failureUrl("/login?error=true").usernameParameter("email")
.passwordParameter("password").and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/").and().exceptionHandling();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/img/**", "/assets/css/**", "/assets/css/vendor/**", "/assets/fonts/**", "/assets/images/**", "/assets/js/**", "/assets/js/vendor/**", "/assets/js/ui/**", "/assets/js/pages/**");
}
}
[![Response API][1]][1]

Related

Authenticating without WebSecurityConfigurerAdapter

I've been following issues such as this one in order to figure out how to implement Authentication without WebSecurityConfigurerAdapter, but my code simply fails to work.
This is my SecurityConfig class:
package com.authentication.take.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import com.authentication.take.services.CustomUserDetailsService;
#Configuration
#EnableWebSecurity
public class SecurityConfig {
private final CustomUserDetailsService customUserDetailsService;
private final AuthenticationConfiguration configuration;
public SecurityConfig(CustomUserDetailsService customUserDetailsService,
AuthenticationConfiguration configuration) {
super();
this.customUserDetailsService = customUserDetailsService;
this.configuration = configuration;
}
#Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http)
throws Exception {
http
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/yolo/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll();
return http.build();
}
#Bean
AuthenticationManager authenticationManager() throws Exception {
return configuration.getAuthenticationManager();
}
void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(customUserDetailsService).passwordEncoder(getPasswordEncoder());
}
}
The problem I am getting is that the /login route is being overriden somehow, and cannot be found. Therefore, when I post data to /login, it isn't interpreted because there is no form in that location.
just add loginProcessingUrl()
....
http
.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/yolo/**").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login").permitAll().loginProcessingUrl("/login")//or any another url ,this url accept just post request
.and()
.logout().permitAll();

I think that there is something wrong with my security config

So i have created a Security Config where i defined the patterns that i want to be granted access to without logging in. And it is not working. In my mind either the file its self is not getting scanned(even though i set it so it would be using #ComponentScan tag in the main Spring application) or the code is faulty.
Here is the code :
package com.projects.AProj.security;
import com.projects.AProj.service.AccountUserDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import static com.projects.AProj.security.Permission.DATA_READ;
import static com.projects.AProj.security.Permission.DATA_WRITE;
#Configuration
#EnableWebSecurity
#AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
private final AccountUserDetailsService accountUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/","/**","/api/**")
.permitAll()
.antMatchers("/my-tree", "/my-tree/*")
.hasAnyAuthority(DATA_READ.getPermission_info(), DATA_WRITE.getPermission_info())
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.defaultSuccessUrl("/",true)
.and()
.logout()
.logoutSuccessUrl("/");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getDaoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider getDaoAuthenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider =
new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(accountUserDetailsService);
return daoAuthenticationProvider;
}
}
btw i would think that it would be helpful to note that the project it self has been acting a tad bit strange. I would get errors that the Repositories are not getting recognized, stuff like can't create bean with name "baseController", unsatisfied dependencies and those kinds of stuff.
Thanks.

Spring Security always returns 403 forbidden in Postman

I'm trying to configure Spring Security authorization but I'm getting 403 (forbidden) for each Postman request.
I checked the other questions but nothing works. Can anyone who got this problem and resolved it share what I need to do to fix it?
I want to add an authorization to make /authenticate accessible for all users, /registeradmin, /registersimpleuser and /listallusers only for the admin role.
I'm getting 403 even in /authenticate which is configured as permit all.
Spring Security config class:
package com.project.encheres.security.configuration;
import javax.servlet.Filter;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import com.project.encheres.repository.UserRepository;
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class })
#Configuration
#EnableWebSecurity
#Component
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserRepository userRepo;
#Autowired
UserDetailsService userDetailsService;
public SecurityConfiguration(UserRepository userRepo) {
this.userRepo = userRepo;
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/user/registersimpleuser").permitAll();
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/authenticate").permitAll()
.antMatchers(HttpMethod.GET, "localhost:8070/user/listallusers").hasAuthority("ADMIN");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
public BCryptPasswordEncoder gePasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/user/registersimpleuser").permitAll();
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "localhost:8070/authenticate").permitAll()
.antMatchers(HttpMethod.GET, "localhost:8070/user/listallusers").hasAuthority("ADMIN");
http
.csrf().disable();
}
Just added http.csrf().disable(); in the end of the method.
this will describe why your code was not working earlier

Sending POST on /login spring security with postman

I'm struggling with log into my application with postman. I'm using spring security with simple configuration:
package main.configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
public WebSecurityConfiguration(#Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/createUser").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
#Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(HttpMethod.POST, "/createUser")
.antMatchers(HttpMethod.POST, "/login");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I'm sending POST request on /loginso that I could log in, but all the time I get:
photo from postman
Could you tell me what I'm doing wrong here? How am I supposed to log in and oparte on postman normally? What is interesting if I try to get page within my browser, I'm asked for credentials and then I'm succesfully logged in.
I want to access my other pages which are protected and test them using POSTMAN.
Here is the answer, lack of httpBasic()
Conf class:
package main.configuration;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
#Configuration
#EnableWebSecurity()
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
public WebSecurityConfiguration(#Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/createUser").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll().and().httpBasic();
http.csrf().disable();
}
#Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(HttpMethod.POST, "/createUser");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
In that case can you please change below as of now and take it from there ?
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password(passwordEncoder().encode("user1Pass")).roles("POSTMAN");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/success.html", true) // example page where request need to be redirected when login is sucessful.
.and()
.logout()
.deleteCookies("JSESSIONID");
}
Try above username and password using in memory implementation first and then configure databaseservice later.
Create success.html and you should see the same after login attempt
If you want to test internal URL's through POSTMAN without authentication/ authorization then comment .anyRequest().authenticated() during testing.

How to auto-logout when session expire in java spring boot / spring security (HttpSecurity)

By auto-logout I mean the browser will be redirected to logout url by itself when session expire, without the user having to click any link that will redirect him to logout url anyway.
this is my SecurityConfig:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.access.vote.RoleVoter; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy;
/** * Created by plato on 5/5/2016. */
#Configuration #EnableWebSecurity #EnableGlobalMethodSecurity(prePostEnabled = true) #Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
DatabaseAuthenticationProvider authenticationProvider;
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/img/**", "/templates/**", "/thymeleaf/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login")
.failureUrl("/login?failed=true")
.defaultSuccessUrl("/login-success")
.and().logout()
.logoutSuccessUrl("/")
.and().authorizeRequests()
.antMatchers("/admin**", "/api/admin/**").hasAuthority("ADMIN")
.antMatchers("/**")
.permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/login?expired-session")
.and()
.invalidSessionUrl("/?invalid-session");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider).eraseCredentials(true);
}
}
The client would have to poll. There server cannot "push" the redirect.
The client can poll every X amount of time, where X is just a bit longer than the session timeout. If the poll is more frequent than that it would refresh the session and so it would never timeout. The client can reset the timer with every user interaction.

Categories

Resources