[git-bridge] Add support for Oauth2 Personal Access Tokens (#12795)

* [git-bridge] Add support for Oauth2 Personal Access Tokens

Adds support for Personal Access Tokens by sending a Bearer
token authentication when the username is `git`.
The feature is controlled by `GIT_BRIDGE_ACCESS_TOKEN_ENABLED`

---------

Co-authored-by: Eric Mc Sween <5454374+emcsween@users.noreply.github.com>
GitOrigin-RevId: 5553b0b68574158ede86ceec6c618cf4c4b09c92
This commit is contained in:
Miguel Serrano
2023-05-02 11:37:55 +02:00
committed by Copybot
parent 1da76f0a8d
commit 0564532f92
6 changed files with 55 additions and 29 deletions

View File

@@ -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");

View File

@@ -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),
"/*",

View File

@@ -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);
}