Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Micronaut Cors does not work as expected when we define custom HttpServerFilters #10869

Open
somitmittal opened this issue May 31, 2024 · 6 comments

Comments

@somitmittal
Copy link

somitmittal commented May 31, 2024

Expected Behavior

OPTIONS preflight request should not fail

Actual Behaviour

OPTIONS preflight request fails

Steps To Reproduce

  1. Enable cors on micronaut application using micronaut.server.cors.enabled = true in application.yml
  2. Define another HttpServerFilter for e.g. AuthFilter that basically checks for "Authorization" header in a request and return s 401 if token is missing.
  3. On adding custom filter, when OPTIONS preflight request is made to the application, the custom filter executes and checks for "Authorization" header and since it is missing in OPTIONS preflight request, the custom filter returns a 401 failing the OPTIONS request resulting in a CORS error.
11:57:04.377 io.micronaut.runtime.Micronaut [?:?] [] - Startup completed in 9762ms. Server Running: http://localhost:8080
11:57:12.782 s.f.filters.AuthorizationFilter [?:?] [] - Invalid Token Exception for Url: /v2/api and Method: POST Exception: { error: UNAUTHORIZED, httpStatus: UNAUTHORIZED, httpStatusCode: 401 }
11:57:12.786 s.f.filters.AuthorizationFilter [?:?] [] - ErrorSummary: exception: { error: UNAUTHORIZED, httpStatus: UNAUTHORIZED, httpStatusCode: 401 }, uri: /v2/api, apiMethod: POST, apiVersion: v2, 

curl:

curl --location --request OPTIONS 'http://localhost:8080/v2/api' \
--header 'Origin: postman' \
--header 'Access-Control-Request-Method: POST'

Response:
Screenshot 2024-05-31 at 12 12 09 PM

Environment Information

Micronaut: 3.7.2
Language: Kotlin

Example Application

No response

Version

3.7.2

@graemerocher
Copy link
Contributor

this sounds like you have the filter ordering incorrect

@somitmittal
Copy link
Author

somitmittal commented May 31, 2024

@graemerocher thanks for quick reply. Is Cors filter of highest precedence?

As per cors filter code in Micronaut. I believe it is returning a response decorated with preflight headers if status is < 400.
In this case, how can I specify cors filter to be of highest precedence?

@NonNull
    private Publisher<MutableHttpResponse<?>> handlePreflightRequest(@NonNull HttpRequest<?> request, @NonNull ServerFilterChain chain, @NonNull CorsOriginConfiguration corsOriginConfiguration) {
        Optional<HttpStatus> statusOptional = this.validatePreflightRequest(request, corsOriginConfiguration);
        if (statusOptional.isPresent()) {
            HttpStatus status = (HttpStatus)statusOptional.get();
            if (status.getCode() >= 400) {
                return Publishers.just(HttpResponse.status(status));
            } else {
                MutableHttpResponse<?> resp = HttpResponse.status(status);
                this.decorateResponseWithHeadersForPreflightRequest(request, resp, corsOriginConfiguration);
                this.decorateResponseWithHeaders(request, resp, corsOriginConfiguration);
                return Publishers.just(resp);
            }
        } else {
            return Publishers.then(chain.proceed(request), (respx) -> {
                this.decorateResponseWithHeadersForPreflightRequest(request, respx, corsOriginConfiguration);
                this.decorateResponseWithHeaders(request, respx, corsOriginConfiguration);
            });
        }
    }

Can cors filter ever proceed with chain request if options preflight request succeeded and land into custom authorization filter and still fail there?

@somitmittal
Copy link
Author

somitmittal commented Jun 1, 2024

@graemerocher can you please suggest how can I fix the ordering so that cors filter runs first?

@yawkat
Copy link
Member

yawkat commented Jun 1, 2024

Add an order to your own filter that is higher than that of the cors filter, which should be 9250

@somitmittal
Copy link
Author

@yawkat
Few findings:
On using
@order(Ordered.LOWEST_PRECEDENCE) on the custom filter, its not working.
It fails on OPTIONS request.

curl --location --request OPTIONS 'http://localhost:8080/v2/api' \
--header 'Origin: http://www.google.com' \
--header 'Access-Control-Request-Method: POST'

But overriding the method getOrder works

override fun getOrder(): Int {
        return Integer.MAX_VALUE
    }

@somitmittal
Copy link
Author

Hey any updates here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants