-
Bug
-
Resolution: Done
-
Major
-
None
-
None
JASPIAuthenticationMechanism#authenticate installs a response wrapper to later on handle secureResponse.
This is correct for the initial call to the SAM/context (prior to entering the Servlet pipeline), but this is most likely not correct for a call following HttpServletRequest#authenticate. In many situations this will lead to exceptions about a "requestChannel" already been opened (perhaps this should be "responseChannel"?).
JASPIAuthenticationMechanism#authenticate contains the following code:
@Override public AuthenticationMechanismOutcome authenticate(final HttpServerExchange exchange, final SecurityContext sc) { final ServletRequestContext requestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); final JASPIServerAuthenticationManager sam = createJASPIAuthenticationManager(); final GenericMessageInfo messageInfo = createMessageInfo(exchange, sc); final String applicationIdentifier = buildApplicationIdentifier(requestContext); // ... secureResponse(exchange, sc, sam, messageInfo, cbh); return outcome;
With secureResponse:
private void secureResponse(final HttpServerExchange exchange, final SecurityContext securityContext, final JASPIServerAuthenticationManager sam, final GenericMessageInfo messageInfo, final JASPICallbackHandler cbh) { // we add a response wrapper to properly invoke the secureResponse, after processing the destination exchange.addResponseWrapper(new ConduitWrapper<StreamSinkConduit>() { @Override public StreamSinkConduit wrap(final ConduitFactory<StreamSinkConduit> factory, final HttpServerExchange exchange) { ServletRequestContext requestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); String applicationIdentifier = buildApplicationIdentifier(requestContext); // ... return factory.create(); } }); }
As can be seen, every call to authenticate attempts to install the handler again.
I guess secureResponse should somehow check if the call was made from request#authenticate, or that it was done at the beginning of the request, or simply remember whether a registration has already been made or not.
I patched the code locally to use a request attribute to implement the last option and this seems to work.