I want to make a config file to configure TLS and Oauth2 in my SecureConfig.java
The tls config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
The Oauth2.0 config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requiresChannel()
.anyRequest()
.requiresSecure();
}
What is the better way to use these two in the same config file and method? Does the and() work fine?
Like that:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER).and()
.requiresChannel()
.anyRequest()
.requiresSecure();
}
Issue with your two filter chain approach (Regardless of what your configure inside the methods
Spring security is a chain of filters see Filters in Spring Security Filter Chain
By implementing configure(HttpSecurity http) twice, you have created two spring-security-filter-chains.
Since you are not providing http.requestMatcher(...), both chains are applicable to every url. And it is a problem for spring security as it will only apply one filter chain to a particular request. So if you try to start up your app, it will fail to start with an error
You can make your app start by defining an #Order annotation so spring security chooses the one with the lower number applicable for a url. But since both chains are applicable to every url as per your config, the filter chain with lower #Order overrides the filter chain with higher #Order making it useless
Solution
Use one class that extends WebSecurityConfigurerAdapter so you have one security filter chain
Channel Security vs Authentication vs Authorisation
Security is mainly 4 aspects. Authentication, Authorisation, Integrity and Confidentiality. Rest API under https security
What you have in the filter is about authentication. You may have also defined some urls need some roles which is Authorisation. So that config was about those 2 aspects
By requiresSecure() you are addressing Confidentiality. i.e If you use requiresSecure() without the first one, you know you are not talking to some middle man but you won't know who you are talking to because that is what the purpose of authentication.
Since they are complimentary security aspects, They can be combined together and spring will create one filter chain where the first filter ensures you are first talking over https by placing ChannelProcessingFilter as the first barrier
Related
i am trying to implement a simple Spring security project but I am facing an issue where the behavior of http.authorizeRequests().anyRequest().authenticated(); is not understandable. what i expect from this method is to prevent all incoming requests until the user is authenticated but in my case all the requests are go through and no interception happened. the normal behavior of preventing request to go through took a place when I un-comment the lines which include hasAnyAuthority.
Below is My security configs
#Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthFilter customAuthFilter = new CustomAuthFilter(authenticationManagerBean());
//override behavior of url for our api
customAuthFilter.setFilterProcessesUrl("/api/login");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/api/login/**").permitAll();
http.authorizeRequests().antMatchers("/register/**").permitAll();
/////http.authorizeRequests().antMatchers(GET,"/api/users/").hasAnyAuthority("ROLE_USER");
//////http.authorizeRequests().antMatchers(POST,"/api/user/save/**").hasAnyAuthority("ROLE_ADMIN");
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(customAuthFilter);
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
i have resolved the issue , it was just a miss-understanding of how authenticated method works.
so first Spring security checks if the user authenticated and and then checks if this endpoint need any type of authorization. if authenticated and not authorization exist the user would be redirected to the endpoint. it make sense for me now.
Thank you.
While configuring the security of my Spring Boot application, I wanted to secure parts of the API depending on the PathVariable that is entered there. My current configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//not important
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors();
http.authorizeRequests()
.mvcMatchers("/api").authenticated()
.mvcMatchers("/api/TEST").hasAuthority("SCOPE_dep:TEST")
.and().oauth2ResourceServer().jwt();
}
}
In the the 'api/{PathVariable}' endpoint is the one I want to have customized, making sure that someone with the authority 'SCOPE_dep:TEST' can access the 'api/TEST' endpoint, someone with 'SCOPE_dep:TEST2' authority can access the 'api/TEST2' endpoint, even allowing more then one such endpoint for a user which has multiple of these authorities.
Is there a way to do this by using a type of wildcard/matcher that I'm unaware of, or is the only possiblity hardcoding all these different authorities?
I added to spring config my own custom filter:
#Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(filter, BasicAuthenticationFilter.class);
http.csrf().disable();
http.authorizeRequests().antMatchers("/oauth/token").fullyAuthenticated();
}
but doFilter(...) doesn't invoke. I need to proccess request before it will be "eaten" by spring-security-oauth. How to make it work?
According to the documentation, addFilterBefore configuration method "allows adding a filter before one of the known Filter classes. The known Filter instances are either a Filter listed in HttpSecurityBuilder.addFilter(Filter) or a Filter that has already been added using HttpSecurityBuilder.addFilterAfter(Filter, Class) or HttpSecurityBuilder.addFilterBefore(Filter, Class)"
HttpSecurity documentaion
This basically means that your filter will be applied if and only if BasicAuthenticationFilter is already registered to process your requests, which is probably not.
Disclaimer: My question is somewhat similar to this question and this question, but I have tried all the answers suggested in those threads and already spent few days struggling with the problem.
I am introducing Spring Security 3.2.6 in my existing application (JSP, Servlet only) and I am using Java configuration. My application will be used both by browsers and non-browser clients. I want all the browser requests to URLs (i.e. /webpages/webVersion/ and /webpages/webVersion2/) to be CSRF enabled and all the other requests to be CSRF disabled. Non-browser clients never access above two URLs, whereas the browser application may also access CSRF disabled URLs.
I have tried a variety of options:
Enable Spring Security only on the aformentioned URLs:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/resources/****").permitAll()
.antMatchers("/webpages/webVersion/****", "/webpages/webVersion2/****").authenticated()
.antMatchers("/webpages/****").permitAll()
.anyRequest().anonymous()
.and()
.formLogin().loginPage("/webpages/webVersion/login/newLogin.jsp").failureUrl("/webpages/webVersion/login/newLogin.jsp?error=true").loginProcessingUrl("/j_spring_security_check")
.usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/webpages/webVersion/login/loginSuccess.jsp", true).permitAll()
.and()
.logout().logoutUrl("/webpages/webVersion/logout.jsp").permitAll()
.and().exceptionHandling().accessDeniedPage("/webpages/webVersion/404-error-page.jsp")
.and()
.csrf();
}
This didn't work as I observe that CSRF is enabled for all of the URLs.
Tried using CSRFProtectionMatcher:
.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);
CSRF is enabled for intended URLs only, but even /resources/** and /webpages/** URLs need to be checked inside matches function. Seems to be a bit much considering it will be for all requests.
Tried using another version of the configure method:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().regexMatchers(".*?/jsp/(?!webVersion|webVersion2).*?");
}
I am not sure whether I did it correctly but this didn't produce the results I wanted.
Which of the above approach is the correct (Spring Security) way of doing what I want? How can I achieve the desired behavior from my Spring Security configuration?
It turned out that their was some error with my configuration and finally I achieved the objective using approach 3.. I used below version of the configure function along with the usual configure(HttpSecurity http) function..
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().regexMatchers(".*?/jsp/(?!webVersion|webVersion2).*?");
}
I am writing an LTI application using Spring boot. LTI applications are basically a plug-in for a learning management system (in this case Canvas) which work by sending an Oauth1 signed POST to my server. The result of this request is displayed to the user inside of an iframe. There is a pre-shared key and secret that the LMS uses to sign the request. If the signature on the POST checks out, I have an authenticated user. I have this part working, partially based on this question.
During the initial request (which comes to the URL "/launch") I can call SecurityContextHolder.getContext().getAuthentication() and use this without problems. My problem is when the user makes another request, say for a picture or by clicking on a link in my content, the SecurityContext object isn't following them. I'm pretty sure I'm not setting up the Spring security filter chain correctly so the SecurityContextPersistenceFilter isn't being hit on subsequent requests. At the end of the day, SecurityContextHolder.getContext().getAuthentication() returns null.
The OAuth signature verification happens in a WebSecurityConfigurerAdapter like so: (again, based on this)
#Configuration
public static class OAuthSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
//spring auto-wiring to set up the
//zeroLeggedOauthProviderProcessingFilter (see linked question)
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/launch")
.addFilterBefore(zeroLeggedOAuthProviderProcessingFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests().anyRequest().hasRole("OAUTH")
.and().csrf().disable();
}
}
So this works and creates an authenticated principal and everything. But due to that antMatcher, it only applies to the /launch path.
It seems like it should be simple to add another security configurer adapter that will ensure that all other paths in the application are protected by an authenticated session and in so doing would cause the SecurityContext associated with this user to become available but I have been unable to come up with the magic sauce. The documentation focuses more on standard login form based authentication setups. I'm also kind of new to Spring in general so I'm clearly missing something. I tried this but it causes all other requests to return a 403:
#Configuration
public static class SessionSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().hasRole("OAUTH")
.and().csrf().disable();
}
}