Home > OS >  Swagger Page not showing controller endpoints due to csrf api failed
Swagger Page not showing controller endpoints due to csrf api failed

Time:08-30

In my application, I am adding swagger-ui but it's not showing controller apis. When I checked in developer console, it's showing that localhost:9000/ and localhost:9000/csrf apis getting failed.

enter image description here

Below is my Security config:

    @Override
    protected void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider authenticationProvider =
                new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl,ldapBase);

        authenticationProvider.setConvertSubErrorCodesToExceptions(true);
        authenticationProvider.setUseAuthenticationRequestCredentials(true);
        authenticationProvider.setSearchFilter("(sAMAccountName={1})");
        return authenticationProvider;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf()
                .disable()
                .exceptionHandling().authenticationEntryPoint(jwtUnAuthorizedResponseAuthenticationEntryPoint).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                .antMatchers("/v2/api-docs",
                        "/configuration/ui",
                        "/swagger-resources/**",
                        "/configuration/security",
                        "/swagger-ui.html",
                        "/webjars/**").permitAll()
                .anyRequest().authenticated();
        httpSecurity
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        httpSecurity
                .headers()
                .frameOptions().sameOrigin()  //H2 Console Needs this setting
                .cacheControl(); //disable caching
    }

    @Override
    public void configure(WebSecurity webSecurity) throws Exception {
        webSecurity
                .ignoring()
                .antMatchers(
                        HttpMethod.POST,
                        authenticationPath
                )
                .antMatchers(HttpMethod.OPTIONS, "/**")
                .and()
                .ignoring()
                .antMatchers(
                        HttpMethod.GET,
                        "/" //Other Stuff You want to Ignore
                )
                .and()
                .ignoring()
                .antMatchers("/h2-console/**/**");//Should not be in Production!
    }

SwaggerConfig:

public static final String DEFAULT_INCLUDE_PATTERN = "/deployer/*.*";

@Bean
    public Docket productApi() {
        return new Docket(DocumentationType.SWAGGER_2).select()
                .apis(RequestHandlerSelectors.basePackage("com.org.deployer.controller"))
                .paths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN)).build().apiInfo(metaData())
                .securityContexts(Lists.newArrayList(securityContext()))
                .securitySchemes(Lists.newArrayList(apiKey()))
                .useDefaultResponseMessages(false);
    }

    private ApiKey apiKey() {
        return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(DEFAULT_INCLUDE_PATTERN))
                .build();
    }

    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope
                = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(
                new SecurityReference("JWT", authorizationScopes));
    }

Response for /v2/api-docs api:

{
  "swagger": "2.0",
  "info": {
    "description": "deployment Tool ",
    "version": "1.0",
    "title": " api",
    "termsOfService": "Terms of service",
    "contact": {
      "name": "Support Team"
    },
    "license": {
      
    }
  },
  "host": "localhost:9000",
  "basePath": "/",
  "securityDefinitions": {
    "JWT": {
      "type": "apiKey",
      "name": "Authorization",
      "in": "header"
    }
  }
}

Controller:

package com.org.deployer.controller;


@RestController
@CrossOrigin(origins = "http://localhost:4200")
@Api(value = "package operations", description = "Operations pertaining to Package Schedule")
public class PackageScheduleController {

    private static final Logger logger = LoggerFactory.getLogger(PackageScheduleController.class);

    @Autowired
    PackageScheduleService packageScheduleService;


    @PostMapping("/schedule")
    @ApiOperation(value = "This method is used to get the clients.")
    public PackageScheduleResponse schedule(@RequestBody PackageScheduleRequest packageScheduleRequest){
        try{
        logger.info("Schedule Request received for {}",packageScheduleRequest.getName());
            System.out.println(packageScheduleRequest.getScheduleTime().toLocalTime());
        return packageScheduleService.schedule(packageScheduleRequest);
        }
        catch(Exception e){
            logger.error("Exception occured",e);
            throw new RuntimeException("Some Error Occured");
        }
    }

    @GetMapping("/view-schedule")
    public List<PackageScheduleDto> schedule(){
        try{
            logger.info("Request received for fetching upcoming schedule jobs");
            return packageScheduleService.fetchAllScheudules();
        }
        catch(Exception e){
            logger.error("Exception occured",e);
            throw new RuntimeException("Some Error Occured");
        }
    }
}

By Seeing I can understand that it's related csrf configuration but not sure how to solve it.

CodePudding user response:

The calls to localhost:9000 and localhost:9000/csrf are an attempt by Springfox to retrieve a csrf token. Even if they fail, Springfox should still work. If you don't like those calls, you can disable them by adding the following configuration:

private SecurityContext securityContext() {
    return SecurityConfigurationBuilder.builder() 
        // ...
        .enableCsrfSupport(false) // Add this
        .build();
  }

However, the problem is that your controller endpoints do not match the pattern you configured (/deployer/*.*). Due to this, they aren't included in Springfox. To fix this, you can change the pattern (DEFAULT_INCLUDE_PATTERN) or change the path selector to PathSelectors.any():

@Bean
public Docket productApi() {
    return new Docket(DocumentationType.SWAGGER_2)
        .select()
        // ...
        .paths(PathSelectors.any()) // Change this
        .build()
        // ...
}

Don't forget to change this in your SecurityContext as well.

  • Related