The Waffle Servlet Security Filter implements the Negotiate and Basic protocols with Kerberos and NTLM single sign-on support. This allows users to browse to a Windows intranet site without having to re-enter credentials for browsers that support Kerberos or NTLM and to fall back to Basic authentication for those that do not. While it still enables you to protect different resources based on different user roles (user groups), the filter is a catch-all solution to enable Windows single-sign-on for a web server that implements servlets (Tomcat, Jetty, etc.).
Moreover, this filter supports impersonating the remote client, enabling to perform actions as the remote user using native Windows APIs.
The following steps are required to configure a web server with the Waffle Servlet Security Filter. These instructions work for Tomcat, Jetty, WebSphere and possibly others.
Package Waffle JARs (1.8.4), including waffle-jna-1.8.4.jar
, guava-20.0.jar
, jna-4.3.0.jar
, jna-platform-4.3.0.jar
and slf4j-1.7.22.jar
in the application's lib
directory or copy them to your web server's lib.
- For latest snapshot instead use
waffle-jna-1.9.0-SNAPSHOT
,caffeine-2.3.5.jar
,jna-4.3.0.jar
,jna-platform-4.3.0.jar
andslf4j-1.7.22.jar
.
Add a security filter to WEB-INF\web.xml
of your application.
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The filter can be configured with the following init-param
options.
- disableSSO: Allows for the enabling/disabling of Single-SignOn Security Filter.This is useful if you require to bypass the SSO process for troubleshooting/diagnostics and provide login by some other means.
- principalFormat: Specifies the name format for the principal.
- roleFormat: Specifies the name format for the role.
- allowGuestLogin: Allow guest login. When true and the system's Guest account is enabled, any invalid login succeeds as Guest. Note that while the default value of
allowGuestLogin
is true, it is recommended that you disable the system's Guest account to disallow Guest login. This option is provided for systems where you don't have administrative privileges. - authProvider: A class that implements
IWindowsAuthProvider
and has a parameterless constructor. - securityFilterProviders: A list of security filter providers. By default, both
BasicSecurityFilterProvider
andNegotiateSecurityFilterProvider
will be loaded. - waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols: A list of security protocols supported by the
NegotiateSecurityFilterProvider
. Can be one of or a combination of Negotiate and NTLM. - waffle.servlet.spi.BasicSecurityFilterProvider/realm: The name of the Realm for BASIC authentication.
- impersonate: Allow impersonation. When true the remote user will be impersonated. Note that there is no mapping between the Windows native threads, under which the impersonation takes place, and the Java threads. Thus you'll need to use Windows native APIs to perform impersonated actions. Any action done in Java will still be performed with the user account running the servlet container.
- excludePatterns: Url patterns to exclude from the filter, uses regex for pattern matching
- excludeCorsPreflight: exclude CORS preflight requests. When a request is CORS preflight web security which is an OPTIONS request with 3 valid CORS preflight headers and will not include credentials i.e. credentials would be the method in a CORS preflight request @see https://fetch.spec.whatwg.org/#methods
- excludeBearerAuthorization: exclude requests that include a Bearer Authorization header. if your API has a mix of Windows and OAUTH covered URIs
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>waffle.servlet.NegotiateSecurityFilter</filter-class>
<init-param>
<param-name>disableSSO</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>principalFormat</param-name>
<param-value>fqn</param-value>
</init-param>
<init-param>
<param-name>roleFormat</param-name>
<param-value>both</param-value>
</init-param>
<init-param>
<param-name>allowGuestLogin</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>impersonate</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>excludeCorsPreflight</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>excludeBearerAuthorization</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>excludePatterns</param-name>
<param-value>
.*/rest/.*
.*/api/v2/.*
./oauth2/basic/client_credentials.*
</param-value>
</init-param>
<init-param>
<param-name>securityFilterProviders</param-name>
<param-value>
waffle.servlet.spi.BasicSecurityFilterProvider
waffle.servlet.spi.NegotiateSecurityFilterProvider
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.NegotiateSecurityFilterProvider/protocols</param-name>
<param-value>
Negotiate
NTLM
</param-value>
</init-param>
<init-param>
<param-name>waffle.servlet.spi.BasicSecurityFilterProvider/realm</param-name>
<param-value>WaffleFilterDemo</param-value>
</init-param>
</filter>
A demo application can be found in the Waffle distribution in the Samples\waffle-filter
directory. Copy the entire directory into Tomcat's or Jetty's webapps directory and navigate to http://localhost:8080/waffle-filter/.
You can use maven to build and deploy this demo application by following the steps below. These assume you have checked out the waffle source tree.
- Update your tomcat server configuration (tomcat/conf/tomcat-users.xml) to grant the roles required for a user to deploy an application into tomcat.
<role rolename="tomcat"/>
<user username="tomcat" password="tomcat" roles="tomcat,manager-gui,manager-script,manager-jmx,manager-status"/>
- Update your maven settings.xml file (.m2/settings.xml) to include a definition of your local tomcat server and the user/pwd used to deploy to that server.
<servers>
...
<server>
<id>mylocalserver</id>
<username>tomcat</username>
<password>tomcat</password>
</server>
- Start your tomcat server. You can launch a locally installed tomcat with remote debugging enabled on port 8000 using:
apache-tomcat-7.0.53$ bin/catalina.sh jpda start
- Build and Deploy the demo application to the local tomcat instance. In the waffle source tree, move to the directory: waffle/Source/JNA/waffle-demo-parent/waffle-filter, and execute the following:
mvn clean package tomcat7:redeploy
The app will be available at:
http://localhost:8080/waffle-filter-demo/
Enable waffle logging. Add the following to conf\logging.properties
in your Tomcat installation.
waffle.servlet.NegotiateSecurityFilter.level = FINE
waffle.servlet.spi.SecurityFilterProviderCollection.level = FINE
waffle.servlet.spi.NegotiateSecurityFilterProvider.level = FINE
waffle.servlet.spi.BasicSecurityFilterProvider.level = FINE
Restart Tomcat and review logs\Catalina*.log
.