Reputation: 358
I have been banging my head over this one.
I have a basic web application using Spring Boot running on localhost:8082, a dockerized keycloak server running on localhost:8081 and a dockerized nginx server running on port 80.
When I was using keycloak without spring security integration, a user accessing a secured resource would be redirected to the keycloak login page at http://{keycloak-server}/auth/realms/{myrealm}/protocol/openid-connect/auth/... and everything worked great.
When I added spring security into the mix, as per this tutorial and several others, suddenly my application attempts to redirect to http://{myapp}/sso/login where there is no /sso/login endpoint so I get a 404.
I was only able to get the application routing to the correct login end-point by accessing it directly at http://localhost:8082 and setting the redirect_uri in keycloak for the client to http://localhost:8082/*.
I suspect it may have something to do with nginx config, but again, it was working before I added spring security into the mix, so I am scratching my head. Here is my nginx.conf
worker_processes 2;
events {
worker_connections 1024;
}
http {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
# auth local (keycloak)
server {
listen 80;
server_name auth.local;
location / {
# keycloak
proxy_pass http://host.docker.internal:8081/;
}
}
server {
listen 80;
server_name guardian.local;
location / {
# send to portal
rewrite ^/(.*)$ http://guardian.local/portal/$1 permanent;
}
location /portal {
# guardian web-portal
proxy_pass http://host.docker.internal:8082;
}
}
}
My security config class:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
// Submits the KeycloakAuthenticationProvider to the AuthenticationManager
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
/**
* Used by Spring Security to add Keycloak config from spring config resource (like application.properties).
* @return
*/
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
// Specifies the session authentication strategy
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/portal/client*")
.hasRole("user")
.anyRequest()
.permitAll();
}
}
And my application.properties
server.port = 8082
keycloak.auth-server-url = http://auth.local/auth
keycloak.realm = myRealm
keycloak.resource = guardian-web-portal
keycloak.public-client = true
keycloak.use-resource-role-mappings = true
keycloak.principal-attribute = preferred_username
Any help on this would be greatly appreciated. I am using keycloak-spring-boot-starter 12.0.4 and spring-boot-starter-security 2.4.5.
Upvotes: 1
Views: 2521
Reputation: 54
Try to add the below and change the permitAll() to authenticated()
.antMatchers("/login*", "/error*", "/sso*" ).permitAll()
on your
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/portal/client*")
.hasRole("user")
.anyRequest()
.permitAll();
}
so in the end you will have:
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/login*", "/error*", "/sso*" ).permitAll()
.antMatchers("/portal/client*")
.hasRole("user")
.anyRequest()
.authenticated();
}
Upvotes: 2