I have a spring boot web server which uses the httpWebSecurityAdapter.
I am trying to display some web pages (HTML CSS, javascript) in a div in my Angular app.
X-frame does not allow me to do it if enabled.
I would like to disable the x-frame options only for a certain type of request.
Right now I have it disabled for everything. I would like to do only for a certain URL.
http.headers().frameOptions().disable()
You will need to provide multiple WebSecurityConfigurerAdapter configurations. In other words, multiple security configurations for each of your url patterns.
Here's a sample configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig {
// #Order is to specify which WebSecurityConfigurerAdapter should be considered first. This configuration has the highest priority.
// This configuration is activated for url pattern: /home/**
#Order(1)
#Configuration
public static class DefaultSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/home/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().formLogin()
.and().httpBasic();
}
}
// This configuration is considered after DefaultSecurityConfiguration since it has #Order(2).
// This configuration is activated for url pattern: /registerUser/**
#Order(2)
#Configuration
public static class DisabledFrameOptionsSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/registerUser/**")
.authorizeRequests()
.anyRequest().permitAll();
http.headers().frameOptions().sameOrigin();
}
}
}
In my Spring boot project I have some endpoints that require authentication and others don't. I'm using spring-security-oauth2-autoconfigure dependency. The problem is when I want to access a resource that don't require authentication with an invalid access_token I get an error "error": "invalid_token".
How can I prevent checking access token when if my method is not secured?
ResourceServerConfiguration.java
#Configuration
#EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable().and().authorizeRequests().antMatchers("/graphql/**")
.permitAll();
}
}
WebSecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
.anyRequest().authenticated().and().httpBasic().and().csrf().disable();
}
}
to disable spring security chain for a particular resource you can add ignore web request for pattern like below in your WebSecurityConfiguration class
#Override
public void configure(WebSecurity webSecurity) throws Exception
{
webSecurity
.ignoring()
.antMatchers("/resourcename**");
}
I'm trying to authenticate with Basic Auth though LDAP but I only need to do so with /login route. All the other routes need to be authenticated through a custom JWT Filter that I implemented. Actually, what I've done just doesn't work.
Edit : just to be more clear, at the moment when I call on /auth/login, it goes through the LDAP filter and not the JWT Filter. But when I call any other route, it goes through JWT Filter and then still goes through the LDAP one and always makes my request fail. The behaviour is only correct when it's the /auth/login call.
Here's the configuration :
public class SecurityConfiguration {
#Configuration
#EnableWebSecurity
#Order(Ordered.HIGHEST_PRECEDENCE + 21)
public static class CompanySecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private LdapContextSource ldapContextSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication().contextSource(ldapContextSource).userDnPatterns("uid={0},ou=people");
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.httpBasic().and()
.requestMatchers()
.antMatchers("/auth/login")
.and().authorizeRequests().anyRequest().authenticated()
.and().csrf().disable();
}
}
#Configuration
#EnableWebSecurity
#Order(Ordered.HIGHEST_PRECEDENCE + 20)
public static class JWTSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.requestMatchers()
.antMatchers("/projects", "/projects/**", "/credential/**")
.and()
.addFilterAfter(new JWTFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests().anyRequest().authenticated()
.and().cors().disable();
}
}
}
I am looking for a non invasive way to add a captcha filter for certain api calls.
My setup consists of two WebSecurityConfigurerAdapters with one filter each (not the captcha filter):
Internal api ("/iapi" use Filter A on all calls but also ignore some public requests like /authenticate)
External api ("/eapi" use Filter B on all calls)
How can I add a filter before the Spring Security stuff, on public, internal api or external api calls? I don't need the SecurityContext, just need to check for a Captcha in the request headers, forward to filterChain (normal filters) or manually deny access. I tried declaring a filter in web.xml, but that breaks the ability to use dependency injection.
Here is my Spring Security Configuration:
#EnableWebSecurity
public class SpringSecurityConfig {
#Configuration
#Order(1)
#EnableGlobalMethodSecurity(securedEnabled = true)
public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private Filter filterA;
public InternalApiConfigurerAdapter() {
super(true);
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/public/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/iapi/**")
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.authorizeRequests()
.anyRequest().authenticated().and()
.addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
#Configuration
#Order(2)
#EnableGlobalMethodSecurity(securedEnabled = true)
public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private FilterB filterB;
public ExternalApiConfigurerAdapter() {
super(true);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/external/**")
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.authorizeRequests()
.anyRequest().authenticated().and()
.addFilterBefore(filterB, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
Update: At the moment I have a working configuration with a filter declared in web.xml. However, it has the drawback of being seperated from the Spring Context (e.g. no autowiring of beans), so I am looking for a better solution leveraging Spring.
Summary: There are two remaining problems:
add a filter for specific urls only - using beforeFilter(...) inside any configuration adds a filter to all urls of that configuration. Antmatchers didn't work. I need something like that: /iapi/captcha/, /external/captcha/, /public/captcha/*.
I have a public api which bypasses Spring Security completely: (web
.ignoring()
.antMatchers("/public/**");). I need to bypass Spring Security but still declare a filter there, using Spring autowiring but not necessarily Spring Security features, since my captcha filter only rejects or forwards calls in a stateless way.
You already have a working configuration with filters A and B inserted before UsernamePasswordAuthenticationFilter so should be easy to add another custom filter.
First, you create the filter, and declare it as a bean, either annotating the class with #Component, or as a #Bean inside a #Configuration class, so it is ready to be injected with #Autowired.
Now you are able to inject it, as filter A and B, and use it. According to the Filter Ordering section in the Spring Security reference documentation, the very first Filter in the chain is ChannelProcessingFilter, so in order to insert the filter before anything else in the Spring Security filter chain, you'd do this:
#Autowired
private CaptchaFilter captchaFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/iapi/**")
.addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
.addFilterBefore(filterA, (Class<? extends Filter>) UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
}
By the way, exceptionHandling() anonymous() and servletApi() aren't needed because when extending WebSecurityConfigurerAdapter, these are already included, except for anonymous() when you actually specify more configuration details, as it states HttpSecurity javadoc
Keep in mind that the Spring Security "entrypoint", the DelegatingFilterProxy still will be executed before your filter, but this component only delegates the request to the first filter in the chain, which in this case would be the CaptchaFilter, so you really would execute your filter before anything else from Spring Security.
But if you still want the captcha filter be executed before the DelegatingFilterProxy, there is no way to do so in the Spring Security configuration, and you need to declare it in the web.xml file.
Update: If you do not desire to include the captcha filter in the other configurations, you can always add a third configuration, and the configurations class would be as follows:
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityConfig {
#Configuration
#Order(1)
public static class CaptchaApiConfigurerAdatper extends WebSecurityConfigurerAdapter {
#Autowired
private CaptchaFilter captchaFilter;
public CaptchaApiConfigurerAdatper() {
super(true);
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/public/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatcher("/iapi/captcha**")
.antMatcher("/external/captcha**")
.and()
.addFilterBefore(captchaFilter, (Class<? extends Filter>) ChannelProcessingFilter.class)
.authorizeRequests()
.anyRequest().authenticated();
}
}
#Configuration
#Order(2)
public static class InternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
// ommiting code for the sake of clarity
}
#Configuration
#Order(3)
public static class ExternalApiConfigurerAdapter extends WebSecurityConfigurerAdapter {
// ommiting code for the sake of clarity
}
By the way, another tip, you can refactor all the common configuration outside the specific configurations, into the main class, like #EnableGlobalMethodSecurity(securedEnabled = true) the AuthenticationManager, the WebSecurity to skip security for the public, but for those since the main class is not extending anything you should #Autowire the method declarations.
Although there would be one problem with the WebSecurity, if you are ignoring /public/** the matcher for the HttpSecurity with /public/captcha** would be ignored, so i guess, you shouldnt refactor out the WebSecurity and have a different pattern in the CaptchaConfig class so it doesnt overlap.
I am trying to setup a single path (/basic) in my spring-boot spring MVC based application to be basic auth protected. I am just going to configure this using my own custom configuration parameters so the username and password are simply "admin" and "admin".
This currently works for the /basic path (I am prompted and can login correctly). The problem is that logout does not work (and I am not sure why) and also other paths (like /other shown) are being asked for basic auth credentials (before always being denied).
static class MyApplicationSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/open").permitAll();
http.authorizeRequests().antMatchers("/other").denyAll(); // Block it for now
http.authorizeRequests().antMatchers("/basic").authenticated().and().httpBasic().and().logout().logoutUrl("/basic/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
}
}
I expected /other to always be denied but I don't get why basic auth is coming up for it. /open works as expected. I also don't understand why /basic/logout does not log me out (it also does not produce error messages). I do have a simple bit of code as a placeholder for the logout endpoint but if I do not have that then I get a 404. The "home" view is my web app root so I just want to send the user there after logout.
#RequestMapping("/logout")
public ModelAndView logout() {
// should be handled by spring security
return new ModelAndView("home");
}
UPDATE:
Here is the solution that seemed to work in the end (except the logout part, still not working):
#Configuration
#Order(1) // HIGHEST
public static class OAuthSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth").authorizeRequests().anyRequest().denyAll();
}
}
#Configuration
public static class BasicAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/basic").authorizeRequests().anyRequest().authenticated().and().httpBasic();
http.logout().permitAll().logoutUrl("/logout").logoutSuccessUrl("/").invalidateHttpSession(true);
//.and().logout().logoutUrl("/basic/logout").invalidateHttpSession(true).logoutSuccessUrl("/");
}
}
i'm not sure about the logout, but we had a similar problem with having some of our site under basic and some of it not. Our solution was to use a second nested configuration class only for the paths that needed http basic. We gave this config an #Order(1)..but i'm not sure if that was necessary or not.
Updated with code
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private static final Logger LOG = LoggerFactory.getLogger(SecurityConfig.class);
#Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth, Config appConfig) throws Exception {
auth.inMemoryAuthentication()
.withUser(appConfig.getString(APIConfig.CONFIG_KEY_MANAGEMENT_USER_NAME))
.password(appConfig.getString(APIConfig.CONFIG_KEY_MANAGEMENT_USER_PASS))
.roles(HyperAPIRoles.DEFAULT, HyperAPIRoles.ADMIN);
}
/**
* Following Multiple HttpSecurity approach:
* http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity
*/
#Configuration
#Order(1)
public static class ManagerEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/management/**").authorizeRequests().anyRequest().hasRole(HyperAPIRoles.ADMIN).and()
.httpBasic();
}
}
/**
* Following Multiple HttpSecurity approach:
* http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#multiple-httpsecurity
*/
#Configuration
public static class ResourceEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
//fyi: This adds it to the spring security proxy filter chain
.addFilterBefore(createBBAuthenticationFilter(), BasicAuthenticationFilter.class)
;
}
}
}
this seems to secure the actuator endpoints at /management with basic auth while the others work with a custom auth token header. We do not prompt for credentials (no challenge issued) though for anything..we'd have to register some other stuff to get that going (if we wanted it).
Hope this helps
only one path will be protected
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception
{
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("user"))
.roles("USER");
}
#Configuration
#Order(1)
public static class ManagerEndpointsSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/add/**").authenticated()
.anyRequest().permitAll()
.and()
.httpBasic()
.and().csrf().disable();
}
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}