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);
         }
     }

Reply via email to