Skip POST/PUT request content before sending the challenge
@@ -42,6 +42,7 @@ import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+import java.io.InputStream;
import java.security.Principal;
import java.util.Base64;
import java.util.List;
@@ -55,6 +56,8 @@ import static com.google.common.base.CharMatcher.JAVA_ISO_CONTROL;
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.propagateIfInstanceOf;
+import static com.google.common.io.ByteStreams.copy;
+import static com.google.common.io.ByteStreams.nullOutputStream;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static io.airlift.http.client.HttpStatus.BAD_REQUEST;
import static io.airlift.http.client.HttpStatus.INTERNAL_SERVER_ERROR;
@@ -171,7 +174,7 @@ public class LdapFilter
}
catch (AuthenticationException e) {
log.debug(e, "LDAP authentication failed");
- processAuthenticationException(e, response);
+ processAuthenticationException(e, request, response);
}
}
@@ -188,15 +191,30 @@ public class LdapFilter
}
}
- private static void processAuthenticationException(AuthenticationException e, HttpServletResponse response)
+ private static void processAuthenticationException(AuthenticationException e, HttpServletRequest request, HttpServletResponse response)
throws IOException
{
if (e.getStatus() == UNAUTHORIZED) {
+ // If we send the challenge without consuming the body of the request,
+ // the Jetty server will close the connection after sending the response.
+ // The client interprets this as a failed request and does not resend
+ // the request with the authentication header.
+ // We can avoid this behavior in the Jetty client by reading and discarding
+ // the entire body of the unauthenticated request before sending the response.
+ skipRequestBody(request);
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"presto\"");
}
response.sendError(e.getStatus().code(), e.getMessage());
}
+ private static void skipRequestBody(HttpServletRequest request)
+ throws IOException
+ {
+ try (InputStream inputStream = request.getInputStream()) {
+ copy(inputStream, nullOutputStream());
+ }
+ }
+
private static Credentials getCredentials(String header)
throws AuthenticationException
{
