I have a Spring Boot project with keycloak integrated. Now I want to disable keycloak for testing purposes.
I tried by adding keycloak.enabled=false
to application.properties
as mentioned in Keycloak documentation but it didnt work.
So how do I disable it?
My Workaround:
1. Create a Custom-Filter and add it to the (Spring) Security-Chain in early position.
2. Create a flag in the application.yml (securityEnabled)
3. Query the flag in the Custom-Filter. If 'true' simply go on with the next filter by calling chain.doFilter(). If 'false' create a dummy Keycloak-Account set the roles you need and set it to the context.
4. By the way the roles are also outsourced to the application.yml
5. Skip the rest of the filters in the Security-Chain (so no keycloak-stuff is executed and the corresponding Authorization happend)
In Detail:
1. Class of Custom-Filter
public class CustomFilter extends OncePerRequestFilter {
@Value("${securityEnabled}")
private boolean securityEnabled;
@Value("${grantedRoles}")
private String[] grantedRoles;
@Override
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res,
FilterChain chain) throws IOException, ServletException {
if (!securityEnabled){
// Read roles from application.yml
Set<String> roles = Arrays.stream(grantedRoles)
.collect(Collectors.toCollection(HashSet::new));
// Dummy Keycloak-Account
RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(null, null, null, null, null, null, null);
final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<>("Dummy_Principal", session);
final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, principal.getKeycloakSecurityContext());
// Dummy Security Context
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(new KeycloakAuthenticationToken(account, false));
SecurityContextHolder.setContext(context);
// Skip the rest of the filters
req.getRequestDispatcher(req.getServletPath()).forward(req, res);
}
chain.doFilter(req, res);
}
}
2. Insert Custom-Filter in the http-Configuration of Spring-Security
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.cors()
.and()
.csrf()
.disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.sessionAuthenticationStrategy(sessionAuthenticationStrategy())
.and()
.addFilterAfter(CustomFilter(), CsrfFilter.class)
.authorizeRequests()
.anyRequest().permitAll();
}
Have a look at the default Filter-Chain after configuring Keycloak:
Filter-Chain
So it´s obvious to insert the Custom-Filter at position 5 to avoid the whole Keycloak-Magic.
I have used this workaround to defeat the method security and it´s @Secured-Annotation.
For anyone who might have the same trouble, here is what I did.
I didn't disable Keycloak but I made a separate a Keycloak config file for testing purposes.
Here is my config file
@Profile("test")
@Configuration
@EnableWebSecurity
public class SecurityTestConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").permitAll();
http.headers().frameOptions().disable();
http.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**");
}
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public AccessToken accessToken() {
AccessToken accessToken = new AccessToken();
accessToken.setSubject("abc");
accessToken.setName("Tester");
return accessToken;
}
}
Please note it is important to use this only in a test environment and therefore I have annotated the config as @Profile("test")
. I have also added an AccessToken
bean since some of the auditing features in my application depend on it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With