Skip to content

Commit

Permalink
Do not support any Origin by default if CORS is enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
sberyozkin committed Dec 20, 2022
1 parent 6b36df2 commit e85bea0
Show file tree
Hide file tree
Showing 13 changed files with 32 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class UriTagCorsTest {
.overrideConfigKey("quarkus.micrometer.binder.vertx.enabled", "true")
.overrideConfigKey("quarkus.http.cors", "true")
.overrideConfigKey("quarkus.redis.devservices.enabled", "false")
.overrideConfigKey("quarkus.http.cors.origins", "*")
.withApplicationRoot((jar) -> jar
.addClasses(Util.class,
VertxWebEndpoint.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
quarkus.http.cors=true
quarkus.http.cors.origins=*
# whitespaces added to test that they are not taken into account config is parsed
quarkus.http.cors.methods=GET, OPTIONS, POST
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
quarkus.http.cors=true
quarkus.http.cors=true
quarkus.http.cors.origins=*
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class OpenApiHttpRootDefaultPathTestCase {
.withApplicationRoot((jar) -> jar
.addClasses(OpenApiRoute.class)
.addAsResource(new StringAsset("quarkus.http.root-path=/foo\n" +
"quarkus.http.cors=true"), "application.properties"));
"quarkus.http.cors=true\n"
+ "quarkus.http.cors.origins=*"), "application.properties"));

@Test
public void testOpenApiPathAccessResource() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class OpenApiHttpRootPathCorsTestCase {
.withApplicationRoot((jar) -> jar
.addClasses(OpenApiRoute.class)
.addAsResource(new StringAsset("quarkus.http.cors=true\n" +
"quarkus.http.cors.origins=*\n" +
"quarkus.http.non-application-root-path=/api/q\n" +
"quarkus.http.root-path=/api"), "application.properties"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class CORSSecurityTestCase {

private static final String APP_PROPS = "" +
"quarkus.http.cors=true\n" +
"quarkus.http.cors.origins=*\n" +
"quarkus.http.cors.methods=GET, OPTIONS, POST\n" +
"quarkus.http.auth.basic=true\n" +
"quarkus.http.auth.policy.r1.roles-allowed=test\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class CORSWildcardSecurityTestCase {

private static final String APP_PROPS = "" +
"quarkus.http.cors=true\n" +
"quarkus.http.cors.origins=*\n" +
"quarkus.http.auth.basic=true\n" +
"quarkus.http.auth.policy.r1.roles-allowed=test\n" +
"quarkus.http.auth.permission.roles1.paths=/test\n" +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
quarkus.http.cors=true
quarkus.http.cors.origins=*
# whitespaces added to test that they are not taken into account config is parsed
quarkus.http.cors.methods=GET, OPTIONS, POST
quarkus.http.cors.access-control-allow-credentials=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ public class CORSConfig {
* Comma separated list of valid URLs, e.g.: http://www.quarkus.io,http://localhost:3000
* In case an entry of the list is surrounded by forward slashes,
* it is interpreted as a regular expression.
* The filter allows any origin if this is not set.
*
* default: returns any requested origin as valid
*/
@ConfigItem
@ConvertWith(TrimmedStringConverter.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ public class CORSFilter implements Handler<RoutingContext> {
// Must be static because the filter is created(deployed) at build time and runtime config is still not available
final CORSConfig corsConfig;

final List<Pattern> allowedOriginsRegex;
private final boolean wildcardOrigin;
private final List<Pattern> allowedOriginsRegex;
private final List<HttpMethod> configuredHttpMethods;

public CORSFilter(CORSConfig corsConfig) {
this.corsConfig = corsConfig;
this.allowedOriginsRegex = parseAllowedOriginsRegex(this.corsConfig.origins);
configuredHttpMethods = createConfiguredHttpMethods(this.corsConfig.methods);
this.wildcardOrigin = isOriginConfiguredWithWildcard(this.corsConfig.origins);
this.allowedOriginsRegex = this.wildcardOrigin ? List.of() : parseAllowedOriginsRegex(this.corsConfig.origins);
this.configuredHttpMethods = createConfiguredHttpMethods(this.corsConfig.methods);
}

private List<HttpMethod> createConfiguredHttpMethods(Optional<List<String>> methods) {
if (methods.isEmpty()) {
return Collections.emptyList();
return List.of();
}
List<String> corsConfigMethods = methods.get();
List<HttpMethod> result = new ArrayList<>(corsConfigMethods.size());
Expand All @@ -55,6 +57,10 @@ public static boolean isConfiguredWithWildcard(Optional<List<String>> optionalLi
return list.isEmpty() || (list.size() == 1 && "*".equals(list.get(0)));
}

private static boolean isOriginConfiguredWithWildcard(Optional<List<String>> origins) {
return !origins.isEmpty() && origins.get().size() == 1 && "*".equals(origins.get().get(0));
}

/**
* Parse the provided allowed origins for any regexes
*
Expand All @@ -63,7 +69,7 @@ public static boolean isConfiguredWithWildcard(Optional<List<String>> optionalLi
*/
public static List<Pattern> parseAllowedOriginsRegex(Optional<List<String>> allowedOrigins) {
if (allowedOrigins == null || !allowedOrigins.isPresent()) {
return Collections.emptyList();
return List.of();
}

// extract configured origins and find any Regular Expressions
Expand Down Expand Up @@ -179,8 +185,13 @@ public void handle(RoutingContext event) {
processRequestedHeaders(response, requestedHeaders);
}

boolean allowsOrigin = isConfiguredWithWildcard(corsConfig.origins) || corsConfig.origins.get().contains(origin)
|| isOriginAllowedByRegex(allowedOriginsRegex, origin) || isSameOrigin(request, origin);
boolean allowsOrigin = wildcardOrigin;
if (!allowsOrigin) {
allowsOrigin = !corsConfig.origins.isEmpty()
&& (corsConfig.origins.get().contains(origin)
|| isOriginAllowedByRegex(allowedOriginsRegex, origin)
|| isSameOrigin(request, origin));
}

if (allowsOrigin) {
response.headers().set(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ quarkus.http.auth.permission.post-logout.paths=/tenant-logout/post-logout
quarkus.http.auth.permission.post-logout.policy=permit

quarkus.http.cors=true
quarkus.http.cors.origins=*
quarkus.http.auth.proactive=false
quarkus.http.proxy.enable-forwarded-prefix=true
quarkus.http.proxy.allow-forwarded=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ quarkus.keycloak.devservices.create-realm=false
quarkus.keycloak.devservices.realm-name=quarkus-a

quarkus.http.cors=true
quarkus.http.cors.origins=*

quarkus.oidc.token-cache.max-size=3

Expand Down Expand Up @@ -118,4 +119,4 @@ quarkus.native.additional-build-args=-H:IncludeResources=.*\\.pem


quarkus.log.category."io.quarkus.oidc.runtime.CodeAuthenticationMechanism".min-level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.CodeAuthenticationMechanism".level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.CodeAuthenticationMechanism".level=TRACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ quarkus.oidc.tls.key-store-password=password
quarkus.native.additional-build-args=-H:IncludeResources=.*\\.jks

quarkus.http.cors=true
quarkus.http.cors.origins=*

quarkus.http.auth.basic=true
quarkus.security.users.embedded.enabled=true
Expand Down

0 comments on commit e85bea0

Please sign in to comment.