package uk.ac.ic.wlgitbridge.server; import com.google.api.client.auth.oauth2.*; import com.google.api.client.http.GenericUrl; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.gson.GsonFactory; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.eclipse.jetty.server.Request; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.ac.ic.wlgitbridge.application.config.Oauth2; import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException; import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest; import uk.ac.ic.wlgitbridge.util.Instance; import uk.ac.ic.wlgitbridge.util.Util; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.StringTokenizer; /** * Created by winston on 25/10/15. */ public class Oauth2Filter implements Filter { public static final String ATTRIBUTE_KEY = "oauth2"; private final Oauth2 oauth2; public Oauth2Filter(Oauth2 oauth2) { this.oauth2 = oauth2; } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { String project = Util.removeAllSuffixes(((Request) servletRequest).getRequestURI().split("/")[1], ".git"); GetDocRequest doc = new GetDocRequest(project); doc.request(); try { doc.getResult(); } catch (ForbiddenException e) { getAndInjectCredentials(servletRequest, servletResponse, filterChain); return; } filterChain.doFilter(servletRequest, servletResponse); } private void getAndInjectCredentials(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; String authHeader = request.getHeader("Authorization"); if (authHeader != null) { StringTokenizer st = new StringTokenizer(authHeader); if (st.hasMoreTokens()) { String basic = st.nextToken(); if (basic.equalsIgnoreCase("Basic")) { try { String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); String[] split = credentials.split(":"); if (split.length == 2) { String username = split[0]; String password = split[1]; String accessToken = null; try { accessToken = new PasswordTokenRequest(Instance.httpTransport, Instance.jsonFactory, new GenericUrl(oauth2.getOauth2Server() + "/oauth/token"), username, password) .setClientAuthentication(new ClientParametersAuthentication(oauth2.getOauth2ClientID(), oauth2.getOauth2ClientSecret())) .execute().getAccessToken(); } catch (TokenResponseException e) { unauthorized(response); return; } final Credential cred = new Credential.Builder(BearerToken.authorizationHeaderAccessMethod()) .build(); cred.setAccessToken(accessToken); servletRequest.setAttribute(ATTRIBUTE_KEY, cred); filterChain.doFilter(servletRequest, servletResponse); } else { unauthorized(response); } } catch (UnsupportedEncodingException e) { throw new Error("Couldn't retrieve authentication", e); } } } } else { unauthorized(response); } } @Override public void destroy() { } private void unauthorized(ServletResponse servletResponse) throws IOException { HttpServletResponse response = (HttpServletResponse) servletResponse; response.setContentType("text/plain"); response.setHeader("WWW-Authenticate", "Basic realm=\"Git Bridge\""); response.setStatus(401); PrintWriter w = response.getWriter(); w.println("Please sign in using your email address and Overleaf password."); w.println(); w.println("*Note*: if you sign in to Overleaf using another provider, such "); w.println("as Google or Twitter, you need to set a password on your Overleaf "); w.println("account first. Please see https://www.overleaf.com/blog/195 for "); w.println("more information."); w.close(); } }