This is an automated email from the ASF dual-hosted git repository. radcortez pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomee.git
commit 58292c94375f582f5d7fa89d5ef810b28bdab067 Author: Roberto Cortez <[email protected]> AuthorDate: Mon Jan 14 16:35:16 2019 +0000 TOMEE-2365 - Implemented SecurityContext authenticate. --- .../tomee/security/TomEESecurityContext.java | 106 ++++++++++++++++++ .../tomee/security/cdi/TomEESecurityExtension.java | 3 + .../security/context/SecurityContextTest.java | 121 +++++++++++++++++++++ 3 files changed, 230 insertions(+) diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java new file mode 100644 index 0000000..2e31b06 --- /dev/null +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomee.security; + +import org.apache.catalina.authenticator.jaspic.CallbackHandlerImpl; +import org.apache.tomee.security.message.TomEEMessageInfo; + +import javax.security.auth.Subject; +import javax.security.auth.message.AuthException; +import javax.security.auth.message.AuthStatus; +import javax.security.auth.message.MessageInfo; +import javax.security.auth.message.config.AuthConfigFactory; +import javax.security.auth.message.config.AuthConfigProvider; +import javax.security.auth.message.config.ServerAuthConfig; +import javax.security.auth.message.config.ServerAuthContext; +import javax.security.enterprise.AuthenticationStatus; +import javax.security.enterprise.SecurityContext; +import javax.security.enterprise.authentication.mechanism.http.AuthenticationParameters; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.security.Principal; +import java.util.Set; + +import static javax.security.auth.message.AuthStatus.SEND_CONTINUE; +import static javax.security.auth.message.AuthStatus.SEND_FAILURE; +import static javax.security.auth.message.AuthStatus.SUCCESS; + +public class TomEESecurityContext implements SecurityContext { + @Override + public Principal getCallerPrincipal() { + return null; + } + + @Override + public <T extends Principal> Set<T> getPrincipalsByType(final Class<T> pType) { + return null; + } + + @Override + public boolean isCallerInRole(final String role) { + return false; + } + + @Override + public boolean hasAccessToWebResource(final String resource, final String... methods) { + return false; + } + + @Override + public AuthenticationStatus authenticate(final HttpServletRequest request, + final HttpServletResponse response, + final AuthenticationParameters parameters) { + + try { + final MessageInfo messageInfo = new TomEEMessageInfo(request, response, true, parameters); + final ServerAuthContext serverAuthContext = getServerAuthContext(request); + final AuthStatus authStatus = serverAuthContext.validateRequest(messageInfo, new Subject(), null); + + return mapToAuthenticationStatus(authStatus); + + } catch (final AuthException e) { + return AuthenticationStatus.SEND_FAILURE; + } + } + + private AuthenticationStatus mapToAuthenticationStatus(final AuthStatus authStatus) { + if (SUCCESS.equals(authStatus)) { + return AuthenticationStatus.SUCCESS; + } + + if (SEND_FAILURE.equals(authStatus)) { + return AuthenticationStatus.SEND_FAILURE; + } + + if (SEND_CONTINUE.equals(authStatus)) { + return AuthenticationStatus.SEND_CONTINUE; + } + + throw new IllegalArgumentException(); + } + + private ServerAuthContext getServerAuthContext(final HttpServletRequest request) throws AuthException { + final String appContext = request.getServletContext().getVirtualServerName() + " " + request.getContextPath(); + + final AuthConfigProvider authConfigProvider = + AuthConfigFactory.getFactory().getConfigProvider("HttpServlet", appContext, null); + final ServerAuthConfig serverAuthConfig = + authConfigProvider.getServerAuthConfig("HttpServlet", appContext, CallbackHandlerImpl.getInstance()); + + return serverAuthConfig.getAuthContext(null, null, null); + } +} diff --git a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java index 9343c3e..092bcff 100644 --- a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java +++ b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java @@ -16,6 +16,7 @@ */ package org.apache.tomee.security.cdi; +import org.apache.tomee.security.TomEESecurityContext; import org.apache.tomee.security.identitystore.TomEEDefaultIdentityStore; import org.apache.tomee.security.identitystore.TomEEIdentityStoreHandler; @@ -55,6 +56,8 @@ public class TomEESecurityExtension implements Extension { beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(AutoApplySessionInterceptor.class)); beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(LoginToContinueInterceptor.class)); + + beforeBeanDiscovery.addAnnotatedType(beanManager.createAnnotatedType(TomEESecurityContext.class)); } void processAuthenticationMechanismDefinitions(@Observes diff --git a/tomee/tomee-security/src/test/java/org/apache/tomee/security/context/SecurityContextTest.java b/tomee/tomee-security/src/test/java/org/apache/tomee/security/context/SecurityContextTest.java new file mode 100644 index 0000000..efb7898 --- /dev/null +++ b/tomee/tomee-security/src/test/java/org/apache/tomee/security/context/SecurityContextTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomee.security.context; + +import org.apache.tomee.security.AbstractTomEESecurityTest; +import org.junit.Ignore; +import org.junit.Test; + +import javax.inject.Inject; +import javax.security.enterprise.AuthenticationException; +import javax.security.enterprise.AuthenticationStatus; +import javax.security.enterprise.SecurityContext; +import javax.security.enterprise.authentication.mechanism.http.AuthenticationParameters; +import javax.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism; +import javax.security.enterprise.authentication.mechanism.http.HttpMessageContext; +import javax.security.enterprise.credential.UsernamePasswordCredential; +import javax.security.enterprise.identitystore.CredentialValidationResult; +import javax.security.enterprise.identitystore.IdentityStoreHandler; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; +import java.io.IOException; + +import static javax.security.enterprise.identitystore.CredentialValidationResult.Status.VALID; +import static org.junit.Assert.assertEquals; + +public class SecurityContextTest extends AbstractTomEESecurityTest { + @Test + public void authenticate() throws Exception { + final String servlet = "http://localhost:" + container.getConfiguration().getHttpPort() + "/securityContext"; + final Response response = ClientBuilder.newBuilder() + .build() + .target(servlet) + .queryParam("username", "tomcat") + .queryParam("password", "tomcat") + .request() + .get(); + assertEquals(200, response.getStatus()); + assertEquals("ok!", response.readEntity(String.class)); + } + + @Test + public void wrongPassword() throws Exception { + final String servlet = "http://localhost:" + container.getConfiguration().getHttpPort() + "/securityContext"; + assertEquals(401, ClientBuilder.newBuilder().build() + .target(servlet) + .queryParam("username", "tomcat") + .queryParam("password", "wrong") + .request() + .get().getStatus()); + } + + @WebServlet(urlPatterns = "/securityContext") + public static class TestServlet extends HttpServlet { + @Inject + private SecurityContext securityContext; + + @Override + protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) + throws ServletException, IOException { + + final AuthenticationParameters parameters = + AuthenticationParameters.withParams() + .credential(new UsernamePasswordCredential(req.getParameter("username"), + req.getParameter("password"))) + .newAuthentication(true); + + securityContext.authenticate(req, resp, parameters); + + resp.getWriter().write("ok!"); + } + } + + public static class SecurityContextHttpAuthenticationMechanism implements HttpAuthenticationMechanism { + @Inject + private IdentityStoreHandler identityStoreHandler; + + @Override + public AuthenticationStatus validateRequest(final HttpServletRequest request, + final HttpServletResponse response, + final HttpMessageContext httpMessageContext) + throws AuthenticationException { + + if (httpMessageContext.isAuthenticationRequest()) { + try { + final CredentialValidationResult result = + identityStoreHandler.validate(httpMessageContext.getAuthParameters().getCredential()); + + if (result.getStatus().equals(VALID)) { + return httpMessageContext.notifyContainerAboutLogin(result); + } + + } catch (final IllegalArgumentException | IllegalStateException e) { + // Something was sent in the header was not valid. + } + + return httpMessageContext.responseUnauthorized(); + } + + return httpMessageContext.doNothing(); + } + } +}
