Spring Security Role based access restriction - java

I'm new to Spring Security. As per my understanding from the tutorials, we will configure the user roles in the antMatcher.
My question is, if admin is logged in, is it identifies the URL from the context like /admin and allows the permission? If it is so, I have to write individual role based method for /admin/operation and /user/operation. But, how can I restrict the user other than context level implementation.
In other words, I should have only one method with /operation within the operation, I should identify the user role and have to perform role based operation.
How this could be done?
Please help...

You only need to define list of resource URL using antMatchers() method which need authentication. The user having certain role will be able to access the resource no need to do for rest roles. Below I have defined two configurations for both HTTP Basic and Form Based Authentication.
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {
public static final String REALM_NAME = "startwithjava.com";
#Configuration
#Order(1)
public static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
LoggingAccessDeniedHandler accessDeniedHandler;
#Autowired
AuthSuccessHandler authSuccessHandler;
#Autowired
AppUserDetailsService appUserDetailsService;
#Autowired
PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/",
"/js/**",
"/css/**",
"/img/**",
"/webjars/**").permitAll()
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(authSuccessHandler)
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(appUserDetailsService);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
auth.authenticationProvider(daoAuthenticationProvider);
}
}
#Configuration
#Order(2)
public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
AppUserDetailsService appUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/api/**")
.hasRole("ADMIN")
.and()
.httpBasic()
.realmName(REALM_NAME)
.authenticationEntryPoint(new ApiAuthenticationEntryPoint())
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(appUserDetailsService);
auth.authenticationProvider(daoAuthenticationProvider);
}
}
}

Related

Spring Security-Configuration seems to have no effect

I want to create a simple login - I already created one, and it worked as is should - but when I start this server, it gives the following output:
2022-04-15 20:02:27.303 INFO 45172 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will not secure any request
This is the corresponding config-file:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final IUserService userService;
#Autowired
public SecurityConfig(IUserService userService){
this.userService = userService;
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/mw_rest_api/**");
}
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/login", "/register", "/assets/**").permitAll()
.antMatchers("/", "/control-panel", "/control-panel/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(loginSuccessHandler())
.failureHandler(loginFailureHandler())
.and()
.logout()
.permitAll()
.logoutSuccessUrl("/login");
}
}
Now I am wondering if I have forgotten something, which I dont see? Or is this a bug of Spring itself?
In configure() method you need to disable cref() then you can give your authorizeRequests() with antMatchers() I thnk every think is fine
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Autowired
private UserDetailsService userDetailsService;
#Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
return provider;
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests().antMatchers("/login", "/post/blog/**", "/post/viewpost", "/authentication/create").permitAll()
.antMatchers("/post/filter/page/**", "/post/sorted/page/**", "/post/search/page/**").permitAll()
.antMatchers("/authentication/register", "/review/comment/**").permitAll()
.antMatchers("/post/newPost", "/post/publish", "/post/update", "/post/delete").hasAnyAuthority("ADMIN", "AUTHOR")
.antMatchers( "/review/updateComment", "/review/deleteComment").hasAnyAuthority("ADMIN", "AUTHOR", "USER")
.antMatchers("/rest/authenticate", "/rest/blog/**", "/rest/viewpost/**", "/rest/create").permitAll()
.antMatchers("/rest/filter/page/**", "/rest/sorted/page/**", "/rest/search/page/**", "/rest/comment").permitAll()
.antMatchers("/post/register").permitAll()
.antMatchers("/rest/newPost", "/rest/publish", "/rest/update", "/rest/delete").hasAnyAuthority("ADMIN", "AUTHOR")
.antMatchers("/rest/comment/**", "/rest/updateComment/**", "/post/deleteComment/**").hasAnyAuthority("ADMIN", "AUTHOR", "USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/authentication/login").permitAll()
.defaultSuccessUrl("/post/blog")
.and()
.logout().invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/authentication/logout-success").permitAll();
}
}
This is my code you can take it for reference
And I was using jwt for rest API.
Remove permitAll() after logout()
Remove permitAll() after login("...")

Problem with permitAll in Vaadin and WebSecurity - not working

I have few views made in Vaadin by #Route and now I want to add Security and some Login. In my SecurityConfiguration class I'm setting antMatchers.permitAll() only for 2 views and for the rest with Role ADMIN. But it is not working as I think it should. It demands login to access every view, and after login I have access to all views no matter what role has the user.
I hoped this tutorial will help me, but in there are no views accessible without login.
Securing Your App With Spring Security
My configuration class:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserService userService;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public SecurityConfiguration(UserService userService) {
this.userService = userService;
}
#Autowired
private void configureAuth(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("user"))
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.anonymous()
.and()
.authorizeRequests()
.antMatchers("/", "/login").permitAll()
.antMatchers("/recipe-manager", "/ingredient-manager").hasAnyRole("ADMIN")
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().logoutSuccessUrl("/")
.and()
.csrf().disable().cors().disable().headers().disable();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/VAADIN/**",
"/favicon.ico",
"/robots.txt",
"/manifest.webmanifest",
"/sw.js",
"/offline-page.html",
"/icons/**",
"/images/**",
"/frontend/**",
"/webjars/**",
"/h2-console/**",
"/frontend-es5/**", "/frontend-es6/**");
}
}
My Views have annotations like:
#Route("recipe-manager")
public class RecipeManagerView extends VerticalLayout
#Route("")
public class RecipeBrowserView extends VerticalLayout
#Route("login")
public class LoginView extends VerticalLayout
#Route("ingredient-manager")
public class IngredientManagerView extends VerticalLayout
I would expect that anyone can have access to RecipeBrowserView and LoginView, but only logged user can have access to RecipeManagerView and IngredientMangerView.
You cannot use path based matching from Spring Security for Vaadin routes. Spring Security does the matching based on request paths whereas navigation from one view to another inside Vaadin is sent as metadata inside an internal request that always goes to the same hardcoded path.
Instead, you can implement your access control logic in an interceptor provided by Vaadin. You can have a look at https://vaadin.com/tutorials/securing-your-app-with-spring-security to find out more about this.
To my understanding antMatchers only accept single arguments. You should change you configuration class like:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserService userService;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Autowired
public SecurityConfiguration(UserService userService) {
this.userService = userService;
}
#Autowired
private void configureAuth(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("user"))
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and()
.anonymous()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/recipe-manager", "/ingredient-manager").hasAnyRole("ADMIN")
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().logoutSuccessUrl("/")
.and()
.csrf().disable().cors().disable().headers().disable();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/VAADIN/**",
"/favicon.ico",
"/robots.txt",
"/manifest.webmanifest",
"/sw.js",
"/offline-page.html",
"/icons/**",
"/images/**",
"/frontend/**",
"/webjars/**",
"/h2-console/**",
"/frontend-es5/**", "/frontend-es6/**");
}
}

Multiple authentification strategies in spring boot security

In order to use a custom authentification in spring security you got to implement the UserDetailsService interface and override the loadUserByUsername method, such as the example below
public class UserServiceImpl implements UserDetailsService{
#Autowired
private UserDao userDao;
#Override
public UserDetails loadUserByUsername(String useremail)
throws UsernameNotFoundException {
Users user = userDao.findByUserEmail(useremail);
if(user == null){
throw new UsernameNotFoundException("UserName or Password Invalid.");
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), user.getEnabled(), true, true, true, getGrantedAuthorities(userDao.getUserRole(user.getUsersId())));
}
and its working fine for the whole website.
what i want to do now is to expose a restful webservice from the same host and all the requests for that WS will be through the /api/** with a different type of authentification (e.g : using tokens)
is it possible to do it? and if so, is there any idea how to do it ? any useful resources ?
You can start by making security configuration class as follows
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final TokenAuthenticationFilter tokenAuthenticationFilter;
...
public SecurityConfiguration(TokenAuthenticationFilter tokenAuthenticationFilter) {
this.corsFilter = corsFilter;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.and()
.addFilterBefore(tokenAuthenticationFilter, TokenAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(You log out success handler goes here)
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
}
And your TokenAuthenticationFilter class will do the token authenticity for every request.
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final TokenAuthenticationFilter tokenAuthenticationFilter;
...
public SecurityConfiguration(TokenAuthenticationFilter tokenAuthenticationFilter) {
this.corsFilter = corsFilter;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.and()
.addFilterBefore(tokenAuthenticationFilter, TokenAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.logout()
.logoutUrl("/api/logout")
.logoutSuccessHandler(You log out success handler goes here)
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated();
}
}

Forbidden with Spring Security and #Secured

I have setup Spring Security as follows:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private MongoUserDetailsService userServiceDetails;
#Autowired
private BCryptPasswordEncoder bCryptEncoder;
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/fonts/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.formLogin()
.defaultSuccessUrl("/index", true)
.loginPage("/login")
.permitAll()
.and()
.httpBasic()
.and()
.logout()
.permitAll()
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userServiceDetails)
.passwordEncoder(bCryptEncoder);
}
And on my controller I have the following:
#RequestMapping(method = RequestMethod.GET)
#Secured({"ADMIN"})
public List<Item> getItems(#RequestBody filter filter) {
if (filter.hasMissingField()) {
return new ArrayList<>();
}
return service.getItems(filter);
}
On logging in the user details object has the roles needed (In debug):
However, I am getting a 403 - Forbidden. I can't see why. If I remove the #Secured then I can access the page fine, but with #Secured({"ADMIN"}) it fails.
I have combed SO and I see errors in relation to #Secured not working at all, errors in relation to #Secured having no effects at the Controller level but not like my current scenario where it is failing to authorise with the needed role present.
If it helps I am using Spring Boot 1.3.2.
Any help will be appreciated. Thanks
You have to put #Secured({"ROLE_ADMIN"}) with ROLE_ prefix

Unexpected Spring Boot auth behaviour

I want to secure all endpoint except /register and /activate, but the following configuration does not permit unauthenticated calls to the excluded endpoints. What's missing/wrong? I compared it to several tutorials and code snippets but I am not able to find the failure. I have to remove the .anyRequest().authenticated() part to be able to call one of the two endpoints, but then all other endpoints are also unsecured.
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/register", "/activate").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
}
#Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}

Categories

Resources