html
When building intranet web applications in Windows environments, we often need to implement true single sign-on (SSO) where users authenticated via Active Directory can access web apps without additional login prompts. This requires Windows Integrated Authentication rather than traditional form-based authentication.
There are two primary protocols enabling this seamless authentication:
- Kerberos: The preferred modern protocol using ticket-based authentication
- NTLM: The older challenge-response protocol as fallback
For this to work properly, several components must be configured:
1. Active Directory domain-joined client machines
2. Service Principal Names (SPNs) registered in AD
3. Correct browser security zone settings
4. Properly configured web server (IIS/Tomcat/etc.)
Here's how to configure Tomcat to accept Windows authentication:
<!-- In server.xml -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="want" sslProtocol="TLS"
keystoreFile="conf/keystore.jks" keystorePass="changeit"/>
<!-- In web.xml -->
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
For processing the authenticated user in your Java webapp:
public class SSOFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String remoteUser = httpRequest.getRemoteUser();
if (remoteUser != null) {
// User was authenticated via Windows Integrated Auth
Principal principal = httpRequest.getUserPrincipal();
// Process user...
} else {
// Fallback to form-based auth
httpRequest.getRequestDispatcher("/login.jsp").forward(request, response);
}
chain.doFilter(request, response);
}
}
- Double-hop issue: Kerberos has restrictions on credential delegation. Solution: Configure constrained delegation in AD
- Browser configuration: The intranet site must be in Trusted Sites zone. Solution: Push via Group Policy
- SPN issues: Missing or duplicate SPNs cause failures. Solution: Use
setspn
tool to verify
For Spring-based applications, you can leverage Spring Security Kerberos:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().disable()
.logout().disable()
.csrf().disable()
.addFilterBefore(
new SpnegoAuthenticationProcessingFilter(),
BasicAuthenticationFilter.class);
}
}
When troubleshooting Windows Integrated Authentication:
- Enable Kerberos logging via
set KRB5_TRACE=C:\kerberos.log
- Check Windows Event Viewer for security audit events
- Use Wireshark to examine protocol negotiation
- Verify SPNs with
setspn -L [serviceaccount]
When implementing transparent SSO for Active Directory-authenticated intranet applications, the authentication sequence typically follows this pattern:
1. User logs into Windows domain workstation
2. Browser requests protected resource from web server
3. Server responds with 401 Unauthorized + WWW-Authenticate headers
4. Browser automatically negotiates authentication via SPNEGO (Kerberos/NTLM)
5. Server validates credentials against AD without user interaction
There are two primary protocols that enable this transparent authentication:
- Kerberos: The preferred method for modern AD environments
- NTLM: Fallback protocol when Kerberos isn't available
Here's a sample configuration for enabling SPNEGO authentication in Tomcat:
<!-- In server.xml -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="want" sslProtocol="TLS"
keystoreFile="conf/keystore.jks" keystorePass="changeit"
truststoreFile="conf/truststore.jks" truststorePass="changeit"/>
<!-- In context.xml -->
<Realm className="org.apache.catalina.realm.JNDIRealm"
connectionURL="ldap://ad.example.com:389"
userPattern="CN={0},CN=Users,DC=example,DC=com"
roleBase="CN=Roles,DC=example,DC=com"
roleName="cn"
roleSearch="(member={0})"/>
For applications that need custom handling, here's a basic SPNEGO filter:
public class SpnegoFilter implements Filter {
private static final String NEGOTIATE = "Negotiate";
private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String authHeader = req.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith(NEGOTIATE)) {
res.setHeader(WWW_AUTHENTICATE, NEGOTIATE);
res.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
// Extract token and validate with JGSS API
byte[] token = Base64.getDecoder().decode(
authHeader.substring(NEGOTIATE.length()).trim());
try {
GSSManager manager = GSSManager.getInstance();
GSSName clientName = manager.createContext(
new GSSByteArrayToken(token)).getSrcName();
req.setAttribute("REMOTE_USER", clientName.toString());
chain.doFilter(request, response);
} catch (GSSException e) {
res.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
}
SPN Registration Issues:
setspn -A HTTP/webserver.example.com domain\serviceaccount
Browser Configuration: Ensure the intranet zone is properly configured in IE/Edge or Firefox/Chrome equivalent settings.
Cross-Domain Challenges: Kerberos requires strict name resolution - ensure DNS is properly configured with forward/reverse lookups.
For environments where SPNEGO isn't feasible:
- ADFS with WS-Federation: For web applications across security boundaries
- Header-based Authentication: Using IIS as a reverse proxy with authentication
- OAuth2/OIDC with AD as Identity Provider: For modern web applications