Use access key directly, not the jwt token

This commit is contained in:
Rene Pfeuffer
2020-02-17 11:08:08 +01:00
parent 4fb8884bf2
commit 97cc0e7b9c
5 changed files with 31 additions and 34 deletions

View File

@@ -32,15 +32,15 @@ package sonia.scm.security;
/** /**
* Shared constants for Xsrf related classes. * Shared constants for Xsrf related classes.
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
* @since 2.0.0 * @since 2.0.0
*/ */
public final class Xsrf { public final class Xsrf {
static final String HEADER_KEY = "X-XSRF-Token"; public static final String HEADER_KEY = "X-XSRF-Token";
static final String TOKEN_KEY = "xsrf"; public static final String TOKEN_KEY = "xsrf";
private Xsrf() { private Xsrf() {
} }

View File

@@ -36,11 +36,11 @@ package sonia.scm.repository;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.security.AccessToken;
import sonia.scm.security.CipherUtil; import sonia.scm.security.CipherUtil;
import sonia.scm.security.Xsrf;
import sonia.scm.web.HgUtil; import sonia.scm.web.HgUtil;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -119,9 +119,9 @@ public final class HgEnvironment
} }
try { try {
String credentials = hookManager.getCredentials(); AccessToken accessToken = hookManager.getAccessToken();
environment.put(SCM_BEARER_TOKEN, CipherUtil.getInstance().encode(credentials)); environment.put(SCM_BEARER_TOKEN, CipherUtil.getInstance().encode(accessToken.compact()));
extractXsrfKey(environment, credentials); extractXsrfKey(environment, accessToken);
} catch (ProvisionException e) { } 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); 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()); environment.put(ENV_CHALLENGE, hookManager.getChallenge());
} }
private static void extractXsrfKey(Map<String, String> environment, String credentials) { private static void extractXsrfKey(Map<String, String> environment, AccessToken accessToken) {
// we need to remove the signature, because we cannot access the key and otherwise the parser would fail environment.put(SCM_XSRF, accessToken.<String>getCustom(Xsrf.TOKEN_KEY).orElse("-"));
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, "-");
}
} }
} }

View File

@@ -49,7 +49,6 @@ import sonia.scm.config.ScmConfigurationChangedEvent;
import sonia.scm.net.ahc.AdvancedHttpClient; import sonia.scm.net.ahc.AdvancedHttpClient;
import sonia.scm.security.AccessToken; import sonia.scm.security.AccessToken;
import sonia.scm.security.AccessTokenBuilderFactory; import sonia.scm.security.AccessTokenBuilderFactory;
import sonia.scm.security.CipherUtil;
import sonia.scm.util.HttpUtil; import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util; import sonia.scm.util.Util;
@@ -196,11 +195,9 @@ public class HgHookManager
return this.challenge.equals(challenge); return this.challenge.equals(challenge);
} }
public String getCredentials() public AccessToken getAccessToken()
{ {
AccessToken accessToken = accessTokenBuilderFactory.create().build(); return accessTokenBuilderFactory.create().build();
return accessToken.compact();
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------

View File

@@ -5,20 +5,22 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.security.AccessToken;
import sonia.scm.security.Xsrf;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; 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.assertThat;
import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.entry;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class HgEnvironmentTest { 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 @Mock
HgRepositoryHandler handler; HgRepositoryHandler handler;
@Mock @Mock
@@ -26,7 +28,10 @@ class HgEnvironmentTest {
@Test @Test
void shouldExtractXsrfTokenWhenSet() { 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<String, String> environment = new HashMap<>(); Map<String, String> environment = new HashMap<>();
HgEnvironment.prepareEnvironment(environment, handler, hookManager); HgEnvironment.prepareEnvironment(environment, handler, hookManager);
@@ -36,7 +41,10 @@ class HgEnvironmentTest {
@Test @Test
void shouldIgnoreXsrfWhenNotSetButStillContainDummy() { 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<String, String> environment = new HashMap<>(); Map<String, String> environment = new HashMap<>();
HgEnvironment.prepareEnvironment(environment, handler, hookManager); HgEnvironment.prepareEnvironment(environment, handler, hookManager);

View File

@@ -38,6 +38,7 @@ package sonia.scm.repository;
import org.junit.Assume; import org.junit.Assume;
import sonia.scm.SCMContext; import sonia.scm.SCMContext;
import sonia.scm.TempDirRepositoryLocationResolver; import sonia.scm.TempDirRepositoryLocationResolver;
import sonia.scm.security.AccessToken;
import sonia.scm.store.InMemoryConfigurationStoreFactory; import sonia.scm.store.InMemoryConfigurationStoreFactory;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@@ -107,7 +108,6 @@ public final class HgTestUtil
RepositoryLocationResolver repositoryLocationResolver = new TempDirRepositoryLocationResolver(directory); RepositoryLocationResolver repositoryLocationResolver = new TempDirRepositoryLocationResolver(directory);
HgRepositoryHandler handler = HgRepositoryHandler handler =
new HgRepositoryHandler(new InMemoryConfigurationStoreFactory(), new HgContextProvider(), repositoryLocationResolver, null, null); new HgRepositoryHandler(new InMemoryConfigurationStoreFactory(), new HgContextProvider(), repositoryLocationResolver, null, null);
Path repoDir = directory.toPath();
handler.init(context); handler.init(context);
return handler; return handler;
@@ -128,7 +128,9 @@ public final class HgTestUtil
"http://localhost:8081/scm/hook/hg/"); "http://localhost:8081/scm/hook/hg/");
when(hookManager.createUrl(any(HttpServletRequest.class))).thenReturn( when(hookManager.createUrl(any(HttpServletRequest.class))).thenReturn(
"http://localhost:8081/scm/hook/hg/"); "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; return hookManager;
} }