Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle invalid authentication response #2877

Closed
ThomasSousa96 opened this issue Jun 21, 2018 · 3 comments
Closed

Handle invalid authentication response #2877

ThomasSousa96 opened this issue Jun 21, 2018 · 3 comments
Assignees

Comments

@ThomasSousa96
Copy link

The jwt security use HttpServletRequest and HttpServletResponse directly, then when the passed token is invalid the below code sends immediately the 401 error code, using something like HttpServletResponse response...; response.sendError(401).

public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {
if (httpMessageContext.isProtected()) {
IdentityStoreHandler identityStoreHandler = CDI.current().select(IdentityStoreHandler.class).get();
SignedJWTCredential credential = getCredential(request);
if (credential != null) {
CredentialValidationResult result = identityStoreHandler.validate(credential);
if (result.getStatus() == VALID) {
httpMessageContext.getClientSubject()
.getPrincipals()
.add(result.getCallerPrincipal());
}
return httpMessageContext.notifyContainerAboutLogin(result);
}
}
return httpMessageContext.doNothing();
}

Invoking response.sendError(401) directly i cannot do some handling in the response, using a ContainerRequestFilter, per example.

Now, when a ContainerRequestFilter invoke

requestContext.abortWith(Response.status(UNAUTHORIZED);

The server not send the response immediately, making possible the remaining filters ContainerRequestFilter do some handling in the response, as add a header, per example.

Is possible do the same behavior of a requestContext.abortWith(Response.status(UNAUTHORIZED) in the HttpAuthenticationMechanism class?

@arjantijms
Copy link
Contributor

Postprocessing can be done by (dynamically) adding an interceptor to the HttpAuthenticationMechanism bean. You can either intercept the validateRequest or the secureResponse method.

There's a bit of code needed for this, unfortunately. See

https://arjan-tijms.omnifaces.org/2017/08/dynamically-adding-interceptor-to-build.html

A future version of Payara as well as a future version of EE security (with help from an also future version of CDI) should make this easier. See for instance

@arjantijms
Copy link
Contributor

As a followup, in a next version of Payara we'll likely support decorators for authentication mechanisms, making that task even easier.

@arjantijms
Copy link
Contributor

@ThomasSousa96 see this example:

/**
 * This is a CDI decorator that decorates the authentication mechanism (in this test
 * the one that is installed via the annotation on the {@link Servlet} class.
 *
 * @author Arjan Tijms
 *
 */
@Decorator
@Priority(100)
public abstract class AuthenticationMechanismDecorator implements HttpAuthenticationMechanism {

    @Inject
    @Delegate
    private HttpAuthenticationMechanism delagate;

    @Override
    public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {

        // Wrap the response, so we can catch the error code being sent
        // (the error code causes the response to be committed)
        ResponseWrapper responseWrapper = new ResponseWrapper(response);
        httpMessageContext.getMessageInfo().setResponseMessage(responseWrapper);

        try {

            // Invoke the original authentication mechanism
            AuthenticationStatus status = delagate.validateRequest(request, responseWrapper, httpMessageContext);

            // If there was an error, add our custom header and pass on the error
            // to the original response
            if (responseWrapper.getError() != null) {
                response.addHeader("foo", "bar");
                response.sendError(responseWrapper.getError());
            }

            return status;

        } catch (IOException e) {
            throw new AuthenticationException(e);
        } finally {
            // Restore the original response
            httpMessageContext.getMessageInfo().setResponseMessage(response);
        }
    }

    private static class ResponseWrapper extends HttpServletResponseWrapper {

        private Integer error;

        public ResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public void sendError(int sc) throws IOException {
            error = sc;
        }

        public Integer getError() {
            return error;
        }

    }

}

https://github.com/arjantijms/soteria/blob/1fd01f69ccf0d58dda6f73a63f667960f20f340c/test/app-mem-basic-decorate/src/main/java/test/AuthenticationMechanismDecorator.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants