0
votes

I'm trying to build a frontend application in Angular 9 and the backend in spring boot.

Using keycloak to authenticate and authorize users.

I created 2 clients on keycloak a frontend with a public access type and a bearer only backend.

Frontend configuration enter image description here

The angular app is configured using this tutorial https://www.npmjs.com/package/keycloak-angular

The spring boot app is configured with this application.properties

spring.profiles.active=development
server.port=9000

keycloak.enabled = true
keycloak.realm                      = test-realm
keycloak.auth-server-url            = http://localhost:8080/auth/
keycloak.ssl-required               = external
keycloak.resource                   = backend
keycloak.credentials.secret         = 5353e8ee-80b5-4c2b-b543-c08247475868
keycloak.use-resource-role-mappings = true
keycloak.bearer-only                = true

keycloak.cors = true

keycloak.securityConstraints[0].securityCollections[0].name = protected resource
keycloak.securityConstraints[0].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /products
keycloak.securityConstraints[0].securityCollections[0].patterns[1] = /products/

When I try to post on /products from the angular app I get

enter image description here

enter image description here

Looking at various examples I tried to modify springboot's application.properties file in this way

spring.profiles.active=development
server.port=9000

keycloak.enabled = true
keycloak.realm                      = test-realm
keycloak.auth-server-url            = http://localhost:8080/auth/
keycloak.ssl-required               = external
keycloak.resource                   = frontend
keycloak.bearer-only                = true
keycloak.public-client=true
keycloak.cors = true

keycloak.securityConstraints[0].securityCollections[0].name = protected resource
keycloak.securityConstraints[0].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /products
keycloak.securityConstraints[0].securityCollections[0].patterns[1] = /products/

And works, but from what i understand, the most correct way would be to have 2 separate clients on keycloak for frontend and backend.

where am i wrong, why i get the CROS error??? I checked this section on Angular app, but is ok https://www.npmjs.com/package/keycloak-angular#client-configuration

I think the problem is an incorrect configuration on Angular but I don't know what.

2

2 Answers

0
votes

Firstly, you need this @Bean in config class. Change allowedOrigins if you are using different url. Maybe you will need add @CrossOrigin annotation in your controller. Secondly you need add http.cors() in configuration method if you are using Spring Security.

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("https://localhost:4200");
            }
        };
    }

}

Example method of Spring Security config if you are using it:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .cors().and()
            .csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
            .anyRequest().permitAll()
            .and().httpBasic();
}
0
votes

TL;DR

After hours and hours of testing, I discovered that the problem was simply this flag keycloak.use-resource-role-mappings = true

After removing it everything started working properly.

More details

I found out that the CORS error is actually a false clue, after adding this class

@Configuration
public class FilterProvider {

    @Bean
    public WebMvcConfigurer corsConfiguration() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods(HttpMethod.GET.toString(), HttpMethod.POST.toString(),
                                HttpMethod.PUT.toString(), HttpMethod.DELETE.toString(), HttpMethod.OPTIONS.toString())
                        .allowedOrigins("*");
            }
        };
    }
}

I got the 403 unauthorized error, so the problem was not in the CORS settings but somewhere else ... the keycloak.use-resource-role-mappings = true