This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 77bb2c25156c108e7755f1a33435d6fa0b84c38d Author: Alex Heneveld <g...@alex.heneveld.org> AuthorDate: Thu Jun 27 14:04:42 2024 +0100 remove the WWW-Authenticate header when using the login form it had been added for errors as part of oauth support, but when using the login form, it triggers a browser login popup --- .../BrooklynSecurityProviderFilterJersey.java | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java index d2c91f2819..be2c9752b5 100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java @@ -19,6 +19,7 @@ package org.apache.brooklyn.rest.filter; import java.io.IOException; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -63,6 +64,8 @@ public class BrooklynSecurityProviderFilterJersey implements ContainerRequestFil @Context private ContextResolver<ManagementContext> mgmtC; + private static boolean LOGGED_LOGIN_FORM_WITH_INCOMPATIBLE_AUTH_WARNING = false; + @SuppressWarnings("resource") @Override public void filter(ContainerRequestContext requestContext) throws IOException { @@ -85,10 +88,7 @@ public class BrooklynSecurityProviderFilterJersey implements ContainerRequestFil rin = Response.status(Status.UNAUTHORIZED).entity("Authentication is required").build(); } } - if (rin.getStatus()==Status.UNAUTHORIZED.getStatusCode() && - Strings.isNonBlank(mgmt.getConfig().getConfig(BrooklynSecurityProviderFilterJavax.LOGIN_FORM))) { - rin = Response.status(Status.UNAUTHORIZED).entity("Authentication is required").header(LOGIN_PAGE_HEADER, mgmt.getConfig().getConfig(BrooklynSecurityProviderFilterJavax.LOGIN_FORM)).build(); - } + // adding headers in `headersToForward` if they are present in the original response MultivaluedMap<String, Object> responseHeaders = e.getResponse().getHeaders(); if(responseHeaders != null && !responseHeaders.isEmpty()){ @@ -98,6 +98,26 @@ public class BrooklynSecurityProviderFilterJersey implements ContainerRequestFil } }; } + + // if form is being used, we must NOT forward the WWW-Auth header + if (rin.getStatus()==Status.UNAUTHORIZED.getStatusCode()) { + String form = mgmt.getConfig().getConfig(BrooklynSecurityProviderFilterJavax.LOGIN_FORM); + if (Strings.isNonBlank(form)) { + if (!LOGGED_LOGIN_FORM_WITH_INCOMPATIBLE_AUTH_WARNING) { + List<Object> existingAuthHeaders = rin.getHeaders().get(HttpHeader.WWW_AUTHENTICATE); + if (!existingAuthHeaders.isEmpty() && existingAuthHeaders.stream().noneMatch(x -> ("" + x).toLowerCase().startsWith("basic "))) { + LOGGED_LOGIN_FORM_WITH_INCOMPATIBLE_AUTH_WARNING = true; + log.warn(BrooklynSecurityProviderFilterJavax.LOGIN_FORM.getName() + " " + form + " being used with incompatible auth scheme (logging once only): " + existingAuthHeaders); + } + } + rin = Response.fromResponse(rin).status(Status.UNAUTHORIZED).entity("Authentication is required using form at "+form) + .header(LOGIN_PAGE_HEADER, form) + .header(HttpHeaders.WWW_AUTHENTICATE, null) // clear the previous, so we don't return basic as browsers interecept that + .header(HttpHeaders.WWW_AUTHENTICATE, "X-Basic realm=\"login-form\"") // then add our custom one + .build(); + } + } + requestContext.abortWith(rin); } }