Skip to content

Commit

Permalink
logging(auth): adding optional logging to authentication exceptions (d…
Browse files Browse the repository at this point in the history
…atahub-project#7929)

(cherry picked from commit b71baac)
  • Loading branch information
david-leifker authored and lix-mms committed Jul 3, 2023
1 parent fe66445 commit 30100ea
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import static com.datahub.authentication.AuthenticationConstants.*;
Expand All @@ -67,6 +68,9 @@ public class AuthenticationFilter implements Filter {
@Named("dataHubTokenService")
private StatefulTokenService _tokenService;

@Value("#{new Boolean('${authentication.logAuthenticatorExceptions}')}")
private boolean _logAuthenticatorExceptions;

private AuthenticatorChain authenticatorChain;

@Override
Expand All @@ -81,7 +85,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
AuthenticationRequest context = buildAuthContext((HttpServletRequest) request);
Authentication authentication = null;
try {
authentication = this.authenticatorChain.authenticate(context);
authentication = this.authenticatorChain.authenticate(context, _logAuthenticatorExceptions);
} catch (AuthenticationException e) {
// For AuthenticationExpiredExceptions, terminate and provide that feedback to the user
log.debug("Failed to authenticate request. Received an AuthenticationExpiredException from authenticator chain.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;


Expand Down Expand Up @@ -43,10 +45,10 @@ public void register(@Nonnull final Authenticator authenticator) {
* Returns null if {@link Authentication} cannot be resolved for the incoming request.
*/
@Nullable
public Authentication authenticate(@Nonnull final AuthenticationRequest context) throws AuthenticationException {
public Authentication authenticate(@Nonnull final AuthenticationRequest context, boolean logExceptions) throws AuthenticationException {
Objects.requireNonNull(context);
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
List<Pair<String, String>> authenticationFailures = new ArrayList<>();
List<Pair<String, Exception>> authenticationFailures = new ArrayList<>();
for (final Authenticator authenticator : this.authenticators) {
try {
log.debug(String.format("Executing Authenticator with class name %s", authenticator.getClass().getCanonicalName()));
Expand All @@ -67,17 +69,24 @@ public Authentication authenticate(@Nonnull final AuthenticationRequest context)
throw e;
} catch (Exception e) {
// Log as a normal error otherwise.
authenticationFailures.add(new Pair<>(authenticator.getClass().getCanonicalName(), e.getMessage()));
log.debug(String.format(
"Caught exception while attempting to authenticate request using Authenticator %s",
authenticator.getClass().getCanonicalName()), e);
"Caught exception while attempting to authenticate request using Authenticator %s",
authenticator.getClass().getCanonicalName()), e);
authenticationFailures.add(new Pair<>(authenticator.getClass().getCanonicalName(), e));
} finally {
Thread.currentThread().setContextClassLoader(contextClassLoader);
}
}
// No authentication resolved. Return null.
if (!authenticationFailures.isEmpty()) {
log.warn("Authentication chain failed to resolve a valid authentication. Errors: {}", authenticationFailures);
List<Pair<String, String>> shortMessage = authenticationFailures.stream()
.peek(p -> {
if (logExceptions) {
log.error("Error during {} authentication: ", p.getFirst(), p.getSecond());
}
})
.map(p -> Pair.of(p.getFirst(), p.getSecond().getMessage())).collect(Collectors.toList());
log.warn("Authentication chain failed to resolve a valid authentication. Errors: {}", shortMessage);
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void testAuthenticateSuccess() throws Exception {
// Verify that the mock authentication is returned on Authenticate.
final AuthenticationRequest mockContext = Mockito.mock(AuthenticationRequest.class);

Authentication result = authenticatorChain.authenticate(mockContext);
Authentication result = authenticatorChain.authenticate(mockContext, false);

// Verify that the authentication matches the mock returned by authenticator1
assertSame(result, mockAuthentication);
Expand All @@ -53,7 +53,7 @@ public void testAuthenticateFailure() throws Exception {
// Verify that the mock authentication is returned on Authenticate.
final AuthenticationRequest mockContext = Mockito.mock(AuthenticationRequest.class);

Authentication result = authenticatorChain.authenticate(mockContext);
Authentication result = authenticatorChain.authenticate(mockContext, false);

// If the authenticator throws, verify that null is returned to indicate failure to authenticate.
assertNull(result);
Expand All @@ -71,6 +71,6 @@ public void testAuthenticateThrows() throws Exception {
// Verify that the mock authentication is returned on Authenticate.
final AuthenticationRequest mockContext = Mockito.mock(AuthenticationRequest.class);

assertThrows(AuthenticationExpiredException.class, () -> authenticatorChain.authenticate(mockContext));
assertThrows(AuthenticationExpiredException.class, () -> authenticatorChain.authenticate(mockContext, false));
}
}
3 changes: 3 additions & 0 deletions metadata-service/factories/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ authentication:
signingKey: ${DATAHUB_TOKEN_SERVICE_SIGNING_KEY:WnEdIeTG/VVCLQqGwC/BAkqyY0k+H8NEAtWGejrBI94=}
salt: ${DATAHUB_TOKEN_SERVICE_SALT:ohDVbJBvHHVJh9S/UA4BYF9COuNnqqVhr9MLKEGXk1O=}

# Normally failures are only warnings, enable this to throw them.
logAuthenticatorExceptions: ${METADATA_SERVICE_AUTHENTICATOR_EXCEPTIONS_ENABLED:false}

# Required separately from the DataHubTokenAuthenticator as this is used by the AuthServiceController to authorize token generation
# at user login time.
systemClientId: ${DATAHUB_SYSTEM_CLIENT_ID:__datahub_system}
Expand Down

0 comments on commit 30100ea

Please sign in to comment.