Allow Iframe for all domains while using Spring Security - spring

I am using Spring Security. By default It doesn't allow a page to be loaded in iframe.
Spring Security set header X-Frame-Options value 'DENY'. I don't want this header to be include in my application.
Here is my configuration file.
package com.some.package.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.some.package.crm.enums.Role;
import com.some.package.security.AuthSuccessHandler;
import com.some.package.security.AuthenticationProvider;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
private AuthSuccessHandler authSuccessHandler;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
#Bean
public PasswordEncoder getPasswordEncoder(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
#Override
public void configure(WebSecurity webSecurity) throws Exception
{
webSecurity
.ignoring()
// All of Spring Security will ignore the requests
.antMatchers("/resources/**", "/","/site/**","/affLinkCount", "/forgotPassword","/thirdPartyLogin", "/resetPassword", "/notifyCallbackToRecurring");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
/*
* Security Headers added by default
* Cache Control
* Content Type Options
* HTTP Strict Transport Security
* X-Frame-Options
* X-XSS-Protection
* csrf added by default
*/
http
.authorizeRequests()
.antMatchers("/crm/**").hasRole(Role.CUSTOMER.name())
.antMatchers("/analyst/**").hasRole(Role.ANALYST.name())
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?failed=true")
.successHandler(authSuccessHandler)
.usernameParameter("username")
.passwordParameter("password").loginProcessingUrl("/j_spring_security_check")
.permitAll()
.and()
.sessionManagement().sessionFixation().newSession()
.sessionAuthenticationErrorUrl("/login")
.invalidSessionUrl("/login")
.maximumSessions(1)
.expiredUrl("/login").and()
.and()
.exceptionHandling().accessDeniedPage("/login")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login")
.permitAll();
// .and().headers().frameOptions().disable();
// addFilterAfter(new IFrameEnableFilter(), HeaderWriterFilter.class);
//.headers().frameOptions().addHeaderWriter(new XFrameOptionsHeaderWriter(new WhiteListedAllowFromStrategy(Arrays.asList("localhost"))));
// .headers().addHeaderWriter(new XFrameOptionsHeaderWriter(new WhiteListedAllowFromStrategy(Arrays.asList("localhost"))));
}
}

If you are using Spring Security 4, then you can do this with something like:
http
.headers()
.frameOptions().disable()
.and()
// ...
You can find additional details in the 4.0.x reference.
In Spring Security 3.2.x things are a little different if you want to continue using the other HTTP headers. You need to do something like this:
http
.headers()
.contentTypeOptions();
.xssProtection()
.cacheControl()
.httpStrictTransportSecurity()
.frameOptions()
.and()
// ...
Additional details can be found in the 3.2.x reference.

Thank you #Rob Winch to your answer which leaded me to find a simple solution from the same source, where I could disable it in the xml configuration file as below:
<security:frame-options disabled="true"/>
I just shared this since it may be used by others in order to not do code changes, so it only requires configuration updates

Related

404 when WebSecurityConfig is present

spring-boot-starter-parent 2.4.1
spring-boot-starter-security
package ru.pcask.securing.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
This was copied from an official tutorial (https://spring.io/guides/gs/securing-web/).
The problem:
When I comment every line in his config file out, it shows a Spring security login page. The very login form that is out of the box, made using Bootstrap.
But when I uncomment this code and am redirected to http://localhost:8080/login, this error appears:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Dec 30 19:50:40 MSK 2020
There was an unexpected error (type=Not Found, status=404).
What can I try next to solve this?
the problem is here in this line of code, you want every request to be authenticated.
anyRequest().authenticated()
if you would like to white list some links or all, you can add them explicitly, this is extremely important to add before above call
.anyMatchers("/**").permitAll() // whitelists all
.anyMatchers("/pages/**").permitAll() // whitelists /pages/...
.anyRequest().authenticated()

How to prevent the user after logout when he enter the url in address bar he should get the login page

I have created a web application. Everything works fine.But, if the user is not logged in still they can have access to other jsp pages through url. I want to stop url access. I saw some example it shows the usage of filters. I'm new to filters I don't how to implement it. I'm using spring mvc
I think you want to use Spring security, you can check their official documentation
I think what you want is something that can be placed in your configuration class of WebSecurityConfigurerAdapter
In there, you can protect your pages from unauthenticated and unauthorized access by providing your implementation of configure(HttpSecurity http) method. This is the sample they provide on their documentation page:
package hello;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}

Spring security always returning 403

Can someone tell me why this code is always returning 403?
I mapped /login to trigger the security login but it is not working properly.
package esercizio.security;
import org.springframework.context.annotation.Configuration;
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;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("q#q").password("pluto").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").anonymous()
.antMatchers("/auth/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.jsp")
.defaultSuccessUrl("/auth/list-student")
.failureUrl("/errorPage")
.and()
.logout().logoutSuccessUrl("/login.jsp");
}
}
It should let anyone in if the URL doesn't start with /auth, I don't know why it doesn't happen.
I think, you must prepend 'ROLE_' to you authority like ROLE_USER.
For more visit :
Spring Security always return the 403 accessDeniedPage after login

