Waffle with Spring Security fails in IE
<p>I am using Spring Security and Waffle within a Spring Boot application. I have configured waffle using Java-based Spring configuration. (See below.)</p>

<p>I have Spring Boot configured to use Tomcat (default) with SSL, but the problem exists even if I revert to using an unencrypted http connection.</p>

<p>I can authenticate correctly if I access the website using Google Chrome, but it fails in odd ways in IE11. Waffle produces the following log:</p>

<pre><code>[DEBUG] [http-nio-8443-exec-1] w.s.NegotiateSecurityFilter: - GET /, contentlength: -1
[DEBUG] [http-nio-8443-exec-1] w.s.s.NegotiateSecurityFilterProvider: - security package: Negotiate, connection id: 0:0:0:0:0:0:0:1:52047
[DEBUG] [http-nio-8443-exec-1] w.s.s.NegotiateSecurityFilterProvider: - token buffer: 126 byte(s)
[DEBUG] [http-nio-8443-exec-1] w.s.s.NegotiateSecurityFilterProvider: - continue token: xxxx
[DEBUG] [http-nio-8443-exec-1] w.s.s.NegotiateSecurityFilterProvider: - continue required: true
[DEBUG] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - GET /, contentlength: -1
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - security package: Negotiate, connection id: 0:0:0:0:0:0:0:1:52047
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - token buffer: 121 byte(s)
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - continue token: xxxx
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - continue required: false
[DEBUG] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - logged in user: DOMAIN\username (xxxx)
[DEBUG] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - roles: DOMAIN\username, xxxx, xxxxxxxxxxxxxxxxxx
[INFO ] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - successfully logged in user: DOMAIN\username
[DEBUG] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - GET /, contentlength: -1
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - security package: Negotiate, connection id: 0:0:0:0:0:0:0:1:52047
[DEBUG] [http-nio-8443-exec-6] w.s.s.NegotiateSecurityFilterProvider: - token buffer: 121 byte(s)
[WARN ] [http-nio-8443-exec-6] w.s.NegotiateSecurityFilter: - error logging in user: com.sun.jna.platform.win32.Win32Exception: The token supplied to the function is invalid
</code></pre>

<p>So, it appears to me as though the authentication succeeded, but then for some reason, it attempts to reauthenticate and it fails.</p>

<p>The logs when I access the site through Chrome are similar, but after the successful login, it shows:</p>

<pre><code>[DEBUG] [http-nio-8443-exec-1] w.s.NegotiateSecurityFilter: - GET /, contentlength: -1
[DEBUG] [http-nio-8443-exec-1] w.s.NegotiateSecurityFilter: - GET /index.html, contentlength: -1
[DEBUG] [http-nio-8443-exec-1] w.s.NegotiateSecurityFilter: - GET /index.html, contentlength: -1
</code></pre>

<p>... and so on from there.</p>

<p>There also seems to be a timing problem in the IE case. Sometimes, it succeeds in loading some content from the server: Fonts, images, whatnot, before it suddenly fails again. This is inconsistent and it stops at a different place at different times.</p>

<p>Is this a Waffle bug?</p>

<p>My Spring Boot Java-based configuration:</p>

<pre><code>@Configuration
public class WaffleConfig {

    @Bean
    public WindowsAuthProviderImpl waffleWindowsAuthProvider() {
        return new WindowsAuthProviderImpl();
    }

    @Bean
    @Autowired
    public NegotiateSecurityFilterProvider negotiateSecurityFilterProvider(
            final WindowsAuthProviderImpl windowsAuthProvider) {
        return new NegotiateSecurityFilterProvider(windowsAuthProvider);
    }

    @Bean
    @Autowired
    public BasicSecurityFilterProvider basicSecurityFilterProvider(final WindowsAuthProviderImpl windowsAuthProvider) {
        return new BasicSecurityFilterProvider(windowsAuthProvider);
    }

    @Bean
    @Autowired
    public SecurityFilterProviderCollection waffleSecurityFilterProviderCollection(
            final NegotiateSecurityFilterProvider negotiateSecurityFilterProvider,
            final BasicSecurityFilterProvider basicSecurityFilterProvider) {
        final SecurityFilterProvider[] securityFilterProviders = {
                negotiateSecurityFilterProvider,
                basicSecurityFilterProvider };
        return new SecurityFilterProviderCollection(securityFilterProviders);
    }

    @Bean
    @Autowired
    public NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint(
            final SecurityFilterProviderCollection securityFilterProviderCollection) {
        final NegotiateSecurityFilterEntryPoint negotiateSecurityFilterEntryPoint = new NegotiateSecurityFilterEntryPoint();
        negotiateSecurityFilterEntryPoint.setProvider(securityFilterProviderCollection);
        return negotiateSecurityFilterEntryPoint;
    }

    @Bean
    @Autowired
    public NegotiateSecurityFilter waffleNegotiateSecurityFilter(final SecurityFilterProviderCollection securityFilterProviderCollection) {
        final NegotiateSecurityFilter negotiateSecurityFilter = new NegotiateSecurityFilter();
        negotiateSecurityFilter.setProvider(securityFilterProviderCollection);
        return negotiateSecurityFilter;
    }

}
</code></pre>

<p>And:</p>

<pre><code>@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    @Configuration
    public static class ProductionConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .anyRequest()
                    .authenticated()
                    .and()
                .addFilterBefore(negotiateSecurityFilter, BasicAuthenticationFilter.class)
                .httpBasic()
                    .authenticationEntryPoint(entryPoint);
        }

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication().withUser("user").password("pa").roles("USER");
        }

        @Autowired
        private NegotiateSecurityFilter negotiateSecurityFilter;

        @Autowired
        private NegotiateSecurityFilterEntryPoint entryPoint;
    }
}
</code></pre>