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

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

Related

adding httpSecurity.csrf().disable() to spring security configuration is allowing unauthenticated endpoint calls

I have the following security configuration for my springboot project
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/test_url_1");
}
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/");
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
now I have another endpoint /test_url_2. Calling which should be redirected to error page for an unauthorized user. If am removing csrf().disable() its working fine and the request is going to default /error page. but on adding csrf().disable() ,I am noticing a very unusual behaviour. once another endpoint ex. /test_url_3 is being called with an jwt header for authorization, next time onwards the endpoint(/test_url_2) is blocked even for unauthorized user, i.e. instead of going to the error page its calling the end point.
I am still new to spring security and spring, and not sure if I am writing some configuration wrong, please help me with the issue.
I didn't get exact meaning of the following sentences:
I am noticing a very unusual behaviour. once another endpoint ex. /test_url_3 is being called with an jwt header for authorization, next time onwards the endpoint(/test_url_2) is blocked even for unauthorized user, i.e. instead of going to the error page its calling the end point.
If you didn't get what exactly CSRF I recommend watching this video: https://youtu.be/uzZzlar-iQI from 1:08:00. If you want to authenticate url1 and don't want to authenticate url2 try the following code instead of using anyRequest().
httpSecurity.csrf().disable()
.authorizeRequests()
.antMatchers('/ur1')
.authenticated()
follow through this URL for more info on CSRF: https://www.baeldung.com/spring-security-csrf

How can I allow public access to parts of Spring Security app using permitAll?

I'm trying to get a Spring application to allow some requests to public (without login) and some requests to private (with login).
At this point I'd like to just get the public part to work properly.
I have tried most of the example configurations listed on the Spring Security documentation, including all sorts of combinations of anonymous(), and permitAll(). All end up redirecting to the login page.
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers("/resources/**", "/signup", "/about","/api/home").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated()
.and()
// ...
.formLogin();
}
Expected result: items under permitAll() are accessible without logging in
Actual result:
redirect to login page. This shows up in the log: 2019-06-06
17:29:43.593 INFO 56330 --- [ main]
o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any
request, [org.sprin...
This leads me to believe that it isn't even reading this configuration. Is there any way to fix this?
Thanks!
UPDATE: I tried adding the websecurity ignores, and it doesn't appear to be working still. It appears to still print the "defaultsecuritychain" error so I feel like this may have something to do with it.
UPDATE 2: Added application.properties file under src/main/resources with this line logging.level.org.springframework.security=DEBUG to make it log debug messages.
pastebin.com/2u9k7eHD
Have a look at http://blog.florian-hopf.de/2017/08/spring-security.html, it may explain your use-case in more detail.
My recommendation is to try and use WebSecurity for static and public resources
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/signup", "/about","/api/home");
}
You can achieve your requirements with below configurations. It's a good way to use the URLs which does't require Authentication/Authorization to be placed in WebSecurity using ignoring instead of HttpSecurity as WebScurity will bypass the Spring Security Filter Chain and reduce the execution time
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/signup", "/about","/api/home");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated()
.yourConfigurations
}
When you use HttpSecurity and try to permitAll() requests. Your requests will be allowed to be accessed from the Spring Security Filter Chain. This is costly as there will be requests other requests which would also come into this filter chain which needs to be allowed or disallowed based on Authentication/Authorization
But when you use WebSecurity, any requests to "/resources/**", "/signup", "/about","/api/home" will completely by pass the Spring Security Filter Chain all together. It is safe because you don't need any Authentication/Authorization to be in place to see an image or read a javascript file.
Turns out that I was missing the #SpringBootApplication annotation all along in one of my source files. Make sure that's in there and perhaps it will work.
Thank you to all who replied!

How to allow certain endpoint in spring security to be allowed without authentication?

