So since i'm working on spring security i've setted the headers.frameOptions to DENY, when i try this by putting my backend endpoint in an iframe which is localhost:8080 here , everything is working perfectly fine, the thing is, when i put the frontend localhost:3000 in iframe, nothing happens and the application is displayed in the iframe.
i'm thinking that the headers configuration i'm doing are applying only on APIs and not at the start of the application
at the start of the application as you can see there is no configuration : X-Frame-Options: DENY
Here after i send an API
here is the function
#Override
protected void configure(HttpSecurity http) throws Exception {
http.headers()
.httpStrictTransportSecurity()
.maxAgeInSeconds(31536000)
.includeSubDomains(true);
http.headers()
.contentTypeOptions();
http.cors().and()
.headers()
.xssProtection()
.and()
.contentSecurityPolicy("script-src 'self'")
.and()
.httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000)
.and()
.contentSecurityPolicy("frame-ancestors 'none'")
.and()
.frameOptions()
.deny()
.and()
.csrf()
.disable()
.formLogin().defaultSuccessUrl("/swagger-ui.html", true).and()
.authorizeRequests().antMatchers(AUTH_LIST).authenticated()
.antMatchers("/actuator/**").access("hasAnyRole('ADMIN') and hasIpAddress('127.0.0.1')")
.anyRequest().permitAll()
.and().httpBasic();
}
I finally resolved this issue by configuring the frontend web.xml file by following this
if u're using nginx as a server you can add :
Header always set X-Frame-Options "SAMEORIGIN"
if you're using any other server u can check mdn,
to conclude, if you're working on a full stack application you have to configure the server configuration file otherwise spring security won't prevent you from clickjacking.
Related
please forgive any lack of structure/etiquette, this is my first post.
I have a Java application using Spring Boot (v2.1.6) with annotation based configuration for spring-boot-starter-security and cannot understand how to add the response header of:
"Set-Cookie: SameSite=strict"
to resolve the warning:
A cookie associated with a cross-site resource at "myApiUrl" was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.
The full configuration for my HttpSecurity is listed below and I have attempted to add the header in the last portion of the configuration using StaticHeadersWriter as such:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors()
.and()
.exceptionHandling()
.authenticationEntryPoint(entryPoint) //request is generally sent to entry point when unauthorized
.and()
.authorizeRequests()
.antMatchers("/loggedIn").permitAll()
.antMatchers("/createUser").permitAll()
.antMatchers("/deleteUser").hasRole("ADMIN")
.antMatchers("/fullDB").hasRole("ADMIN")
.antMatchers("/logs").hasRole("ADMIN")
.antMatchers("/**").authenticated()
.and()
.formLogin()
.successHandler(new AuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.deleteCookies(cookieName)
.invalidateHttpSession(true)
.logoutUrl("/logout")
.logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)))
.and()
.headers()
.addHeaderWriter(new StaticHeadersWriter("Set-Cookie", "SameSite=strict"))
.addHeaderWriter(new StaticHeadersWriter("A-cookie","B=val"))
.addHeaderWriter(new StaticHeadersWriter("SetCookie","SameSitestrict"));
}
Using the following configuration I am able to receive a valid response with every header except the Set-Cookie header, which appears to get removed and can be seen in the below link.
Image of Response
Additional attempts at resolving this issue that I have tried included adding a redirect in the provided successHandler() to a custom url endpoint, which would then return a ResponseEntity where I could provide the code below, however these attempts also would not have the "Set-Cookie" response header included.
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.SET_COOKIE, "SomeName=someId");
return new ResponseEntity(httpHeaders, HttpStatus.OK);
or
response.addCookie(new Cookie("SomeName", "someId"));
return ResponseEntity.ok().build();
Any advice on how to provide the "Set-Cookie" header on the response from a Spring Boot API call to resolve this chrome warning would be greatly appreciated!
To give some context, I'm building a PWA (Progressive Web App) for myself and some friends as a test project. I'm using basic authentication.
As it is a PWA I want it to behave like other apps do, which includes not having to log in every few days keeping the user logged in. Disabling the timeout may not be the best way as it gives security risks but for now it should do just fine.
I already tried to increase the timeout setting to a high number and use the -1 value like below.
server.servlet.session.timeout=9999999999
spring.session.timeout=9999999999
and
server.servlet.session.timeout=-1
spring.session.timeout=-1
But both do not work.
This is how I configured my security:
protected void configure(final HttpSecurity http) throws Exception {
http
.headers().cacheControl().disable().and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/user").permitAll()
.antMatchers("/api/*").authenticated()
.anyRequest().permitAll()
.and()
.cors()
.and()
.csrf()
.ignoringAntMatchers("/logout")
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.httpBasic()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.clearAuthentication(true);
}
As mentioned, after a few days the application will still timeout and give me an 401 error (even though the cookies still exists) which means the user has to log in again.
Does anyone know how I can make the session really long or indefinitely. And if this is not possible which other solution could I use to solve this problem?
I have a Spring boot web app that serves up both web content and exposes REST Services. The web content is protected by SiteMinder, the REST Services are protected by "Basic Auth".
I using Springs security 4.2.3. My Java code is extending the class WebSecurityConfigurerAdapter, my configure(HttpSecurity) method looks like:
#Override
protected void configure(HttpSecurity http) throws Exception {
RequestHeaderAuthenticationFilter siteMinderFilter = new RequestHeaderAuthenticationFilter();
siteMinderFilter.setAuthenticationManager(authenticationManager());
http
// Error page is for everyone
.authorizeRequests()
.antMatchers("/error.html")
.permitAll()
.anyRequest()
.anonymous()
// Basic Auth for our REST services
.and()
.authorizeRequests()
.antMatchers("/services/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
// Site-Minder protection for the web content
.and()
.addFilter(siteMinderFilter)
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().hasRole(ApplicationConstants.SITE_MINDER_AUTHORITY);
http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
}
Is there something wrong with my configuration? Does my configuration create three separate filters? Maybe my question should be, how do I create the three filters?
When I attempt to call the REST Service using PostMan / "Basic Auth", I get the error message:
org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException: SM_USER header not found in request.
I expect the service to get called, instead I get the SiteMinder filter firing.
I'm using Spring Boot and Thymeleaf. I have a custom 404 template page defined in src/main/resources/templates/error/404.html
This works properly when users are logged in.
However, when they are logged out, they do not get any type of 404 page, they just get redirected back to /login.
I'm thinking my security configuration needs to change but not sure what.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/register*","/resetPassword","/forgotPassword","/login","/404").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().formLogin().loginPage("/login").failureUrl("/login?error")
.defaultSuccessUrl("/dashboard").successHandler(successHandler)
.usernameParameter("email").passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/error**","/resources/**", "/static/**", "/css/**", "/js/**", "/img/**");
}
First of all I encourage you to use indentation when using java config to configure your security for your spring application. It helps with readability.
Note all top level methods on the first indentation (authRequest,formLogin,logout) all configure/update the HTTP object it self. All these elements are from the org.springframework.security.config.annotation.web.builders.HttpSecurity class.
The children of these classes further refine the HTTP security configuration.
http
.authorizeRequests()
.antMatchers("/","/register*","/resetPassword","/forgotPassword","/login","/404")
.permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.anyRequest().authenticated() // <--------
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/dashboard")
.usernameParameter("email").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling()
.accessDeniedPage("/access-denied");
Note .anyRequest().authenticated() is specifically stating that any request must be authenticated. So when you attempt to goto any missing url on your domain it will ask you to login rather than goto the 404 page.
So if you remove that statement it and then try an goto a missing url page it will redirect you to a 404 page.
If you remove .anyRequest().Authenticated() then you can log in without authenticated.
Therefore, do not try to delete. For example, if you go to the address "http://localhost:8080/user", then you will be taken to the authorization page. And if you try to enter the page "http://localhost:8080/user/" then you will be taken to the user page. Please note that links differ only by the forward slash at the end. Of course if you remove ".anyRequest().Authenticated()" in this case you need to add more parameters to antMatchers like "/user" and "/user/"
Therefore, be careful and attentive.
I followed the guide here: http://spring.io/guides/gs/rest-service/ to build my rest service example and now I am trying to enable the CSRF protection. I read that it should be enabled by default, so if I DON'T include:
http.csrf().disable()
in my WebSecurityConfigurerAdapter configuration, the CSRF protectection should be enabled by default, but it does not seem to to be the case. The problem is that the X-CSRF-TOKEN is not generated and not included in my HTTP response in any way.
What am I expected to do, to have the x-csrf-token generated and included in the response and, of course, the csrf protection fully working?
I noticed that, with a similar spring mvc configuration, I get the x-csrf-token generated simply including:
< security:csrf disabled="false"/>
in my security configuration file. But, with spring boot maybe I am getting something wrong and there is no way to have the csrf token generated. Can anybody help me, perhaps pointing me to a working example? My security configuration is:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
// .csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.formLogin()
.successHandler(new RestAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutSuccessHandler(new RestLogoutSuccessHandler());
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(restUserDetailService);
}
To include the CSRF Token in your csrf protection, you can include CSRFTokenRepository to generate tokens. To illustrate in your case adding a simple line is enough:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) //HERE ! Defaults XSRF-TOKEN as cookie name and X-XSRF-TOKEN as header name
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.formLogin()
.successHandler(new RestAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutSuccessHandler(new RestLogoutSuccessHandler());}
Using Spring security 5.3.0.Final, one of the ways you can generate the CSRF token is by setting it in the cookie using the following code below.
http.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
You also need to include the generated CSRF token in your request for the server to authorize.
<form>
<input type="hidden" name="_csrf" value="${cookie['XSRF-TOKEN'].getValue()}" />
//Code goes here
</form>
In the event you're using a JS framework, you need to include the token by setting it in the request header.
Here is an example for a JQuery ajax call.
// Get the CSRF token from the cookie
const csrfCookie= document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$)|^.*$/, '$1');
// Add the CSRF token to each ajax request header
settings.beforeSend = function(xhr) {
xhr.setRequestHeader('X-XSRF-TOKEN', springCsrfCookie);
};
$.ajax(settings);
There are other implementations that will suit your needs documented in the following link by Spring | https://docs.spring.io/spring-security/site/docs/5.3.0.RELEASE/reference/html5/#servlet-csrf
We had pretty similar issue during our security tests where we suspected that we accidentally disable csfr in configure method of websecurityconfig class,by default it is enabled. by changing the congfigure method as shown below , we had spring automatically generate csfr tokens.
websecurityconfig class configure method==>
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/login","/loginError","/home","/interruption").permitAll()
.antMatchers("/admin").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.HALLEYYNT01.role())
.antMatchers("/requests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.CCHALLEYLOGIN.role())
.antMatchers("/solrequests").hasAuthority(Roles.ROLE_PREFIX.role()+Roles.SOLHALLEYLOGIN.role())
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
//.failureUrl("/loginError")
.loginProcessingUrl("/authenticate")
.defaultSuccessUrl("/")
.and()
.logout().clearAuthentication(true).invalidateHttpSession(true).deleteCookies("JSESSIONID")
.logoutSuccessUrl("/login");
//.and()
//.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
}