diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/pom.xml b/multiuser/machine-auth/che-multiuser-machine-authentication-agent/pom.xml deleted file mode 100644 index d1dc770219d..00000000000 --- a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/pom.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - 4.0.0 - - che-multiuser-machine-auth - org.eclipse.che.multiuser - 7.4.0-SNAPSHOT - - che-multiuser-machine-authentication-agent - Che Multiuser :: Machine Authentication Agent - - ${project.build.directory}/generated-sources/dto/ - - - - com.google.guava - guava - - - io.jsonwebtoken - jjwt - - - javax.inject - javax.inject - - - javax.servlet - javax.servlet-api - - - org.eclipse.che.core - che-core-api-core - - - org.eclipse.che.core - che-core-commons-auth - - - org.eclipse.che.core - che-core-commons-test - - - org.eclipse.che.multiuser - che-multiuser-machine-authentication-shared - - - com.google.code.gson - gson - test - - - javax.ws.rs - javax.ws.rs-api - test - - - org.everrest - everrest-test - test - - - org.hamcrest - hamcrest-core - test - - - org.mockito - mockito-core - test - - - org.mockito - mockito-testng - test - - - org.testng - testng - test - - - diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/main/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilter.java b/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/main/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilter.java deleted file mode 100644 index 1a03365145a..00000000000 --- a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/main/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilter.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.multiuser.machine.authentication.agent; - -import static com.google.common.base.Strings.isNullOrEmpty; -import static java.lang.String.format; -import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; -import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.MACHINE_TOKEN_KIND; -import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.USER_ID_CLAIM; -import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.USER_NAME_CLAIM; -import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.WORKSPACE_ID_CLAIM; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.SignatureException; -import io.jsonwebtoken.UnsupportedJwtException; -import java.io.IOException; -import java.security.PublicKey; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import org.eclipse.che.commons.auth.token.RequestTokenExtractor; -import org.eclipse.che.commons.env.EnvironmentContext; -import org.eclipse.che.commons.subject.Subject; -import org.eclipse.che.commons.subject.SubjectImpl; - -/** - * Protects user's machine from unauthorized access. - * - * @author Anton Korneta - */ -@Singleton -public class MachineLoginFilter implements Filter { - - private final PublicKey publicKey; - private final RequestTokenExtractor tokenExtractor; - - private final String workspaceId; - - @Inject - public MachineLoginFilter( - @Named("env.CHE_WORKSPACE_ID") String workspaceId, - @Named("signature.public.key") PublicKey publicKey, - RequestTokenExtractor tokenExtractor) { - this.tokenExtractor = tokenExtractor; - this.publicKey = publicKey; - this.workspaceId = workspaceId; - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException {} - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - final HttpServletRequest httpRequest = (HttpServletRequest) request; - final HttpSession session = httpRequest.getSession(false); - - // sets subject from session - final Subject sessionSubject; - if (session != null - && (sessionSubject = (Subject) session.getAttribute("che_subject")) != null) { - try { - EnvironmentContext.getCurrent().setSubject(sessionSubject); - chain.doFilter(request, response); - return; - } finally { - EnvironmentContext.reset(); - } - } - - // retrieves a token from a request and verify it - final String token = tokenExtractor.getToken(httpRequest); - if (isNullOrEmpty(token)) { - sendErr(response, SC_UNAUTHORIZED, "Authentication on machine failed, token is missed."); - return; - } - - // checks token signature and workspace identifier if ok then sets subject into the context - try { - final Jws jwt = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token); - final Claims claims = jwt.getBody(); - if (!isValidToken(jwt)) { - sendErr( - response, SC_UNAUTHORIZED, "Authentication on machine failed, invalid token provided."); - return; - } - - try { - final SubjectImpl subject = - new SubjectImpl( - claims.get(USER_NAME_CLAIM, String.class), - claims.get(USER_ID_CLAIM, String.class), - token, - false); - EnvironmentContext.getCurrent().setSubject(subject); - final HttpSession httpSession = httpRequest.getSession(true); - httpSession.setAttribute("che_subject", subject); - chain.doFilter(request, response); - } finally { - EnvironmentContext.reset(); - } - } catch (ExpiredJwtException - | UnsupportedJwtException - | MalformedJwtException - | SignatureException - | IllegalArgumentException ex) { - sendErr( - response, - SC_UNAUTHORIZED, - format("Authentication on machine failed cause: '%s'", ex.getMessage())); - } - } - - /** Checks whether given JWT token is valid */ - private boolean isValidToken(Jws jwt) { - return MACHINE_TOKEN_KIND.equals(jwt.getHeader().get("kind")) - && workspaceId.equals(jwt.getBody().get(WORKSPACE_ID_CLAIM, String.class)); - } - - /** Sets given error code with err message into give response. */ - private static void sendErr(ServletResponse res, int errCode, String msg) throws IOException { - final HttpServletResponse response = (HttpServletResponse) res; - response.sendError(errCode, msg); - } - - @Override - public void destroy() {} -} diff --git a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/test/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilterTest.java b/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/test/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilterTest.java deleted file mode 100644 index aa3ee6ea5a8..00000000000 --- a/multiuser/machine-auth/che-multiuser-machine-authentication-agent/src/test/java/org/eclipse/che/multiuser/machine/authentication/agent/MachineLoginFilterTest.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.multiuser.machine.authentication.agent; - -import static io.jsonwebtoken.SignatureAlgorithm.RS512; -import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; -import static org.eclipse.che.multiuser.machine.authentication.shared.Constants.MACHINE_TOKEN_KIND; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import com.google.gson.Gson; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.ws.rs.core.HttpHeaders; -import org.eclipse.che.commons.auth.token.RequestTokenExtractor; -import org.eclipse.che.commons.subject.Subject; -import org.eclipse.che.commons.subject.SubjectImpl; -import org.eclipse.che.multiuser.machine.authentication.shared.Constants; -import org.mockito.Mock; -import org.mockito.testng.MockitoTestNGListener; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; - -/** - * Tests {@link MachineLoginFilter}. - * - * @author Anton Korneta - */ -@Listeners(MockitoTestNGListener.class) -public class MachineLoginFilterTest { - - private static final int KEY_SIZE = 1024; - - private static final Gson GSON = new Gson(); - - private static final String SIGNATURE_ALGORITHM = "RSA"; - private static final String WORKSPACE_ID = "workspace31"; - private static final String SUBJECT = "che_subject"; - private static final String USER_ID = "test_user31"; - private static final String USER_NAME = "test_user"; - - private static final Map HEADER = new HashMap<>(); - private static final Map CLAIMS = new HashMap<>(2); - - static { - HEADER.put("kind", MACHINE_TOKEN_KIND); - CLAIMS.put(Constants.WORKSPACE_ID_CLAIM, WORKSPACE_ID); - CLAIMS.put(Constants.USER_ID_CLAIM, USER_ID); - CLAIMS.put(Constants.USER_NAME_CLAIM, USER_NAME); - CLAIMS.put(Claims.ID, "8312-213-1we31"); - } - - @Mock private RequestTokenExtractor tokenExtractorMock; - @Mock private FilterChain chainMock; - @Mock private HttpSession sessionMock; - @Mock private HttpServletResponse responseMock; - - private MachineLoginFilter machineLoginFilter; - - private String machineToken; - private KeyPair keyPair; - private Subject subject; - - @BeforeMethod - public void setUp() throws Exception { - final KeyPairGenerator kpg = KeyPairGenerator.getInstance(SIGNATURE_ALGORITHM); - kpg.initialize(KEY_SIZE); - keyPair = kpg.generateKeyPair(); - machineToken = - Jwts.builder() - .setClaims(CLAIMS) - .setHeader(HEADER) - .signWith(RS512, keyPair.getPrivate()) - .compact(); - machineLoginFilter = - spy(new MachineLoginFilter(WORKSPACE_ID, keyPair.getPublic(), tokenExtractorMock)); - - subject = new SubjectImpl(USER_NAME, USER_ID, machineToken, false); - lenient() - .when(tokenExtractorMock.getToken(any(HttpServletRequest.class))) - .thenReturn(machineToken); - } - - @Test - public void testProcessRequestWithSubjectFromSession() throws Exception { - when(sessionMock.getAttribute(SUBJECT)).thenReturn(subject); - - machineLoginFilter.doFilter(getRequestMock(sessionMock, machineToken), responseMock, chainMock); - - verify(sessionMock).getAttribute(SUBJECT); - verifyZeroInteractions(tokenExtractorMock); - } - - @Test - public void testSetErrorInResponseWhenNullTokenProvided() throws Exception { - when(tokenExtractorMock.getToken(any(HttpServletRequest.class))).thenReturn(null); - - machineLoginFilter.doFilter(getRequestMock(null, machineToken), responseMock, chainMock); - - verify(tokenExtractorMock).getToken(any(HttpServletRequest.class)); - verify(responseMock) - .sendError(SC_UNAUTHORIZED, "Authentication on machine failed, token is missed."); - } - - @Test - public void testProcessRequestWithValidTokenAndCreateSession() throws Exception { - machineLoginFilter.doFilter(getRequestMock(null, machineToken), responseMock, chainMock); - - verify(tokenExtractorMock).getToken(any(HttpServletRequest.class)); - verify(sessionMock).setAttribute(SUBJECT, subject); - verifyZeroInteractions(responseMock); - } - - @Test - public void testSetErrorInResponseWhenInvalidTokenProvided() throws Exception { - final String invalidToken = "invalid_token"; - when(tokenExtractorMock.getToken(any(HttpServletRequest.class))).thenReturn(invalidToken); - - machineLoginFilter.doFilter(getRequestMock(null, invalidToken), responseMock, chainMock); - - verify(tokenExtractorMock).getToken(any(HttpServletRequest.class)); - verify(responseMock) - .sendError( - eq(SC_UNAUTHORIZED), - argThat(s -> s.startsWith("Authentication on machine failed cause:"))); - } - - @Test - public void testSetErrorInResponseWhenNonMachineTokenProvided() throws Exception { - final String differentToken = - Jwts.builder() - .setPayload(GSON.toJson(subject)) - .setHeader(new HashMap<>()) - .signWith(RS512, keyPair.getPrivate()) - .compact(); - when(tokenExtractorMock.getToken(any(HttpServletRequest.class))).thenReturn(differentToken); - - machineLoginFilter.doFilter(getRequestMock(null, differentToken), responseMock, chainMock); - - verify(tokenExtractorMock).getToken(any(HttpServletRequest.class)); - verify(responseMock) - .sendError(SC_UNAUTHORIZED, "Authentication on machine failed, invalid token provided."); - } - - @Test - public void testSetErrorInResponseWhenTokenIsNotRelatedToThisWorkspace() throws Exception { - final Map headers = new HashMap<>(); - headers.put("kind", MACHINE_TOKEN_KIND); - headers.put("workspace", "workspace73"); - final String differentToken = - Jwts.builder() - .setPayload(GSON.toJson(subject)) - .setHeader(headers) - .signWith(RS512, keyPair.getPrivate()) - .compact(); - when(tokenExtractorMock.getToken(any(HttpServletRequest.class))).thenReturn(differentToken); - - machineLoginFilter.doFilter(getRequestMock(null, differentToken), responseMock, chainMock); - - verify(tokenExtractorMock).getToken(any(HttpServletRequest.class)); - verify(responseMock) - .sendError(SC_UNAUTHORIZED, "Authentication on machine failed, invalid token provided."); - } - - // if the session is null it means that there will be created new one - private HttpServletRequest getRequestMock(HttpSession session, String token) { - final HttpServletRequest request = mock(HttpServletRequest.class); - lenient().when(request.getSession(false)).thenReturn(session); - lenient().when(request.getSession(true)).thenReturn(sessionMock); - lenient().when(request.getHeader(HttpHeaders.AUTHORIZATION)).thenReturn(token); - return request; - } -} diff --git a/multiuser/machine-auth/pom.xml b/multiuser/machine-auth/pom.xml index 291769cf376..090980d565f 100644 --- a/multiuser/machine-auth/pom.xml +++ b/multiuser/machine-auth/pom.xml @@ -26,6 +26,5 @@ che-multiuser-machine-authentication-shared che-multiuser-machine-authentication - che-multiuser-machine-authentication-agent diff --git a/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Credentials.java b/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Credentials.java deleted file mode 100644 index e4d7f3f1ec1..00000000000 --- a/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Credentials.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.api.auth.shared.dto; - -import org.eclipse.che.dto.shared.DTO; - -/** @author gazarenkov */ -@DTO -public interface Credentials { - - String getRealm(); - - void setRealm(String realm); - - Credentials withRealm(String realm); - - String getUsername(); - - void setUsername(String name); - - Credentials withUsername(String name); - - String getPassword(); - - void setPassword(String password); - - Credentials withPassword(String password); -} diff --git a/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Token.java b/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Token.java deleted file mode 100644 index a5f551aeabf..00000000000 --- a/wsmaster/che-core-api-auth-shared/src/main/java/org/eclipse/che/api/auth/shared/dto/Token.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.api.auth.shared.dto; - -import org.eclipse.che.dto.shared.DTO; - -/** - * Authentication token. - * - * @author gazarenkov - */ -@DTO -public interface Token { - /** "Authentication token obtained after login" */ - String getValue(); - - void setValue(String value); - - Token withValue(String value); -}