Skip to content

Instantly share code, notes, and snippets.

@sguilhen
Last active January 2, 2016 12:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sguilhen/90b862a145e4d47a4d5d to your computer and use it in GitHub Desktop.
Save sguilhen/90b862a145e4d47a4d5d to your computer and use it in GitHub Desktop.
JASPIC implementation issues
After reviewing the JASPIC tests in Arun Gupta's testsuite and comparing them with our implementation I've
identified a number of issues and missing bits that are not tested by the TCK.
The testsuite contains a few modules:
** basic-authentication: checks if access to a protected web application is correctly granted/denied to
users. With a proper security domain in place all tests in this module pass.
** ejb-propagation: checks if the authenticated user is propagated by the container to the EJB layer. We
have a couple of failures here. The JASPI callback handler correctly populates the security context and
the context is propagated to the EJB layer. However, the test assumes that the EJBs will be called
*without* authenticating the user again as it expects the container will trust the authentication performed
by the web layer. WF throws an exception denying access as the incoming security context has not been
validated by the EJB layer (it uses the "other" security domain and that domain rejects all authentication
attempts by default)
So problem here is that right now we don't have that kind of trust between layers - the EJB layer will
always authenticate the incoming principal. While we could get around the failures by setting up a security
domain for the EJBs, I think this might be a good oportunity to think about a better mechanism in which the
EJB authentication is skipped when the incoming security context corresponds to a user that has already
been authenticated.
** lifecycle: checks if the JASPI modules are called when they should. Exemples include the
validateRequest/secureResponse pair that must be invoked for every request and cleanSubject that should be
called when a HttpServletRequest.logout() is performed.
We have several issues here. The first has to do with secureResponse. While it *is* always called, the call
happens at a stage in which its to late to write anything to the response because it has already been
committed. The JASPIAuthenticationMechanism is incorrectly using an ExchangeCompletionListener to invoke
the secureResponse method, which pretty much renders secureResponse useless. The question here is what can
we do to invoke secureResponse after the servlet is done writting but before the response is committed?
The second issue we have here is that HttpServletRequest login(), logout() and authenticate() are ignoring
JASPIC. The implementation should be using the AuthConfigFactory to check if there is an AuthConfigProvider
for the "HttpServlet" layer and the servlet appContextId. If a provider is found, it should be used to
(according to the spec):
* throw an exception if login() is called.
* call validateRequest if authenticate is called. This might be working as the code seems to be calling
the configured JASPIC mechanism when authenticate is performed. The mech will do the whole
validateRequest/secureResponse processing.
* call cleanSubject if logout() is called. This is definitely not working as the HttpServletRequestImpl
ignores JASPIC.
** register-session: checks if the authenticated user is "remembered" by the container when the javax.servlet.http.registerSession property is set by the JASPIC module in the MessageInfo. In other words,
the container must store the authenticated Principal, its roles, etc so that they are restored in
subsequent requests. JASPIC modules will still be called and they should be able to do
request.getUserPrincipal() to retrieve the principal restored by the container.
I'm haven't really looked into this particular scenario yet so I'm not sure how to do this in Undertow.
Perhaps calling authenticationComplete() with cachingRequired=true is enough to remember the authenticated
Account?
A related issue has to do with the getAuthType() implementation that should also check if the JASPIC
module has set the javax.servlet.http.authType property in the MessageInfo. This is what the spec says:
"When getAuthType is to return a non-null value, the Map of the MessageInfo object used in the call to
validateRequest must be consulted to determine if it contains an entry for the key identified in Table 3-3.
If the Map contains an entry for the key, the corresponding value must be obtained from the Map and
established as the getAuthType return value. If the Map does not contain an entry for the key, and an auth-
method is defined in the login-config element of the deployment descriptor for the web application, the
value from the auth-method must be established as the getAuthType return value. If the Map does not contain
an entry for the key, and the deployment descriptor does not define an auth-method, a product defined default
non-null value must be established the getAuthType return value, and the same default value need not be used
for both cases."
Right now the mechanis always returns "JASPI" as the authType, which is clearly wrong. In order to properly
implement this I would need access to the auth-method that has been configured for the servlet but that
information is not available in the exchange or the ServletRequestContext (at least I couldn't find it).
DeploymentManagerImpl uses the auth-method to instantiate the corresponding mechanims but when JASPIC is
used this information is lost and as a result I can't change the mech to properly implement the
getAuthType() method.
** wrapping: checks whether request/response objects that have been wrapped by JASPIC modules reach the
servlet in its wrapped form. The JASPIC mech didn't handle this scenario but I've already implemented the
code to deal with wrapped requests and this module is passing.
Then there's configuration. Right now we rely on a security domain that contains a jaspic configuration to
enable JASPIC for a web application. This might look ok but as Arjan pointed out JBoss/WF is the only
container out there that requires special configuration to enable JASPIC. Applications can register
AuthConfigProviders dynamically by using the AuthConfigFactory and they shouldn't need a security domain
if they will be delegating auth decisions to a provider that has been dynamically registered.
In runtime the container should use the AuthConfigFactory to check if there is a registered AuthConfigProvider
for the "HttpServlet" layer and corresponding servlet appContextId. If such provider is found, then JASPIC
authentication is to be performed. If not, container-specifc mechanisms are used. Right now we don't have
a way in Undertow to dynamically select the mechanisms that should be used (or at least I haven't found a
way to do that) so I would like to know your thoughts on this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment