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


The following commit(s) were added to refs/heads/master by this push:
     new f81db2cac3 Allow to forward some to the headers when a 
SecurityProviderDeniedAuthentication is thrown for helping the client to 
identify the reason
     new 2d71a462b8 Merge pull request #1412 from 
jcabrerizo/security-provider-unauthorized-helper
f81db2cac3 is described below

commit f81db2cac3de4edfff365cffd757f6dd51eef916
Author: Juan Cabrerizo <[email protected]>
AuthorDate: Mon Sep 25 11:39:21 2023 +0100

    Allow to forward some to the headers when a 
SecurityProviderDeniedAuthentication is thrown for helping the client to 
identify the reason
---
 .../BrooklynSecurityProviderFilterJersey.java       | 21 ++++++++++++++++++++-
 .../rest/security/provider/SecurityProvider.java    |  7 +++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

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 75e890f4b2..d2c91f2819 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,19 +19,25 @@
 package org.apache.brooklyn.rest.filter;
 
 import java.io.IOException;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import javax.annotation.Priority;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerRequestFilter;
 import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Provider;
 
+import com.google.common.collect.ImmutableSet;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.rest.security.provider.SecurityProvider;
 import 
org.apache.brooklyn.rest.security.provider.SecurityProvider.SecurityProviderDeniedAuthentication;
 import org.apache.brooklyn.util.text.Strings;
 import org.eclipse.jetty.http.HttpHeader;
@@ -46,6 +52,11 @@ public class BrooklynSecurityProviderFilterJersey implements 
ContainerRequestFil
     private static final Logger log = 
LoggerFactory.getLogger(BrooklynSecurityProviderFilterJersey.class);
     public static final String LOGIN_PAGE_HEADER = "X_BROOKLYN_LOGIN_PAGE";
 
+    private final Set<String> headersToForward = ImmutableSet.of(
+            HttpHeaders.WWW_AUTHENTICATE, // defines the HTTP authentication 
methods ("challenges") that might be used to gain access to a specific resource
+            SecurityProvider.UNAUTHORIZED_MESSAGE_HEADER // helper message 
from the security provider
+            );
+
     @Context
     HttpServletRequest webRequest;
 
@@ -78,7 +89,15 @@ public class BrooklynSecurityProviderFilterJersey implements 
ContainerRequestFil
                     
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()){
+                for(String headerKey: headersToForward) {
+                    if(responseHeaders.containsKey(headerKey)) {
+                        rin = Response.fromResponse(rin).header(headerKey, 
responseHeaders.get(headerKey).stream().map(Object::toString).collect(Collectors.joining(",
 "))).build();
+                    }
+                };
+            }
             requestContext.abortWith(rin);
         }
     }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
index fbd1b3ef6d..458df7ffd8 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
@@ -34,6 +34,12 @@ import 
org.apache.brooklyn.rest.util.MultiSessionAttributeAdapter;
  */
 public interface SecurityProvider {
 
+    /**
+     * Header for return to the user a helper message related to the 
unauthorized response
+     */
+    public static final String UNAUTHORIZED_MESSAGE_HEADER = 
"X_BROOKLYN_UNAUTHORIZED_MESSAGE";
+
+
     /** If user supplied a value session, this passes that in so the {@link 
SecurityProvider}
      * can check whether the user has previously authenticated, e.g. via an 
{@link HttpSession#setAttribute(String, Object)}
      * done by {@link #authenticate(HttpServletRequest, Supplier, String, 
String)}.
@@ -78,6 +84,7 @@ public interface SecurityProvider {
     public boolean logout(HttpSession session);
     
     public static class SecurityProviderDeniedAuthentication extends Exception 
{
+
         private static final long serialVersionUID = -3048228939219746783L;
         private final Response response;
         public SecurityProviderDeniedAuthentication() { this(null); }

Reply via email to