jhipster-registry icon indicating copy to clipboard operation
jhipster-registry copied to clipboard

CORS problems since 5.0.0 on management and config endpoints

Open pdelaby opened this issue 5 years ago • 3 comments

Overview of the issue

Since v5.0.0, the registry served behind a traefik proxy (or letsencrypt) on docker seems to have CORS issues on post methods ( authenticate, config/encrypt, management/loggers).

Sample configuration

jhipster-registry:
       image: jhipster/jhipster-registry:v5.0.2
       volumes:
           - jhipster-registry-data:/root/.ssh
       environment:
           - _JAVA_OPTIONS=-Xmx512m -Xms256m
           - SPRING_PROFILES_ACTIVE=prod
           ...
           - LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB_CORS=TRACE
           - JHIPSTER_CORS_ALLOWED-ORIGINS=https://my.domain.name
           - 'JHIPSTER_CORS_ALLOWED-METHODS=GET, PUT, POST, DELETE, OPTIONS'
           - 'JHIPSTER_CORS_ALLOWED-HEADERS="*"'
           - 'JHIPSTER_CORS_EXPOSED-HEADERS='
           - 'JHIPSTER_CORS_ALLOW-CREDENTIALS=true'
       networks:
          - "traefik-public"
       deploy:
          replicas: 1
          labels:
           - traefik.frontend.rule=Host:my.domain.name
           - traefik.enable=true
           - traefik.port=8761
           - traefik.tags=traefik-public
           - traefik.docker.network=traefik-public
           # Traefik service that listens to HTTP
           - traefik.redirectorservice.frontend.entryPoints=http
           - traefik.redirectorservice.frontend.redirect.entryPoint=https
           # Traefik service that listens to HTTPS
           - traefik.webservice.frontend.entryPoints=https
       depends_on:
          - traefik

The configuration worked in previous versions, but a http 403 'invalid cors request' is now returned.

I added

- JHIPSTER_CORS_ALLOWED-ORIGINS=https://my.domain.name
- 'JHIPSTER_CORS_ALLOWED-METHODS=GET, PUT, POST, DELETE, OPTIONS'
- 'JHIPSTER_CORS_ALLOWED-HEADERS="*"'
- 'JHIPSTER_CORS_EXPOSED-HEADERS='
- 'JHIPSTER_CORS_ALLOW-CREDENTIALS=true'

in the docker-compose, and it fixed the problem for /authenticate, but other POST on endpoints (like the encryption in configuration/encryption or changing the log levels) doesn't seems to share that configuration (they use the CORS configuration mapped to '/**' ).

Am I missing a property ?

Motivation for or Use Case

It worked in previous version ( before 5.0.0).

Reproduce the error

Start jhipster-registry on docker, served behind an https domain name.

JHipster Registry Version(s)

5.0.2

  • [x] Checking this box is mandatory (this is just to show you read everything)

pdelaby avatar Jul 01 '19 14:07 pdelaby

+1 here. Working before 5.0.0, now got invalid cors request at login

antaka1 avatar Aug 09 '19 14:08 antaka1

As per current implementation, configurable CORS settings are applied against following URI patterns in the WebConfigurer. If your URL path doesn't match against these patterns, then, the default CORS configuration is applied that deny the incoming request with 403.

            source.registerCorsConfiguration("/eureka/**", config);
            source.registerCorsConfiguration("/api/**", config);
            source.registerCorsConfiguration("/v2/api-docs", config);
            source.registerCorsConfiguration("/*/api/**", config);

To support customization, I think we can externalize these URL patterns like other CORS settings.

vishal423 avatar Aug 09 '19 14:08 vishal423

To fix the loggers, I added the following cors filters to WebConfigurer.corsFilter():

            source.registerCorsConfiguration("/management/**", config);
            source.registerCorsConfiguration("/auth/**", config);
            source.registerCorsConfiguration("/services/*/api/**", config);
            source.registerCorsConfiguration("/services/**/management/**", config);
            source.registerCorsConfiguration("/*/management/**", config);
            source.registerCorsConfiguration("/*/oauth/**", config);

To fix the swagger ui when combined with the jhipster uaa, I also replaced the OAuth2ClientCredentialsService.retrieveNewAccessToken() implementation with:

    private void retrieveNewAccessToken() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        final String authString = jHipsterProperties.getSecurity().getClientAuthorization().getClientId() + ":" + jHipsterProperties.getSecurity().getClientAuthorization().getClientSecret();
        final String authorization = "Basic " + Base64.encodeBase64String(authString.getBytes());
        headers.add("Authorization", authorization);

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("grant_type", "client_credentials");

        HttpEntity<?> requestEntity = new HttpEntity<>(map, headers);
        String tokenEndpoint = getTokenEndpoint();
        ResponseEntity<DefaultOAuth2AccessToken> responseEntity = this.restTemplate.exchange(tokenEndpoint, HttpMethod.POST, requestEntity, DefaultOAuth2AccessToken.class);

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            logger.debug("Request failed for '{}'", Optional.ofNullable(requestEntity.getHeaders()).map(HttpHeaders::getLocation).map(URI::toString).orElse(""));
        }

        accessToken = Objects.requireNonNull(responseEntity.getBody()).getValue();
    }

    /**
     * Returns the configured OAuth2 token endpoint URI.
     *
     * @return the OAuth2 token endpoint URI.
     */
    private String getTokenEndpoint() {
        String tokenEndpointUrl = jHipsterProperties.getSecurity().getClientAuthorization().getAccessTokenUri();
        if (tokenEndpointUrl == null) {
            throw new InvalidClientException("no token endpoint configured in application properties");
        }
        return tokenEndpointUrl;
    }

kavenr avatar Aug 27 '19 20:08 kavenr