Spring Security: Allow requests from specific host name - java

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);
}

Related

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 to ignore certain endpoints using Spring Security Oauth

I am using Spring security, oauth in the following way:
#Configuration
#EnableAuthorizationServer
#EnableResourceServer
public class AuthServerOAuth2Config extends AuthorizationServerConfigurerAdapter {
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.jdbc(jdbcTemplate.getDataSource());
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception {
configurer.tokenStore(tokenStore())
.reuseRefreshTokens(true)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
}
I want to now make certain URL's public, so that no token is required to access those resources. For example /public/**
How would I do this? Do I need to use a WebSecurityConfigurerAdapter? Thanks for any help!
UPDATE
I added the WebSecurityConfigurerAdapter as pointed out below. So now the /public/** URL is accessible without any tokens. However, all other endpoints are no longer accessible, and respond with 403 Forbidden
For making the path public/** open without authentication, you can configure the WebSecurityConfigurerAdapter like the following:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/public/**").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated();
}
}
you should have something like this
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login*").permitAll();
}
This is how I solved it:
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(HttpMethod.GET, "/public/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
}
}

Configure Spring Security at multiple places

I can obviously use the full power of Spring Security by implementing a single WebSecurityConfigurerAdapter and access HttpSecurity in its configure method. But this results in monolithic implementations and cannot be spread across application modules without implementing custom measures for that.
So, one could be tempted to implement multiple WebSecurityConfigurerAdapter subclasses. But this results in duplicated HttpSecurity objects, trying to reconfigure some basic aspects (e.g. csrf) and cannot properly modify things already configured in the first adapter. Even disabling the defaults does not quite help here.
Thus, my question is: Is there a Spring- or Spring-Boot-way of specifying the http security in independent Configuration/Component classes? (so Java not xml config)
An example might be to add a security filter in the middle of the chain. Another one to change csrf (e.g. session to cookie) while another class alone would just keep the defaults.
I dont think so that there is a direct way of doing this. But still we can force it in our project architecture to do so.
There are mainly 3 methods which we usually override for our configuration from WebSecurityConfigurerAdapter.
1. configure(AuthenticationManagerBuilder auth)
2. configure(WebSecurity web)
3. configure(HttpSecurity http)
As per Spring security architecture there can only be one instance of WebSecurityConfigurer used.
We can design something like this :
1. With this rule we can have our parent project holding this WebsecurityConfigurer Instance.
2. We can have IBaseSecurityConfig having above 3 methods signature.
3. We will ignore any other WebsecurityConfigurer instance and allow only parent WebsecurityConfigurer instance.
4. We can have abstract implementation of IBaseSecurityConfig as BaseSecurityConfig.
Like Spring enforces WebsecurityConfigurer upon us, you can force BaseSecurityConfig upon your project modules to override any Security Related configs.
I will try explaining it with an example.
public interface IBaseSecurityConfig {
void configure(AuthenticationManagerBuilder auth) throws Exception;
void configure(WebSecurity web) throws Exception;
void configure(HttpSecurity http) throws Exception;
}
#Configuration
public abstract class BaseSecurityConfig implements IBaseSecurityConfig {
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO Any defaults
}
#Override
public void configure(WebSecurity web) throws Exception {
// TODO Any defaults
}
#Override
public void configure(HttpSecurity http) throws Exception {
// TODO Any defaults
}
}
Now we will declare our security configs anywhere by extending BaseSecurityConfig. Lets say we declared WebSecurityConfiguration1 as below.
#Configuration
public class WebSecurityConfiguration1 extends BaseSecurityConfig {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/css/**", "/js/**", "/admin/**").permitAll().anyRequest().authenticated()
.and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
.formLogin().loginPage("/login").permitAll().and().logout().logoutSuccessUrl("/");
}
}
Now we will declare a separate security config at any other place. Lets call it WebSecurtiyConfiguration2.
#Configuration
public class WebSecurtiyConfiguration2 extends BaseSecurityConfig {
#Override
public void configure(HttpSecurity http) throws Exception {
IsSecureFilter i1 = new IsSecureFilter();
http.addFilterBefore(i1, ChannelProcessingFilter.class);
}
}
Now we have to auto configure both the above declared security configs. We will do it in our parent project or you may say it that we will confiure them in the actual instance of SecurityConfig as below.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private List<IBaseSecurityConfig> securityConfigs;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
for(IBaseSecurityConfig secConfig : securityConfigs) {
secConfig.configure(auth);
}
}
#Override
public void configure(WebSecurity web) throws Exception {
for(IBaseSecurityConfig secConfig : securityConfigs) {
secConfig.configure(web);
}
}
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("CONFIGURING FROM BASE");
for(IBaseSecurityConfig secConfig : securityConfigs) {
secConfig.configure(http);
}
}
}
Now here is our Application loading class.
We will have to ensure that no other WebSecurityConfigurerAdapter loads and only ours parent instance gets loaded. We do it by #Component-> exclusion filters. With the help of #Import will be ensured that only our instace gets loaded.
#SpringBootApplication
#EnableCaching
#ComponentScan(excludeFilters = #ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes=WebSecurityConfigurerAdapter.class))
#Import(SecurityConfig.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Now you have forced your architecture to declare any security config by extending only BaseSecurityConfig and you can do this at different location.
But be cautious that this can override each others configs in case of conflicts.

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: Config API using ResourceServerConfigurerAdapter

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

Categories