In a Spring Secuity / Boot application I have multiple #Configuration annotated Configurations that extend WebSecurityConfigurerAdapter.
In one of these specific configurations, I want to protect a specific URL with basic auth. I do that by overriding configure(final HttpSecurity) and using antMatcher("myURL") onto the HttpSecurity object, followed by the usual authorization-chain and httpBasic().
But configuring basic auth in spring also requires your configuration to override configure(final AuthenticationManagerBuilder auth), where you configure an authentication-mechanism, as I understand. In my case, that is a simple inMemoryAuthentication(), with user and password of my choice.
Now, I know that some of the other configurations in the project configure the rest of the urls with a way more complex authentication-mechanism, which implement's SSO. I am not entirely sure if my configuration, which messes with the AuthenticationManagerBuilder, interferes with these other mechanisms in any way?
My expectation is that, because in configure(final HttpSecurity) I use antMatcher("myURL"), this configuration will create a SecurityFilterChain that has my specific inMemoryAuthentication() logic (somewhere deep in a spring filter that handles basic auth) and that this chain will only be used for the requests matching "myURL" pattern. I expect other filters-chains that are created by other other existing configurations and their more complex authentication mechanisms to be unaffected by my new configuration. My new inMemoryAuthentication should never play a role there. Is that correct?
Related
I am trying to implement Spring basic auth into the app. I added the folowing lines to application.properties:
#Security
security:
user:
name: admin
password: admin
So the Spring will create a web security config bean by itself. But I ran some tests and everything works as expected for any method besides POST as it throws 403 status. I browsed the web and discovered that it happens due to csrf protection and I disabled it, creating additional web security config class:
#EnableWebSecurity
public class WebSecurityConfig {
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
return http.build();
}
}
However, it completely disables the authentication. The user does not need a password and a login to use the resources.
My question is, how do I configure the authentication in a way POST method will not throw 403? Do I need to write a full web security config and delete those 4 lines from application.properties or there is an alternative way? Thanks in advance.
I have rest API where I need to secure some (UI facing) endpoints with OKTA authentication, and others (backend-facing) with Azure Active Directory. I managed to do it separately (either I can secure the endpoints with OKTA or AAD), but they don't want to work together. As soon as I add okta-spring-boot-starter to POM (or okta-spring-security-oauth2) - AAD security stops working and endpoints are either open or secured with OKTA only. I am trying to do it using WebSecurityConfigurerAdapter implementations for okta and aad:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig {
#Configuration
#Order(1)
public static class OktaAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/v1/endpoint1").authenticated()
.antMatchers("/v1/endpoint2/**").authenticated();
}
}
#Configuration
#Order(2)
public static class ActiveDirectoryAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private AADAppRoleStatelessAuthenticationFilter filter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/endpoint3/**").authenticated()
.antMatchers("/v1/endpoint4/**").authenticated()
.and()
.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
}
}
This configuration however works only for endpoint1 and endpoint2 (secured with okta), other rest points are open (as if 2nd implementation of WebSecurityConfigurerAdapter was ignored). If I remove okta package from pom, AAD configuration starts working. If I switch orders of above configurations then nothing is secured. I suspect okta package does some autoconfiguration, but can't find any information about it. What am I missing?
The Okta Spring Boot Starter is mostly just a light wrapper to help configure the existing Spring Security OAuth autoconfig with a few Okta specific bits.
My first suggestion (if possible) is to try to use Spring Security OAuth for both IdPs, as it doesn't look like the AAD starter works Spring Security's built-in OAuth support (I could be wrong, I only took a quick look). Assuming AAD is just OAuth/OIDC it will just work with a little bit of configuration.
You will still need a solution to protect your given routes 1 & 2 -> Okta 3 & 4 AAD. There are a few ways to do this. You could use scopes (assuming they are different) or some other type of "authority":
http.authorizeRequests()
.antMatchers("/your/route").hasAuthority("SCOPE_custom");
The Okta Spring Boot Starter should work with other IdPs configured with Spring Security OAuth properties: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login-boot-property-mappings
I cannot speak 100% to what the ADD starter adds, but I'm guessing it's similar to Okta. Which is:
A common set of properties (inline with other vendor offerings)
Vendor-specific JWT validation (Spring Security only does basic JWT validation, and each vendor has its own recommendations, assuming you are using JWT access tokens)
A little sugar (for example the Okta starter adds a mapping of Okta groups to Spring Authorities)
As far as JWT validation goes Okta recommends validating JWTs like this:
https://scotch.io/tutorials/jwt-vs-opaque-access-tokens-use-both-with-spring-boot#toc-better-jwt-validation
A similar technique could be used (if needed).
Keep us posted!
I have migrated a Spring Boot web application from 1.5.10 to 2.0.0, which is deployed with Heroku and runs over several domains. For the main domain, that was the first one to be set, everything is working smoothly but for the rest any of the static resources; like Javascript, CSS, images and icons (Webjars) are not accessible.
maindomain.com/js/example.js works fine and can be directly accessed with the browser. secondarydomain.com/js/example.js can't be accessed by the browser and running the app arises this error, I guess because instead of the .js file is returning some text message:
Refused to execute script from '' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled
The static resources are located at:
/resources/static/css
/resources/static/js
/resources/static/images
I have set the Spring security configuration with an extension of WebSecurityConfigurerAdapter, where I have withdrawn the annotation #EnableWebSecurity and I have added this code, with the intention to make sure that those resources are accessible, without success:
http
.authorizeRequests()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
There is a HandleInterceptor, which deals with the directories accessible by each secondary domain. The main one, has access all over the application.
In this other question, with a different approach to the same problem, there is an extract of the HandleInterceptor.
Spring Boot 2.0.0 & static resources with different domains for the same app
Spring Security with boot is on the classpath, the auto-configuration secures all endpoints by default.
However, when it comes to complex applications, we need different security policies per endpoints. We also need to configure which endpoints should be secured, what type of users should be able to access the endpoints, and which endpoints should be public.
WebSecurity allow we to configure adding RequestMatcher instances that Spring Security should ignore.
HttpSecurity allow we can configure the endpoints that should be secured and the endpoint that should be public
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/image/**"").permitAll()
}
}
Hope it help.
I have created an oauth module for my project.
It has the mechanism for authorization server, spring security and the resource server.
I need some of the end-points to be accessible only on authorization, so I configured the security in the resource-server:
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatcher(new OrRequestMatcher(new AntPathRequestMatcher("/secured/**")))
.authorizeRequests().anyRequest().authenticated();
}
So far access-token/refresh-token calls are working fine.
Now, I want to create a separate module for all the webservices API - where I would put all the controllers and the logic for processing the requests.
Is it advisable to do it in a different module than oauth?
If yes, how can I secure the calls and verify the tokens? How can I use the resource server in another module.
If the oauth module is where your spring boot app is you could add #ComponentScan("webservices API") to let it know where your api controllers are. Take a look at this question which may have your answer:
NOTE: My application uses the latest version of the Spring framework, 4.0.6, 3.2.4 for security, and, it uses no xml but only Java-Config to configure the application.
I have a set of services which I would like to secure with roles and other business specific authorization conditions. This services are grouped into a module (a jar) which is used by a REST application and a web application. I already have an AuthenticationProvider in the web application (REST application is in initial phase). I use #EnableGlobalMethodSecurityin the web application. Having said that, I now need to secure the methods in the services too. In that case, do I need to provide another authentication provider? Or, is right to move the authentication provider to the services module so that the web/rest apps uses the authentication provider in the services jar? If I configure #EnableGlobalMethodSecurity in the ApplicationServiceConfig.java of the services module, I get the blow exception.
com.name.mvoice.project.service.ApplicationServiceConfig: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: An AuthenticationManager is required
How do I configure the security if the application requires double authentication, one from the RDBMS and the other from the LDAP. The condition should be that the user information should be present and be enabled in both the systems. Do I need to write this in the existing authentication manager itself or shall I provide separate auth provider for the LDAP? If so how?
WebSecurityConfig.java
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
AuthenticationProvider dbAuthenticationProvider = new DatabaseAuthenticationProvider();
auth.authenticationProvider(dbAuthenticationProvider );
// is it right to do like this
AuthenticationProvider ldapAuthenticationProvider = new LDAPAuthenticationProvider();
auth.authenticationProvider(ldapAuthenticationProvider );
}
Though, I seeAuthenticationManagerBuilder.authenticationProvider adds the supplied authenticationprovider to a list!
No, this won't give you the desired result. The default Spring Security implementation uses only one AuthenticationProvider at a time. Your second call to auth.authenticationProvider() would force Spring Security to use just the LDAP provider.
To achieve what you want
Step 1: Create a class of your own, say
public class CompositeAuthenticationProvider implements AuthenticationProvider {}
Step 2: Then, inject the Database and LDAP providers into it.
Step 3: In the authenticate method of the class CompositeAuthenticationProvider, orchestrate the request between the Database and LDAP providers as you see fit. Return a response based on the results you obtain from both the providers.