Add CSS file to Spring Boot + Spring Security Thymeleaf file

I wanted to add CSS file to my HTML file.
The problem appeared when I tried to add CSS to Spring Security application (I work on basic Spring Getting Started Content). I blame Spring Security because without it the CSS file loads properly.
Application.java file:
package mainpack;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) throws Throwable {
SpringApplication.run(Application.class, args);
}
}
MvcConfig.java file:
package mainpack;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/register").setViewName("register");
registry.addViewController("/whatever").setViewName("whatever");
}
}
WebSecurityConfig.java file:
package mainpack;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home", "/index", "/register", "../static/css", "../static/images").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
I load CSS with line:
<link href="../static/css/index.css" th:href="#{/css/index.css}" rel="stylesheet" />
in index.html file.
Your pattern ../static/css is not matching your relative URL ../static/css/index.css, see AntPathMatcher:
PathMatcher implementation for Ant-style path patterns.
Part of this mapping code has been kindly borrowed from Apache Ant.
The mapping matches URLs using the following rules:
? matches one character
* matches zero or more characters
** matches zero or more directories in a path
{spring:[a-z]+} matches the regexp [a-z]+ as a path variable named "spring"
and Spring Boot Reference:
By default, resources are mapped on /** but you can tune that via spring.mvc.static-path-pattern.
Your request will be redirected to login form, because your are not logged in and all other requests need authentication.
To fix it, change your pattern to /css/** and /images/**.
A better solution for static resources is WebSecurity#ignoring:
Allows adding RequestMatcher instances that Spring Security should ignore. Web Security provided by Spring Security (including the SecurityContext) will not be available on HttpServletRequest that match. Typically the requests that are registered should be that of only static resources. For requests that are dynamic, consider mapping the request to allow all users instead.
Example Usage:
webSecurityBuilder.ignoring()
// ignore all URLs that start with /resources/ or /static/
.antMatchers("/resources/**", "/static/**");
The web.ignore()worked the best for me. just add the following method to your WebSecurityConfig class.
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/img/**", "/icon/**");
}
.antMatchers("/**/*.js", "/**/*.css").permitAll();
This allows all the js and css files present in resources/static folder to be permitted for request access.

Return to the previous page after authorization, Spring Security AuthenticationSuccessHundler

I have a login page (/page/login) and dropdown login forms in every page. I want user to be redirected to the page from which he has logged in (by dropdown login form), or the home page if it was from login page.
I tried to use AuthenticationSuccessHandler but it does not seems to work, every time it just redirects user to home page. What is the right way to solve it?
#Component
public class MySimpleUrlAuthenticationSuccessHendler implements AuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException {
if(httpServletRequest.getContextPath().equals("/login")){
sendRedirect(httpServletRequest, httpServletResponse, "/user/profile");
}
else{
sendRedirect(httpServletRequest, httpServletResponse,httpServletRequest.getContextPath());
}
}
private void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
if(!response.isCommitted()){
new DefaultRedirectStrategy().sendRedirect(request,response,url);
}
}
}
Spring security config
package com.example.configuration;
import org.springframework.beans.factory.annotation.Autowired;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
#Configuration
public class DemoSpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
#Autowired
UserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.regexMatchers(HttpMethod.GET, "rating/place/[0-9]{0,}", "/place/[0-9]{0,}/liked/", "/rating/place/[0-9]{0,}")
.hasRole("USER")
.antMatchers(HttpMethod.GET, "/user/orders",
"/user/places")
.hasRole("USER")
.regexMatchers(HttpMethod.POST, "/menu/[0-9]{0,}/comment",
"/place/[0-9]{0,}/menu/[0-9]{0,}")
.hasRole("USER")
.regexMatchers(HttpMethod.POST, "/place/menu/[0-9]{0,}")
.hasRole("OWNER")
.antMatchers(HttpMethod.GET, "/newplace")
.authenticated()
.antMatchers(HttpMethod.POST, "/newplace")
.authenticated()
.antMatchers(HttpMethod.POST, "/registration")
.permitAll()
.antMatchers(HttpMethod.GET, "/resend", "/page/login", "/registration", "/place/")
.permitAll();
http
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/");
http
.rememberMe()
.key("rememberme");
http
.formLogin()
.loginPage("/page/login")
.failureUrl("/page/login")
.loginProcessingUrl("/login")
.usernameParameter("j_username")
.passwordParameter("j_password")
.successHandler(authenticationSuccessHandler);
http.
userDetailsService(userDetailsService);
http.
csrf().disable();
}
}
You need something like this in your AuthenticationSuccessHandler.
I also had similar requirement in my project and I solved this using below step:-
When the login form in dropdown is submitted I also send the current url (window.location.href) as a hidden request parameter.
Inside UserNamePasswordFilter and I get this parameter from request and store it in session (say variable name is redirectPrevUrl).
Now, in authentication success handler if this variable is present (i.e. redirectPrevUrl!=null) I redirect to this url instead of default home page.
This worked for me and I hope it will work for you as well,

Resources