From 97cc0e7b9c96a96ebe648c50e9b60ab49f04aa13 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Mon, 17 Feb 2020 11:08:08 +0100 Subject: [PATCH] Use access key directly, not the jwt token --- .../main/java/sonia/scm/security/Xsrf.java | 10 ++++---- .../sonia/scm/repository/HgEnvironment.java | 24 ++++++------------- .../sonia/scm/repository/HgHookManager.java | 7 ++---- .../scm/repository/HgEnvironmentTest.java | 18 ++++++++++---- .../java/sonia/scm/repository/HgTestUtil.java | 6 +++-- 5 files changed, 31 insertions(+), 34 deletions(-) rename {scm-webapp => scm-core}/src/main/java/sonia/scm/security/Xsrf.java (94%) diff --git a/scm-webapp/src/main/java/sonia/scm/security/Xsrf.java b/scm-core/src/main/java/sonia/scm/security/Xsrf.java similarity index 94% rename from scm-webapp/src/main/java/sonia/scm/security/Xsrf.java rename to scm-core/src/main/java/sonia/scm/security/Xsrf.java index f9ee8a0872..83e83c80b4 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/Xsrf.java +++ b/scm-core/src/main/java/sonia/scm/security/Xsrf.java @@ -32,15 +32,15 @@ package sonia.scm.security; /** * Shared constants for Xsrf related classes. - * + * * @author Sebastian Sdorra * @since 2.0.0 */ public final class Xsrf { - - static final String HEADER_KEY = "X-XSRF-Token"; - - static final String TOKEN_KEY = "xsrf"; + + public static final String HEADER_KEY = "X-XSRF-Token"; + + public static final String TOKEN_KEY = "xsrf"; private Xsrf() { } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgEnvironment.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgEnvironment.java index 1bcbcc321a..a9328c1129 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgEnvironment.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgEnvironment.java @@ -36,11 +36,11 @@ package sonia.scm.repository; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.ProvisionException; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import sonia.scm.security.AccessToken; import sonia.scm.security.CipherUtil; +import sonia.scm.security.Xsrf; import sonia.scm.web.HgUtil; import javax.servlet.http.HttpServletRequest; @@ -119,9 +119,9 @@ public final class HgEnvironment } try { - String credentials = hookManager.getCredentials(); - environment.put(SCM_BEARER_TOKEN, CipherUtil.getInstance().encode(credentials)); - extractXsrfKey(environment, credentials); + AccessToken accessToken = hookManager.getAccessToken(); + environment.put(SCM_BEARER_TOKEN, CipherUtil.getInstance().encode(accessToken.compact())); + extractXsrfKey(environment, accessToken); } catch (ProvisionException e) { LOG.debug("could not create bearer token; looks like currently we are not in a request; probably you can ignore the following exception:", e); } @@ -130,17 +130,7 @@ public final class HgEnvironment environment.put(ENV_CHALLENGE, hookManager.getChallenge()); } - private static void extractXsrfKey(Map environment, String credentials) { - // we need to remove the signature, because we cannot access the key and otherwise the parser would fail - String[] tokenParts = credentials.split("\\."); - String tokenWithoutSignature = tokenParts[0] + "." + tokenParts[1] + "."; - Claims claims = (Claims) Jwts.parser().parse(tokenWithoutSignature).getBody(); - - Object xsrf = claims.get("xsrf"); - if (xsrf != null) { - environment.put(SCM_XSRF, xsrf.toString()); - } else { - environment.put(SCM_XSRF, "-"); - } + private static void extractXsrfKey(Map environment, AccessToken accessToken) { + environment.put(SCM_XSRF, accessToken.getCustom(Xsrf.TOKEN_KEY).orElse("-")); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java index 9784f3d49d..314bd85b57 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/HgHookManager.java @@ -49,7 +49,6 @@ import sonia.scm.config.ScmConfigurationChangedEvent; import sonia.scm.net.ahc.AdvancedHttpClient; import sonia.scm.security.AccessToken; import sonia.scm.security.AccessTokenBuilderFactory; -import sonia.scm.security.CipherUtil; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; @@ -196,11 +195,9 @@ public class HgHookManager return this.challenge.equals(challenge); } - public String getCredentials() + public AccessToken getAccessToken() { - AccessToken accessToken = accessTokenBuilderFactory.create().build(); - - return accessToken.compact(); + return accessTokenBuilderFactory.create().build(); } //~--- methods -------------------------------------------------------------- diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgEnvironmentTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgEnvironmentTest.java index 678a1f70c5..2718e0b899 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgEnvironmentTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgEnvironmentTest.java @@ -5,20 +5,22 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import sonia.scm.security.AccessToken; +import sonia.scm.security.Xsrf; import java.util.HashMap; import java.util.Map; +import static java.util.Optional.empty; +import static java.util.Optional.of; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class HgEnvironmentTest { - private static final String CREDENTIALS_WITH_XSRF = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW50Iiwic2NtLW1hbmFnZXIucGFyZW50VG9rZW5JZCI6IkFCQyIsInhzcmYiOiJYU1JGIFRva2VuIiwiaWF0IjoxNTgxNTg3MzUzLCJqdGkiOiJFV1JxTjlNMTQ5In0.jgsIoE_2TnTEwbuaqQp8XyKpId5qlYURmYamf9m_08w"; - private static final String CREDENTIALS_WITHOUT_XSRF = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW50Iiwic2NtLW1hbmFnZXIucGFyZW50VG9rZW5JZCI6IkFCQyIsImlhdCI6MTU4MTU4NzM1MywianRpIjoiRVdScU45TTE0OSJ9.VdMz5-NpREiIvLEw9JVJNEUnoY0am0j1lZ0kisblayk"; - @Mock HgRepositoryHandler handler; @Mock @@ -26,7 +28,10 @@ class HgEnvironmentTest { @Test void shouldExtractXsrfTokenWhenSet() { - when(hookManager.getCredentials()).thenReturn(CREDENTIALS_WITH_XSRF); + AccessToken accessToken = mock(AccessToken.class); + when(accessToken.compact()).thenReturn(""); + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(of("XSRF Token")); + when(hookManager.getAccessToken()).thenReturn(accessToken); Map environment = new HashMap<>(); HgEnvironment.prepareEnvironment(environment, handler, hookManager); @@ -36,7 +41,10 @@ class HgEnvironmentTest { @Test void shouldIgnoreXsrfWhenNotSetButStillContainDummy() { - when(hookManager.getCredentials()).thenReturn(CREDENTIALS_WITHOUT_XSRF); + AccessToken accessToken = mock(AccessToken.class); + when(accessToken.compact()).thenReturn(""); + when(accessToken.getCustom(Xsrf.TOKEN_KEY)).thenReturn(empty()); + when(hookManager.getAccessToken()).thenReturn(accessToken); Map environment = new HashMap<>(); HgEnvironment.prepareEnvironment(environment, handler, hookManager); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgTestUtil.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgTestUtil.java index ee5117b276..a5be01465f 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgTestUtil.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/HgTestUtil.java @@ -38,6 +38,7 @@ package sonia.scm.repository; import org.junit.Assume; import sonia.scm.SCMContext; import sonia.scm.TempDirRepositoryLocationResolver; +import sonia.scm.security.AccessToken; import sonia.scm.store.InMemoryConfigurationStoreFactory; import javax.servlet.http.HttpServletRequest; @@ -107,7 +108,6 @@ public final class HgTestUtil RepositoryLocationResolver repositoryLocationResolver = new TempDirRepositoryLocationResolver(directory); HgRepositoryHandler handler = new HgRepositoryHandler(new InMemoryConfigurationStoreFactory(), new HgContextProvider(), repositoryLocationResolver, null, null); - Path repoDir = directory.toPath(); handler.init(context); return handler; @@ -128,7 +128,9 @@ public final class HgTestUtil "http://localhost:8081/scm/hook/hg/"); when(hookManager.createUrl(any(HttpServletRequest.class))).thenReturn( "http://localhost:8081/scm/hook/hg/"); - when(hookManager.getCredentials()).thenReturn(""); + AccessToken accessToken = mock(AccessToken.class); + when(accessToken.compact()).thenReturn(""); + when(hookManager.getAccessToken()).thenReturn(accessToken); return hookManager; }