1

I am trying to authenticate the user before he accesses the swagger-ui. I am using Keycloak for ID management. I am following the example given here.

Below is my security config

@Configuration
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = new KeycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        authenticationManagerBuilder.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.csrf().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .exceptionHandling().accessDeniedHandler(
                (request, response, accessDeniedException) -> response.setStatus(HttpServletResponse.SC_NOT_FOUND)
        )
                .and()
                .anonymous()
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .httpBasic().disable()
                .formLogin().disable()
                .logout().disable();
    }


}

Below is my swagger config

@Configuration
@Slf4j
public class SwaggerConfig {

    @Value("${keycloak.auth-server-url}")
    private String AUTH_SERVER;

    @Value("${keycloak.credentials.secret}")
    private String CLIENT_SECRET;

    @Value("${keycloak.resource}")
    private String CLIENT_ID;

    @Value("${keycloak.realm}")
    private String REALM;

    private static final String OAUTH_NAME = "spring_oauth";
    private static final String ALLOWED_PATHS = "src/main/java/io/chait/swagger/demo/.*";
    private static final String GROUP_NAME = "swagger-demo";
    private static final String TITLE = "API Documentation for swagger-demo Application";
    private static final String DESCRIPTION = "Description here";
    private static final String VERSION = "1.0";

    @Bean
    public Docket taskApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName(GROUP_NAME)
                .useDefaultResponseMessages(true)
                .apiInfo(apiInfo())
                .select()
                .paths(regex(ALLOWED_PATHS))
                .build()
                .securitySchemes(Arrays.asList(securityScheme()))
                .securityContexts(Arrays.asList(securityContext()));
    }

    private ApiInfo apiInfo() {
        return new
                ApiInfoBuilder().title(TITLE).description(DESCRIPTION).version(VERSION).build();
    }

    @Bean
    public SecurityConfiguration security() {
        return SecurityConfigurationBuilder.builder()
                .realm(REALM)
                .clientId(CLIENT_ID)
                .clientSecret(CLIENT_SECRET)
                .appName(GROUP_NAME)
                .scopeSeparator(" ")
                .build();
    }

    private SecurityScheme securityScheme() {
        GrantType grantType =
                new AuthorizationCodeGrantBuilder()
                        .tokenEndpoint(new TokenEndpoint(AUTH_SERVER + "/realms/" + REALM + "/protocol/openid-connect/token", GROUP_NAME))
                        .tokenRequestEndpoint(
                                new TokenRequestEndpoint(AUTH_SERVER + "/realms/" + REALM + "/protocol/openid-connect/auth", CLIENT_ID, CLIENT_SECRET))
                        .build();

        SecurityScheme oauth =
                new OAuthBuilder()
                        .name(OAUTH_NAME)
                        .grantTypes(Arrays.asList(grantType))
                        .scopes(Arrays.asList(scopes()))
                        .build();
        return oauth;
    }

    private AuthorizationScope[] scopes() {
        AuthorizationScope[] scopes = {
                new AuthorizationScope("user", "for CRUD operations"),
                new AuthorizationScope("read", "for read operations"),
                new AuthorizationScope("write", "for write operations")
        };
        return scopes;
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(Arrays.asList(new SecurityReference(OAUTH_NAME, scopes())))
                .forPaths(PathSelectors.regex(ALLOWED_PATHS))
                .build();
    }

}

Below is my properties file

spring.datasource.url=jdbc:postgresql://localhost:5432/personal
spring.datasource.password=postgres
spring.datasource.username=postgres
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update


# keycloak config

keycloak.auth-server-url=http://localhost:8180/auth
keycloak.realm=local
keycloak.resource=swagger-demo
keycloak.public-client=true
keycloak.credentials.secret=fb652c4a-70cb-4b81-a339-fa87054f77a0

spring.application.name=swagger-demo

Below is my boot class

@SpringBootApplication
@EnableJpaRepositories
@EnableSwagger2
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

When I fire up the application and access http://localhost:8080/swagger-demo/swagger-ui/ the app redirects me to Keycloak where I enter user credentials. Upon authenticating, I get the exception below

2021-04-02 21:46:04.163 ERROR 4208 --- [nio-8080-exec-8] o.k.adapters.OAuthRequestAuthenticator   : failed to turn code into token
2021-04-02 21:46:04.164 ERROR 4208 --- [nio-8080-exec-8] o.k.adapters.OAuthRequestAuthenticator   : status from server: 401
2021-04-02 21:46:04.164 ERROR 4208 --- [nio-8080-exec-8] o.k.adapters.OAuthRequestAuthenticator   :    {"error":"unauthorized_client","error_description":"Client secret not provided in request"}

All the related threads regarding this exception are pointing towards a change in nginx config or Docker config. I am not using either of them and I am running this entirely on local. I am not sure what I am missing here. I have the code here. Any help is appreciated.

dreamcrash
  • 47,137
  • 25
  • 94
  • 117

0 Answers0