blob: ac4340b93edb01653f9d143eb7585e8914fc700c [file] [log] [blame]
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.googlesource.gerrit.plugins.github.oauth;
import java.io.IOException;
import java.net.HttpURLConnection;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.http.client.HttpClient;
import org.kohsuke.github.GHMyself;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class OAuthFilter implements Filter {
private static final org.slf4j.Logger log = LoggerFactory
.getLogger(OAuthFilter.class);
private static final String GERRIT_COOKIE_NAME = "GerritAccount";
private final GitHubOAuthConfig config;
private final OAuthCookieProvider cookieProvider;
private final OAuthProtocol oauth;
@Inject
public OAuthFilter(GitHubOAuthConfig config) {
this.config = config;
this.cookieProvider = new OAuthCookieProvider(new TokenCipher());
HttpClient httpClient;
httpClient = new GitHubHttpProvider().get();
this.oauth = new OAuthProtocol(config, httpClient, new Gson());
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (!config.enabled) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
log.debug("doFilter(" + httpRequest.getRequestURI() + ") code="
+ request.getParameter("code") + " me=" + oauth.me());
Cookie gerritCookie = getGerritCookie(httpRequest);
try {
OAuthCookie authCookie =
getOAuthCookie(httpRequest, (HttpServletResponse) response);
if(oauth.isOAuthLogout((HttpServletRequest) request)) {
GitHubLogoutServletResponse bufferedResponse = new GitHubLogoutServletResponse((HttpServletResponse) response,
config.logoutRedirectUrl);
chain.doFilter(httpRequest, bufferedResponse);
} else if (((oauth.isOAuthLogin(httpRequest) || oauth.isOAuthFinal(httpRequest)) && authCookie == null)
|| (authCookie == null && gerritCookie == null)) {
if (oauth.isOAuthFinal(httpRequest)) {
GHMyself myself =
oauth.loginPhase2(httpRequest, httpResponse).hub.getMyself();
String user = myself.getLogin();
String email = myself.getEmail();
String fullName =
Strings.emptyToNull(myself.getName()) == null ? user : myself
.getName();
if (user != null) {
OAuthCookie userCookie =
cookieProvider.getFromUser(user, email, fullName);
httpResponse.addCookie(userCookie);
httpResponse.sendRedirect(oauth.getTargetUrl(request));
return;
} else {
httpResponse.sendError(HttpURLConnection.HTTP_UNAUTHORIZED,
"Login failed");
}
} else {
if (oauth.isOAuthLogin(httpRequest)) {
oauth.loginPhase1(httpRequest, httpResponse);
} else {
chain.doFilter(request, response);
}
}
return;
} else {
if (gerritCookie != null && !oauth.isOAuthLogin(httpRequest)) {
if (authCookie != null) {
authCookie.setMaxAge(0);
authCookie.setValue("");
httpResponse.addCookie(authCookie);
}
} else if (authCookie != null) {
httpRequest =
new AuthenticatedHttpRequest(httpRequest, config.httpHeader,
authCookie.user, config.httpDisplaynameHeader,
authCookie.fullName, config.httpEmailHeader, authCookie.email);
}
if (oauth.isOAuthFinalForOthers(httpRequest)) {
httpResponse.sendRedirect(oauth.getTargetOAuthFinal(httpRequest));
return;
} else {
chain.doFilter(httpRequest, response);
}
}
} finally {
HttpSession httpSession = httpRequest.getSession();
if (gerritCookie != null && httpSession != null) {
String gerritCookieValue = gerritCookie.getValue();
String gerritSessionValue =
(String) httpSession.getAttribute("GerritAccount");
if (gerritSessionValue == null) {
httpSession.setAttribute("GerritAccount", gerritCookieValue);
} else if (!gerritSessionValue.equals(gerritCookieValue)) {
httpSession.invalidate();
}
}
}
}
private Cookie getGerritCookie(HttpServletRequest httpRequest) {
for (Cookie cookie : httpRequest.getCookies()) {
if (cookie.getName().equalsIgnoreCase(GERRIT_COOKIE_NAME)) {
return cookie;
}
}
return null;
}
private OAuthCookie getOAuthCookie(HttpServletRequest request,
HttpServletResponse response) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equalsIgnoreCase(OAuthCookie.OAUTH_COOKIE_NAME)
&& !Strings.isNullOrEmpty(cookie.getValue())) {
try {
return cookieProvider.getFromCookie(cookie);
} catch (OAuthTokenException e) {
log.warn(
"Invalid cookie detected: cleaning up and sending a reset back to the browser",
e);
cookie.setValue("");
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
return null;
}
}
}
return null;
}
@Override
public void destroy() {
log.info("Init");
}
}