diff --git a/services/git-bridge/conf/envsubst_template.json b/services/git-bridge/conf/envsubst_template.json index e9c08ef5c9..13d2f6fef3 100644 --- a/services/git-bridge/conf/envsubst_template.json +++ b/services/git-bridge/conf/envsubst_template.json @@ -11,6 +11,7 @@ "oauth2ClientSecret": "${GIT_BRIDGE_OAUTH2_CLIENT_SECRET}", "oauth2Server": "${GIT_BRIDGE_OAUTH2_SERVER:-https://localhost}" }, + "userPasswordEnabled": ${GIT_BRIDGE_USER_PASSWORD_ENABLED:-true}, "repoStore": { "maxFileNum": ${GIT_BRIDGE_REPOSTORE_MAX_FILE_NUM:-2000}, "maxFileSize": ${GIT_BRIDGE_REPOSTORE_MAX_FILE_SIZE:-52428800} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java index 8dbef10b23..af1850188d 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java @@ -31,6 +31,7 @@ public class Config implements JSONSource { config.postbackURL, config.serviceName, Oauth2.asSanitised(config.oauth2), + config.userPasswordEnabled, config.repoStore, SwapStoreConfig.sanitisedCopy(config.swapStore), config.swapJob, @@ -47,6 +48,7 @@ public class Config implements JSONSource { private String serviceName; @Nullable private Oauth2 oauth2; + private boolean userPasswordEnabled; @Nullable private RepoStoreConfig repoStore; @Nullable @@ -75,6 +77,7 @@ public class Config implements JSONSource { String postbackURL, String serviceName, Oauth2 oauth2, + boolean userPasswordEnabled, RepoStoreConfig repoStore, SwapStoreConfig swapStore, SwapJobConfig swapJob, @@ -88,6 +91,7 @@ public class Config implements JSONSource { this.postbackURL = postbackURL; this.serviceName = serviceName; this.oauth2 = oauth2; + this.userPasswordEnabled = userPasswordEnabled; this.repoStore = repoStore; this.swapStore = swapStore; this.swapJob = swapJob; @@ -118,6 +122,7 @@ public class Config implements JSONSource { postbackURL += "/"; } oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class); + userPasswordEnabled = getOptionalString(configObject, "userPasswordEnabled").equals("true"); repoStore = new Gson().fromJson( configObject.get("repoStore"), RepoStoreConfig.class); swapStore = new Gson().fromJson( @@ -173,6 +178,10 @@ public class Config implements JSONSource { return oauth2 != null; } + public boolean isUserPasswordEnabled() { + return userPasswordEnabled; + } + public Oauth2 getOauth2() { if (!isUsingOauth2()) { throw new AssertionError("Getting oauth2 when not using it"); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java index 5e76f00128..f0e700e2ee 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java @@ -166,7 +166,11 @@ public class GitBridgeServer { final ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); if (config.isUsingOauth2()) { - Filter filter = new Oauth2Filter(snapshotApi, config.getOauth2()); + Filter filter = new Oauth2Filter( + snapshotApi, + config.getOauth2(), + config.isUserPasswordEnabled() + ); servletContextHandler.addFilter( new FilterHolder(filter), "/*", diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/Oauth2Filter.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/Oauth2Filter.java index 4174e70d72..df639dc1b9 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/Oauth2Filter.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/Oauth2Filter.java @@ -32,9 +32,12 @@ public class Oauth2Filter implements Filter { private final Oauth2 oauth2; - public Oauth2Filter(SnapshotApi snapshotApi, Oauth2 oauth2) { + private final boolean isUserPasswordEnabled; + + public Oauth2Filter(SnapshotApi snapshotApi, Oauth2 oauth2, boolean isUserPasswordEnabled) { this.snapshotApi = snapshotApi; this.oauth2 = oauth2; + this.isUserPasswordEnabled = isUserPasswordEnabled; } @Override @@ -151,42 +154,49 @@ public class Oauth2Filter implements Filter { if (split.length == 2) { String username = split[0]; String password = split[1]; - String accessToken = null; - if (username.length() > 0) { - capturedUsername = username; - } - try { - accessToken = new PasswordTokenRequest( + + final Credential cred = new Credential.Builder( + BearerToken.authorizationHeaderAccessMethod() + ).build(); + + if(username.equals("git")) { + Log.debug("[{}] username is 'git', skipping password grant flow", projectName); + cred.setAccessToken(password); + } else if (this.isUserPasswordEnabled) { + String accessToken = null; + if (username.length() > 0) { + capturedUsername = username; + } + try { + accessToken = new PasswordTokenRequest( Instance.httpTransport, Instance.jsonFactory, new GenericUrl( - oauth2.getOauth2Server() - + "/oauth/token?client_ip=" - + clientIp + oauth2.getOauth2Server() + + "/oauth/token?client_ip=" + + clientIp ), username, password - ).setClientAuthentication( - new ClientParametersAuthentication( - oauth2.getOauth2ClientID(), - oauth2.getOauth2ClientSecret() - ) - ).execute().getAccessToken(); - } catch (TokenResponseException e) { - handleNeedAuthorization(projectName, capturedUsername, e.getStatusCode(), request, response); - return; + ).setClientAuthentication( + new ClientParametersAuthentication( + oauth2.getOauth2ClientID(), + oauth2.getOauth2ClientSecret() + ) + ).execute().getAccessToken(); + } catch (TokenResponseException e) { + handleNeedAuthorization(projectName, capturedUsername, e.getStatusCode(), request, response); + return; + } + cred.setAccessToken(accessToken); } - final Credential cred = new Credential.Builder( - BearerToken.authorizationHeaderAccessMethod( - ) - ).build(); - cred.setAccessToken(accessToken); - servletRequest.setAttribute(ATTRIBUTE_KEY, cred); + servletRequest.setAttribute(ATTRIBUTE_KEY, cred); filterChain.doFilter( - servletRequest, - servletResponse + servletRequest, + servletResponse ); + } else { handleNeedAuthorization(projectName, capturedUsername, 0, request, response); } diff --git a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java index 02d70def0e..90d1606967 100644 --- a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java +++ b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/application/config/ConfigTest.java @@ -92,6 +92,7 @@ public class ConfigTest { " \"oauth2ClientSecret\": \"\",\n" + " \"oauth2Server\": \"https://www.overleaf.com\"\n" + " },\n" + + " \"userPasswordEnabled\": false,\n" + " \"repoStore\": null,\n" + " \"swapStore\": null,\n" + " \"swapJob\": null,\n" + @@ -104,4 +105,4 @@ public class ConfigTest { ); } -} \ No newline at end of file +} diff --git a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java index cb94bdf2fb..0c6ac74344 100644 --- a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java +++ b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/BridgeTest.java @@ -62,6 +62,7 @@ public class BridgeTest { "", "", null, + false, null, null, null,