How to allow all resources in static folder of spring boot maven using spring security? - spring-boot

I am creating a app using angular for frontend and spring boot for backend.
I am using spring-boot-security for the security purpose.
Spring boot serves static content from src/main/resources/static folder.
I am placing all the contents of angular dist folder here, i.e. all js,css,html produced by ng build.
But upon running the app, I keep on getting a 401 unauthorized error.
Here is my configure() method:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors()
.and()
.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/api/v1/login/").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(getJWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()));
}
If I add .antMatchers("/**").permitAll() then the app will load all angular resources correctly but makes the security then useless as all api endpoints are then exposed.
Also I read that \css,\images,\js etc. are allowed by default, but here my I just refer to static folder.I also tried moving all the content to a new endpoint, say /app by implementing addResourceHandlers() method, but then my angular code breaks, since it references all css,jss directly in its href and not behind any folder name.
I am using spring boot 2.1.1 release and most of the answers refer to spring boot v1, and I am unable to find a soln.
I want to configure spring security to allow access to just all resources under static folder. Doing so will allow me to use my angular code without changing all hrefs. How can I achieve this?

Related

Spring security is blocking Vue.js pages | receiving 403 error

I have a Spring/Vuejs project that couples the frontend and backend into one warFile and for some reason the Spring Security setup I have blocks the Vue.js pages when I run the warFile.
When I have the Configuration set this way, it blocks the pages -
#Override
public void configure(HttpSecurity security) throws Exception {
security.csrf().disable()
.cors().and()
.authorizeRequests()
.antMatchers("/api/v1/authenticate", "/api/v1/register").permitAll()
.anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
security.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
When I have it set up this way, it shows the pages AND the data from my api's (it creates the JWT but still allows the api calls without Authorization) -
#Override
public void configure(HttpSecurity security) throws Exception {
security.csrf().disable()
.cors().and()
.authorizeRequests()
.antMatchers("/api/v1/authenticate", "/api/v1/register", "/**","/css/**","/js/**").permitAll()
.anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
security.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
When I have it setup the first way and run the frontend and backend on different ports, it works perfectly. It shows the pages and blocks all API calls that don't have an authorized JWT.
I want the same type of result with backend/frontend in the same warFile
Is there a solution for this???
When I have it setup the first way and run the frontend and backend on different ports, it works perfectly.
I wonder if this is due to the CORS policy being invoked. Otherwise, Spring Security doesn't take the port number into consideration when making authorization decisions.
When I have the Configuration set this way, it blocks the pages -
That's because you have this line:
.anyRequest().authenticated()
It means that any URL, including JS files, will require authentication.
When I have it set up this way, it shows the pages AND the data from my api's
That's because you have this line:
.antMatchers("/**").permitAll()
It means that any URL is permitted.
The DSL processes URLs in the order the paths are declared. I think you want a hybrid of the two. Something like this:
.antMatchers("/api/v1/authenticate", "/api/v1/register", "/css/**","/js/**").permitAll()
.anyRequest().authenticated()
This means that the two /api endpoints all /css endpoints and all /js endpoints won't require authentication, but everything else will.
Consider making the permitAll as narrow as you can -- it's not clear to me whether you really want all your JS files to not require authentication.
#jzheaux your root comment led me to the answer.
This was the change I made and it works just as I need it to now. Thanks for the guidance!
#Override
public void configure(HttpSecurity security) throws Exception {
security.csrf().disable()
.cors().and()
.authorizeRequests()
.antMatchers("/api/v1/authenticate","/api/v1/register","/static/**","/").permitAll()
.anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
security.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

Google drive API access for aplication testing

I am working on an application which uses Google Oauth2 token and the purpose of application is to download specific file from logged user's Google Drive. I am wondering if there is any chance to test that before going to production environment. I've enabled Google Drive API in Google Cloud Platform created Oauth 2.0 Client ID.
I've got web application created using Java and Spring and authorisation works good. I do receive Oauth 2.0 token from Google Sign In but when I add a scope for Google drive which is the same one added in GCP I do receive following error:
Below is spring security google scope:
spring.security.oauth2.client.registration.google.scope=https://www.googleapis.com/auth/drive.readonly
And the spring security config:
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.csrf()
.disable()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/styles/**", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/goodbye");
}
}
I found some information that if the registered application in GCP has sensitive scope it should goes through validation process but I want to test it first before going to production that's why I've left that in Testing Oauth consent and added testing user but it doesn't work.
Any ideas what might be wrong?
Reproducible example:
Register app in GCP.
Enable Google Drive API and generate Oauth2 credential.
Add auth/drive.readonly scope.
Set consent status to testing and add testing user.
Create Spring Boot app with Spring Security.
Add scope:
spring.security.oauth2.client.registration.google.scope=https://www.googleapis.com/auth/drive.readonly
Run app and authenticate with Google Sign in.

How do I use multiple 'JWK Set Uri' values in the same Spring Boot app?

I have a requirement to use two different authorization servers (two Okta instances) to validate authentication tokens coming from two different web applications inside a single Spring Boot application which is a back-end REST API layer.
Currently I have one resource server working with the following configuration:
#Configuration
#EnableWebSecurity
public class ResourceServerSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests().antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
}
}
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-X.okta.com/oauth2/default
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://dev-X.okta.com/oauth2/default/v1/keys
and with dependencies spring-security-oauth2-resource-server and spring-security-oauth2-jose in my Spring Boot app (version 2.2.4.RELEASE)
The end state I want to get into is, depending on a custom HTTP header set in the request, I want to pick which Okta instance my Spring Boot app uses to decode and validate the JWT token.
Ideally I would have two properties in my configuration file as follows:
jwkSetUri.X=https://dev-X.okta.com/oauth2/default/v1/keys
jwtIssuerUri.X=https://dev-X.okta.com/oauth2/default
jwkSetUri.Y=https://dev-Y.okta.com/oauth2/default/v1/keys
jwtIssuerUri.Y=https://dev-Y.okta.com/oauth2/default
I should be able to use a RequestHeaderRequestMatcher to match the header value in the security configuration. What I cannot workout is how to use two different oauth2ResourceServer instances that goes with the security configuration.
With spring boot this is not possible to do out of the box right now.
Spring Security 5.3 provides functionality to do this (spring boot 2.2.6 still doesn't support spring security 5.3).
Please see following issues:
https://github.com/spring-projects/spring-security/issues/7857
https://github.com/spring-projects/spring-security/pull/7887
It is possible to do manual configuration of resource server to use multiple identity providers, by following links that i have provided. Provided links are mainly for spring boot webflux development. For basic spring boot web development please see this video:
https://www.youtube.com/watch?v=ke13w8nab-k
This is possible as of Spring security 5.3+ using the JwtIssuerAuthenticationManagerResolver object
Override the configure(HttpSecurity http) inside your configuration class which extends WebSecurityConfigurerAdapter
JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver(
"http://localhost:8080/auth/realms/SpringBootKeyClock",
"https://accounts.google.com/o/oauth2/auth",
"https://<subdomain>.okta.com/oauth2/default"
);
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/user/info", "/api/foos/**")
.hasAnyAuthority("SCOPE_email")
.antMatchers(HttpMethod.POST, "/api/foos")
.hasAuthority("SCOPE_profile")
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));

Spring Boot with themeleaf not able to access css on HTML file

Technology : Spring Boot with themeleaf
I'm trying to access the css file placed under src/main/resources/assets/vendor/bootstrap/css/bootstrap.css on my HTML using the following code:
But it is not loading.
Folder Structure :
Resources
--->assets
------>vendor
--------->bootstrap
------------>css
--------------->bootstrap.css
--->code
Can any one help me in this?
Here is my spring security config,
http.
csrf().disable()
.authorizeRequests()
.antMatchers("/home/**", "/**", "/css/**", "/js/**", "/fonts/**", "/images/**", "/public/rest/**","/login*","/signin/**","/signup/**").permitAll()
.antMatchers("/property/**").authenticated()
.antMatchers("/welcome/**").authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and().httpBasic().disable();
Simply you need this line,
.antMatchers("/home/**", "/**", "/css/**", "/js/**", "/fonts/**", "/images/**", "/public/rest/**","/login*","/signin/**","/signup/**").permitAll()
But, I would suggest to disable security first and check if everything is working. If that works, then reenable security and try to configure it like shown.
From my working project. The resources is under resources/static/js/script.js. And I am accessing it from html like js/script.js. No issue. Probably you are missing static folder. And if you are using spring security, you need to make the resources available.

spring security and VAADIN

I am developing my spring boot app which is protected by spring security. Here is part of secured config:
#Override
public void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
// .csrf().ignoringAntMatchers("/dashboard")
// .and()
.httpBasic()
.and()
.headers().frameOptions().disable()
.and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/VAADIN/**", "/PUSH/**", "/UIDL/**").permitAll()
.antMatchers("/vaadinServlet/UIDL/**").permitAll()
.antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority(Authority.Type.ROLE_ADMIN.getName())
.antMatchers("/", "/login**", "/index.html", "/home.html").permitAll()
.and()
.logout().logoutSuccessUrl("/").permitAll()
.and()
.csrf().csrfTokenRepository(csrfTokenRepository())
.and()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// #formatter:on
}
I am going to implement some admin dashboard to manage my app using VAADIN.
I have read that "Disable CSRF-protection in either Spring or Vaadin. If you have both turned on, your application will not work.".
In my case I need to disable CSRF-protection in Vaadin, but I could not find how can I do it using Java config.
For this moment I am getting: https://127.0.0.1:8443/vaadinServlet/UIDL/?v-wsver=7.5.5&v-uiId=0 "Communication error: UIDL could not be read from server. Check servlets mappings. Error code: 403", during navigation from the main view to other views. (e.g: /dashboard#!myview). This because AccessDeniedHandlerImpl handle method is invoked. I have try to fix this using following statements but it doesn't help:
.antMatchers("/vaadinServlet/UIDL/**").permitAll()
.antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
So, please help me to solve this two issues:
Disable CSRF in VAADIN using java config.
Solve problem with view navigation.
Thanks
To fix the above issues, I have decided to divide my project into two modules. First is API app, which has own implemented security configuration. Second is Dashboard, which has both Spring Security integrated with Vaadin4Spring based on this sample.

Resources