diff --git a/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java b/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java index e3a8456..6739341 100644 --- a/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java +++ b/spring-security-kerberos-web/src/main/java/org/springframework/security/kerberos/web/authentication/SpnegoAuthenticationProcessingFilter.java @@ -115,6 +115,14 @@ public class SpnegoAuthenticationProcessingFilter extends GenericFilterBean { private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy(); private boolean skipIfAlreadyAuthenticated = true; + /** + * Authentication header prefix sent by IE/Windows when the domain controller fails to issue a Kerberos + * ticket for the URL. + * + * "TlRMTVNTUA" is the base64 encoding of "NTLMSSP". This will be followed by the actual token. + **/ + private static final String NTLMSSP_PREFIX = "Negotiate TlRMTVNTUA"; + @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; @@ -132,7 +140,7 @@ public class SpnegoAuthenticationProcessingFilter extends GenericFilterBean { String header = request.getHeader("Authorization"); - if (header != null && (header.startsWith("Negotiate ") || header.startsWith("Kerberos "))) { + if (header != null && ((header.startsWith("Negotiate ") && !header.startsWith(NTLMSSP_PREFIX)) || header.startsWith("Kerberos "))) { if (logger.isDebugEnabled()) { logger.debug("Received Negotiate Header for request " + request.getRequestURL() + ": " + header); } diff --git a/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java b/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java index 39c72e6..af85a0e 100644 --- a/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java +++ b/spring-security-kerberos-web/src/test/java/org/springframework/security/kerberos/web/SpnegoAuthenticationProcessingFilterTest.java @@ -92,6 +92,8 @@ public class SpnegoAuthenticationProcessingFilterTest { private static final String TOKEN_PREFIX_KERB = "Kerberos "; + private static final String TOKEN_NTLM = "Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw=="; + private static final BadCredentialsException BCE = new BadCredentialsException(""); @Before @@ -132,7 +134,7 @@ public class SpnegoAuthenticationProcessingFilterTest { everythingWorks(tokenPrefix); verify(successHandler).onAuthenticationSuccess(request, response, AUTHENTICATION); verify(failureHandler, never()).onAuthenticationFailure(any(HttpServletRequest.class), - any(HttpServletResponse.class), any(AuthenticationException.class)); + any(HttpServletResponse.class), any(AuthenticationException.class)); } private void everythingWorks(String tokenPrefix) throws IOException, @@ -160,6 +162,19 @@ public class SpnegoAuthenticationProcessingFilterTest { assertEquals(null, SecurityContextHolder.getContext().getAuthentication()); } + @Test + public void testNTLMSSPHeader() throws Exception { + when(request.getHeader(HEADER)).thenReturn(TOKEN_NTLM); + + filter.doFilter(request, response, chain); + // If the header is not present, the filter is not allowed to call + // authenticate() + verify(authenticationManager, never()).authenticate(any(Authentication.class)); + // chain should go on + verify(chain).doFilter(request, response); + assertEquals(null, SecurityContextHolder.getContext().getAuthentication()); + } + @Test public void testAuthenticationFails() throws Exception { authenticationFails();