I have Spring Boot Rest API web app in which I am using spring security to have most endpoints to require authentication.
This is part of code:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
....
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
}
Can some one explain what each line begining with http.csrf means?
How can I modify above code so that enpoint /bars/pk can be allowed to be accessed without requiring authentication just as if there was no Spring Security ?
By default, Spring Boot activates protection against CSRF attack (Cross Site Request Forgery attack). The attack consists of a malicious site taking advantage of a user being alredy authenticated to a site (e.g. bank) in order to trick the user to do actions on that site (e.g. fund transfer).
The protection against the attack consists of the Spring Boot application sending a token with every response and expecting the token to be sent by the client on subsequent request. If the token is not received, Spring Boot returns an error.
Sometimes, you want to disable this behavior (at your own risks), so you use csrf.disable. You might find it convenient to disable csrf protection if you develop a Stateless API, and you have no way to link a POST request to any previous requests or session. But again, you need to consider this and reason about it carefully.
Please note that CSRF protection has not effect on GET requests. It only affects state chaning requests (e.g. POST, DELETE)
In order to allow your endoints to anyone, without requiring any authentication, you need to use
http.authorizeRequests().antMatchers("/**").permitAll();
EDIT
To specifically allow unauthorized requests to /bars/pk and keep the other elements unchanged, modify your code as follows :
http.csrf().disable()
.requestMatchers()
.antMatchers("/oauth/token")
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/bars/pk").permitAll()
.anyRequest().authenticated();
Here is a complete example:
httpSecurity.authorizeRequests()
.antMatchers(HttpMethod.GET)
.permitAll() // Allow all GET requests to go unauthenticated
.antMatchers(allowedResources)
.permitAll() // Allow all requests to go unauthenticated for the specified paths
.antMatchers(protectedResources).hasRole(USER)
.antMatchers(adminResources).hasRole(ADMIN)
.anyRequest().authenticated(); // Authenticate all other request paths

Spring security antMatchers permitAll doesn't work

I know that there are topics with this problem, but the config which I made is correct and I compared it to a project where it works correctly.
I want to "unsecure" a /login endpoint for JWT security, but still the AuthenticationFilter runs before reaching the /login endpoint.
I'm confused why it is no working.
My Code Below :
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
http
.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
Duplicate: How to add a filter only for one special path WebSecurityConfigurerAdapter
You can't do that with a single Configuration class. Take a look at this question: How to apply spring security filter only on secured endpoints?.
In this case, I think the better solution is to configure multiple HttpSecurity. From Spring IO documentation:
We can configure multiple HttpSecurity instances just as we can have
multiple blocks. The key is to extend the
WebSecurityConfigurationAdapter multiple times. For example, the
following is an example of having a different configuration for URL’s
that start with /api/.
The documentation has a full example with the necessary steps to accomplish this:
Configure Authentication as normal
Create an instance of WebSecurityConfigurerAdapter that contains
#Order to specify which WebSecurityConfigurerAdapter should be
considered first.
The http.antMatcher states that this HttpSecurity
will only be applicable to URLs that start with /api/
Create another instance of WebSecurityConfigurerAdapter. If the URL does not start with /api/ this configuration will be used. This
configuration is considered after ApiWebSecurityConfigurationAdapter
since it has an #Order value after 1 (no #Order defaults to last).
Good luck!

Spring boot security, applying an authentication filter only to certain routes

I'm building a web application which will contain an API and an admin interface in a single application. As a result, I need two types of authentication, token based auth for the API, and form based auth for the admin interface.
I've almost got it working by applying a filter to authenticate API tokens, however the filter is being executed for every request, and I only want it to be executes on paths matching '/api/**'.
Hopefully it's clear from my security configuration what I'm trying to do, but sadly it doesn't work as expected.
All API requests will start '/api/', while all admin interface requests will start '/admin/'. So I was hoping to apply different security rules to each.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/account/login").permitAll();
http.addFilterBefore(webServiceAuthenticationFilter, UsernamePasswordAuthenticationFilter.class).authorizeRequests().antMatchers("/api/**").hasAuthority("APIUSER");
http.authorizeRequests().antMatchers("/admin/**").authenticated().and()
.formLogin()
.loginPage("/admin/account/login").permitAll()
.passwordParameter("password")
.usernameParameter("username")
.failureUrl("/admin/account/login?error").permitAll()
.defaultSuccessUrl("/admin/dashboard")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/account/logout"))
.logoutSuccessUrl("/admin/account/login");
http.exceptionHandling().accessDeniedPage("/admin/account/forbidden");
}
There is a way to configure several HttpSecuritys depending on the url by using the antMatcher (or in more advanced cases requestMatchers) on the HttpSecurity directly (not on authorizeRequests!). See: https://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/config/annotation/web/builders/HttpSecurity.html#antMatcher-java.lang.String-
This requires defining several WebSecurityConfigurerAdapters with defined #Orders such that Spring uses the first appropriate configuration depending on the given url and the order of the configurations. For more details please take a look at the docs at http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#multiple-httpsecurity
I don't know if this is the 'correct' way of doing it, but I've managed to only get the filters code to execute when a route is matched with '/api/**' by adding an if statement to the filter itself;
So within my filter I have the following;
AntPathMatcher urlMatch = new AntPathMatcher();
if (urlMatch.match("/api/**", httpRequest.getRequestURI().substring(httpRequest.getContextPath().length()))) {
// Token authentication in here
}

Resources