Spring: Config API using ResourceServerConfigurerAdapter - java

I have some APIs like this: api/{id}/action/{action} and want to add them to security.
#Override
public void configure(HttpSecurity http) throws Exception {
.antMatchers(HttpMethod.PUT, "api/*/action/*").access("hasAnyRole('View_account','Search_account')");
}
when I use the account without role: View_account and Search_account. This API still works well not response 403. Please advise me how to config security with multiple path variable.

You should use regexp for path variables:
#Override
public void configure(HttpSecurity http) throws Exception {
.antMatchers(HttpMethod.PUT, "api/{\\d+}/action/**")
.access("hasAnyRole('View_account','Search_account')");
}
In this case {\\d+} means that your id is digit

Related

Spring Security: Allow requests from specific host name

While specific IP addresses can be allowed for a given antMatcher using
Security Config
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasIpAddress("127.0.0.1")
.anyRequest().permitAll()
}
}
I am unable to find a way to whitelist hostnames eg: "localhost". Is there any way in which a given domain name can be permitted instead of an IP address?
you can configure the security config as follow:
#Override
public void configure(WebSecurity web) throws Exception {
StrictHttpFirewall firewall = new StrictHttpFirewall();
firewall.setAllowedHostnames(hostName -> hostName.equals("myHost.com"));
web.httpFirewall(firewall);
}

Spring Security : HttpSecurity vs WebSecurity

I'm unable to differentiate between the following HttpSecurity and WebSecurity methods.
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers(HttpMethod.POST, "/api/v1/register");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers(HttpMethod.POST, "/api/v1/register").permitAll();
}
ignoring() and permitAll() makes the URLs as open URL, thus giving access to un-authenticated users also.
But when to use which method ?
HttpSecurity.authenticated() method gives access to all authenticated users, irrespective of role.
But, what is the difference between WebSecurity. ignoring() and HttpSecurity.permitAll() ?

How can I use roles in Spring?

In my application I have these roles:
Guest, User, Owner and Admin
I would like to use some kind of authorization where Admin can use all of the endpoints, while Owner can use all the functions that a User have. How should I achive this? What are good pratices?
If you have your securityConfig file setup and everything then all you need to do is permit access to different pages by different user roles, you do it as follow in your SecurityConfig class:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/homePage").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")
.antMatchers("/userPage").access("hasRole('ROLE_USER')")
.antMatchers("/adminPage").access("hasRole('ROLE_ADMIN')")
.and()
.formLogin().loginPage("/loginPage")
.defaultSuccessUrl("/homePage")
.failureUrl("/loginPage?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/loginPage?logout");
}
}
As you can see, home page is accessed by any user with ROLE_ADMIN or normal user (USER_ROLE) roles...
If you see the adminPage can only be accessed by users with ROLE_ADMIN roles...
You can use methods security. First of all, you need to enable method security, you can do this:
#Configuration
#EnableResourceServer
#EnableGlobalMethodSecurity(prePostEnabled = true) //THIS IS THE KEY
public class SecurityConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
}
}
After enable, you can easily use security by method and user, like this:
#GetMapping("/ativas")
#PreAuthorize("hasAnyAuthority('ROLE_ADMIN', 'ROLE_USER') and #oauth2.hasScope('read')")
public List<YourObject> findAll(){
return service.findAll();
}
This is a short answer.
First add Spring Security dependency to your pom.xml. Now use a class to configure Spring security by extending webSecurityConfigurerAdapter. Make sure you add #Configuration and #EnableWebSecurity annotations. Have a look at code below. This should help.
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(id).password("{noop}" + pwd).roles("USER").and().withUser(admin_id).password("{noop}" + admin_pwd).roles("ADMIN", "USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
csrf().disable().authorizeRequests().antMatchers("/**").hasRole("ADMIN").
and().httpBasic();
}

Spring Security with JWT

I am trying to develop Spring Security project with JWT.
I want access Login api with out Spring Security (without JWT token). But with below configuration, every time (for login api as well) it is checking for JWT token giving me 403 error.
Below is my WebSecurityConfig.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthFilter jwtAuthFilter;
#Autowired
private TokenAuthenticationService jwtAuthenticationProvider;
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(jwtAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().ignoringAntMatchers("/api/v1/login");
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/api/v1/login")
.permitAll()
.and()
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Thanks in advance
For login path configuration something like this can be used:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin()
.usernameParameter("username") // default is username
.passwordParameter("password") // default is password
.loginPage("/authentication/login") // default is /login with an HTTP get
.failureUrl("/authentication/login?failed") // default is /login?error
.loginProcessingUrl("/authentication/login/process"); // default is /login
// with an HTTP
// post
}
If some paths need to be ignored configure(WebSecurity web) can be overridden:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/somepath").antMatchers("/static/**");
}
There is filter class named JwtAuthFilter that is being executed before every service you call.
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
this code provides to be executed filter before every request, but its okay, you have to see this FilterClass there must be some check if token doesnt exist filter class must be returned and request will directly go to the login service. if you can show that Filter class and I will help you.

spring-security login?logout redirects to login

I am using spring-security 3.2.0.RC2 with java config and two HttpSecurity configurations. One for REST API and one for UI.
When I post to /logout it redirects to /login?logout but then (incorrectly) redirects to /login.
When i enter username and password successfully I get redirected to login?logout and have to enter credentials a second time to get to the main page.
So it seems like the permitAll for login is not being honored for login?logout.
My security config looks like this:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Resource
private MyUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
StandardPasswordEncoder encoder = new StandardPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
#Configuration
#Order(1)
public static class RestSecurityConfig
extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/v1/**").authorizeRequests()
.antMatchers("/v1/admin/**").hasRole("admin")
.antMatchers("/v1/account/**").hasRole("admin")
.antMatchers("/v1/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/v1/**").authenticated()
.and().httpBasic();
}
}
#Configuration
#Order(2)
public static class UiSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/**").hasRole("admin")
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/plant/**").access("hasRole('admin') or hasRole('dataProvider')")
.antMatchers("/upload/**").access("hasRole('admin') or hasRole('dataProvider')")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
}
}
Can anyone explain why this is happening or what is wrong with my configuration?
A secondary problem that I see with this configuration is that the jsp tag sec:authorize url=... does not work although sec:authorize access=... does work.
In the url=... case it always shows the content even if the user is not authorized.
I know the user is not authorized becuase hitting the link that should have been hidden by the sec:authorize tag results in a 403 Forbidden.
Any help on this greatly appreciated!
I found a workaround for this apparent bug.
I added permitAll() on /login/** as follows:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll();
}
Answering my own question in case it helps anyone else who runs into this bug.
Instead of this:
.antMatchers("/login/**").permitAll()
I think the better solution would be this:
http
.authorizeRequests()
.antMatchers("/account/request/**").permitAll()
.*antMatchers("/login").permitAll()
.antMatchers("/account/change_password/**").authenticated()
.antMatchers("/account/**").hasAuthority("admin")
.antMatchers("/admin/**").hasAuthority("admin")
.antMatchers("/plant/**").hasAnyAuthority("admin", "dataProvider")
.antMatchers("/upload/**").hasAnyAuthority("admin", "dataProvider")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").permitAll().
.and().logout().logoutSuccessUrl("/login?logout").permitAll();
The reason being, url pattern for permitAll(), in this case has limited scope when compared to "/login/**"

Categories