mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 17:05:43 +01:00
Use access key directly, not the jwt token
This commit is contained in:
@@ -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() {
|
||||||
}
|
}
|
||||||
@@ -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, "-");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 --------------------------------------------------------------
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user