HTTP Basic-Auth support for direct access to GitBlit plugin.
Allow to access directly to GitBlit without going through
the standard Gerrit login process interactively: username
and password are retrieved using HTTP Basic-Auth from the
Http Request.
This is useful when using GitBlit RSS feeds that cannot
authenticate using the manual Gerrit form-based
authentication.
Cherry-picked from 6984f3e035a663414056c21823d18007c07465b8
and adapted for Gerrit 2.5
Change-Id: Iabf3a690f67c96207390070a7d380539a03c8459
Signed-off-by: Luca Milanesio <luca.milanesio@gmail.com>
diff --git a/pom.xml b/pom.xml
index 5926b67..51b2af5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,11 @@
<scope>provided</scope>
<version>3.1</version>
</dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.4</version>
+ </dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GerritGitBlit.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GerritGitBlit.java
index 6e1fe55..8da4164 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GerritGitBlit.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/app/GerritGitBlit.java
@@ -23,6 +23,7 @@
import com.gitblit.models.UserModel;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.gitblit.auth.GerritToGitBlitUserModel;
import com.googlesource.gerrit.plugins.gitblit.auth.GerritToGitBlitUserService;
@Singleton
@@ -36,12 +37,17 @@
public UserModel authenticate(HttpServletRequest request) {
String user = (String) request.getAttribute("gerrit-username");
String token = (String) request.getAttribute("gerrit-token");
- if (token == null) {
- return null;
+ String password = (String) request.getAttribute("gerrit-password");
+ if (token != null) {
+ return GitBlit.self().authenticate(user,
+ (GerritToGitBlitUserService.SESSIONAUTH + token).toCharArray());
+ } else if(user != null && password != null){
+ return GitBlit.self().authenticate(user, password.toCharArray());
+ } else {
+ return GitBlit.self().authenticate(
+ GerritToGitBlitUserModel.ANONYMOUS_USER,
+ GerritToGitBlitUserModel.ANONYMOUS_PASSWORD);
}
-
- return GitBlit.self().authenticate(user,
- (GerritToGitBlitUserService.SESSIONAUTH + token).toCharArray());
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritAuthFilter.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritAuthFilter.java
index 81ff438..e2872d7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritAuthFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritAuthFilter.java
@@ -13,8 +13,10 @@
// limitations under the License.
package com.googlesource.gerrit.plugins.gitblit.auth;
+import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
+
import java.io.IOException;
-import java.net.HttpURLConnection;
+import java.io.UnsupportedEncodingException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
@@ -23,12 +25,18 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.codec.binary.Base64;
+
import com.gitblit.GitBlit;
import com.gitblit.models.UserModel;
+import com.google.common.base.Objects;
import com.google.gerrit.httpd.WebSession;
import com.google.inject.Provider;
+import com.google.inject.Singleton;
+@Singleton
public class GerritAuthFilter {
+ private static final String LIT_BASIC = "Basic ";
/**
* Returns the user making the request, if the user has authenticated.
@@ -58,20 +66,52 @@
ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
- HttpServletResponse httpResponse = (HttpServletResponse) response;
- if (webSession.get().isSignedIn()
- || httpRequest.getHeader("Authorization") != null) {
- request.setAttribute("gerrit-username", webSession.get().getCurrentUser()
- .getUserName());
- request.setAttribute("gerrit-token", webSession.get().getToken());
- return true;
+ String hdr = httpRequest.getHeader("Authorization");
+ if (hdr != null) {
+ return filterBasicAuth((HttpServletRequest) request,
+ (HttpServletResponse) response, hdr);
+ } else if (webSession.get().isSignedIn()) {
+ return filterSessionAuth(webSession, (HttpServletRequest) request);
} else {
- httpResponse.setStatus(HttpURLConnection.HTTP_UNAUTHORIZED);
- httpResponse.setHeader("WWW-Authenticate",
- "Basic realm=\"Gerrit Code Review\"");
+ return true;
+ }
+ }
+
+ public boolean filterSessionAuth(final Provider<WebSession> webSession,
+ HttpServletRequest request) {
+ request.setAttribute("gerrit-username", webSession.get().getCurrentUser()
+ .getUserName());
+ request.setAttribute("gerrit-token", webSession.get().getToken());
+ return true;
+ }
+
+ public boolean filterBasicAuth(HttpServletRequest request,
+ HttpServletResponse response, String hdr) throws IOException,
+ UnsupportedEncodingException {
+ if (!hdr.startsWith(LIT_BASIC)) {
+ response.setHeader("WWW-Authenticate", "Basic realm=\"Gerrit Code Review\"");
+ response.sendError(SC_UNAUTHORIZED);
return false;
}
+
+ final byte[] decoded =
+ new Base64().decode(hdr.substring(LIT_BASIC.length()).getBytes());
+ String usernamePassword =
+ new String(decoded, Objects.firstNonNull(
+ request.getCharacterEncoding(), "UTF-8"));
+ int splitPos = usernamePassword.indexOf(':');
+ if (splitPos < 1) {
+ response.setHeader("WWW-Authenticate", "Basic realm=\"Gerrit Code Review\"");
+ response.sendError(SC_UNAUTHORIZED);
+ return false;
+ }
+ request.setAttribute("gerrit-username",
+ usernamePassword.substring(0, splitPos));
+ request.setAttribute("gerrit-password",
+ usernamePassword.substring(splitPos + 1));
+
+ return true;
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserModel.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserModel.java
index fa5e377..30e3baa 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserModel.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserModel.java
@@ -25,9 +25,12 @@
import com.google.gerrit.reviewdb.client.Project.NameKey;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.project.ProjectControl.Factory;
import com.google.gerrit.server.project.RefControl;
public class GerritToGitBlitUserModel extends UserModel {
+ public static final String ANONYMOUS_USER = "$anonymous";
+ public static final char[] ANONYMOUS_PASSWORD = ANONYMOUS_USER.toCharArray();
private static final long serialVersionUID = 1L;
@@ -59,6 +62,11 @@
this.projectControlFactory = projectControlFactory;
}
+ public GerritToGitBlitUserModel(final ProjectControl.Factory projectControlFactory) {
+ super(ANONYMOUS_USER);
+ this.projectControlFactory = projectControlFactory;
+ }
+
@Deprecated
public boolean canAccessRepository(String repositoryName) {
boolean result = false;
@@ -212,4 +220,8 @@
public int compareTo(UserModel o) {
return username.compareTo(o.username);
}
+
+ public static UserModel getAnonymous(Factory projectControl) {
+ return new GerritToGitBlitUserModel(ANONYMOUS_USER, projectControl);
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserService.java b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserService.java
index 2a3e774..8b8183e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/gitblit/auth/GerritToGitBlitUserService.java
@@ -59,7 +59,10 @@
public UserModel authenticate(String username, char[] password) {
String passwordString = new String(password);
- if (passwordString.startsWith(GerritToGitBlitUserService.SESSIONAUTH)) {
+ if (username.equals(GerritToGitBlitUserModel.ANONYMOUS_USER)) {
+ return GerritToGitBlitUserModel.getAnonymous(projectControl);
+ } else if (passwordString
+ .startsWith(GerritToGitBlitUserService.SESSIONAUTH)) {
return authenticateSSO(username,
passwordString.substring(GerritToGitBlitUserService.SESSIONAUTH
.length()));