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.
Related
I'm trying to get the user session managed with a OAuth2 provider and I made a custom login that made the calls, set the cookies etc... But then I realized that Spring Boot Security has OAuth2 integration and I decided to start from scratch and do it the right way.
The problem is that, for any secured path I access, I get redirected to the service, I log in in there, and then I get redirected back to my callback url, with the code as param and I get the template as usual, going through the controller, not getting authorized on my application at any point.
Before I used this code to access the API but as I understand now Spring should be managing it.
So, I autenticate, I get redirected again into my page (my callback url is permited for all users) and then I am at the same place, not authenticated in any way. I can't access any secured path.
What I did
application.yml:
security:
oauth2:
client:
registration:
wca:
client-id: 0YekXxbT20En0V000000Tk9pGam2K9HvIA0fTPP0
client-secret: cm0001232132132132hGNICxzAwNKqFMg
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/loginWCA'
provider:
wca:
authorization-uri: https://www.worldcubeassociation.org/oauth/authorize
token-uri: https://www.worldcubeassociation.org/api/v0/me
SecurityConfig:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/loginWCA").permitAll().anyRequest().authenticated().and().oauth2Login();
}
Disclaimer: I know that I'm securing everything, my goal is to go to the root path -> get redirected to the provider -> log in -> get back to my web -> have a valid session to access root path as an authenticated user.
You should get token after login passing. please ref your oauth2 provider. then add it with Bearer in request HEADER 'Authentication'. So other pages need not be authenticated.
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 a 'legacy' application build with Vaadin 8 that I need to secure with Keycloak.
Unfortunately, the redirect to Keycloak is not even triggered.
As a test, I created a Spring Boot application and tried to secure it with Keycloak without any problems, but it fails to work with Vaadin 8.
My configuration files for the Spring Boot application are;
application.properties
keycloak.realm=myrealm
keycloak.resource=test-app
keycloak.auth-server-url=http://localhost:8080/auth
keycloak.ssl-required=external
keycloak.public-client=true
keycloak.securityConstraints[0].authRoles[0]=Patient
keycloak.securityConstraints[0].authRoles[1]=Admin
keycloak.securityConstraints[0].securityCollections[0].name=boeken
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/books
keycloak.securityConstraints[1].authRoles[0]=Admin
keycloak.securityConstraints[1].securityCollections[0].name=backend
keycloak.securityConstraints[1].securityCollections[0].patterns[0]=/manager
server.port=8090
KeycloakConfig class
#Configuration
public class KeycloakConfig {
#Bean
public KeycloakSpringBootConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
Just by adding this, the Keycoal-redirect is triggered and I can log in. Easy.
What should I change/add when i'm trying to secure the Vaadin 8 application?
It's not a Spring/Spring boot-application (not started by SpringApplication.run()), I don't think it's mandatory to have a Spring/Spring boot app in order to secure it with Keycloak (correct me if i'm wrong).
The problem seems to be that the application.properties file is ignored (although it is on the class path), as I can navigate to the urls that should be secured.
Does anyone see what's missing/wrong?
In case you would consider using Spring boot, I created a working example of integration between Vaadin 8, Spring Boot and Keycloak.
It makes use of vaadin-spring-boot, keycloak-spring-boot-adapter and keycloak-spring-security-adapter plugins to get jump started and your application.properties will get picked up correctly. In essence, this setup tells Vaadin to let Spring Security handle all security, and in turn Keycloak is hooked up as the security handler.
The only configuration needed is to have a custom SecurityConfiguration to define your specific security needs.
But the bulk comes down to:
#Configuration
#EnableWebSecurity
#EnableVaadinSharedSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().disable();
http.formLogin().disable();
// disable spring security csrf as Vaadin already provides this
// also possible to disable this in Vaadin and leave this enabled
http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/vaadinServlet/UIDL/**").permitAll()
.antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
.anyRequest().authenticated();
http
.logout()
.addLogoutHandler(keycloakLogoutHandler())
.logoutUrl("/sso/logout").permitAll()
.logoutSuccessUrl("/");
http
.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
.addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class);
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint());
http
.sessionManagement()
.sessionAuthenticationStrategy(sessionAuthenticationStrategy());
}
...
}
I could reload application on edit with RemoteSpringApplication until I added spring security to my app,
with
#EnableWebSecurity
public class WebAuthConfig extends WebSecurityConfigurerAdapter { ..
etc
event though I added:
// TODO: this disable all security checks httpSecurity.httpBasic().disable().authorizeRequests().anyRequest().permitAll();
so all my rest calls still works without any auth,
as soon as I change the code and running RemoteSpringApplication detects the change it fails with:
Exception in thread "File Watcher" java.lang.IllegalStateException: Unexpected 403 response uploading class files
How to prevent it?
Thx
Add:
.authorizeRequests()
.antMatchers("/.~~spring-boot!~/**")
.permitAll()
.and()
to your Spring Security config near the top of your http method chain in the configure(HttpSecurity http) method and it'll disable Spring Security on the Spring Boot DevTools URL.
If you want to change this URL you can override it by changing the spring.devtools.remote.context-path property in your application.properties.
Make sure you're not running devtools in production of course!!
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.