Support hybrid OpenID and OAuth2 authentication
e9707d8f85
exposed OAuth authentication extension point. Using this
extension point plugins can offer OAuth2 authentications.
That is fine for new Gerrit sites, which can restrict the auth scheme
to OAuth2 only.
For the existing sites, that rely on non SSO OpenID auth scheme it
doesn't work to migrate to OAuth2 because of diverse contributors
base that use different OpenID providers. Not all OpenID providers
offer OAuth2 protocol. Particularly, widespread OpenID providers
among open source Gerrit communities are Launchpad/UbuntuOne and
FedoraProject don't offer OAuth2 protocol. To not lock out those
contributors from being able to contribute to open source Gerrit
based projects OpenID must still be supported.
With Google's shut down of their OpenID service in April 2015, big
user base is locked out from contribution to Gerrit based projects
that only support OpenID auth scheme.
The only way to still support OpenID 2.0 providers and new OAuth2
based protocol is native support for hybrid authentication scheme
in Gerrit.
This change extends OpenID auth scheme by making it aware of optional
OAuth plugin-based authentication.
When no oauth-provider plugins are deployed, OpenID auth scheme works
as usual. When OAuth provider plugins are deployed, OAuth2 providers
are offered on the OpenID login form, in addition to hard coded Yahoo!
and Launchpad OpenID providers: [1].
[1] http://imgur.com/IcCrChN
Change-Id: I6d70212f4fea5443a6322c7da683e1e943d058eb
This commit is contained in:
parent
b4c5a0e23f
commit
8b5aa48f1d
@ -86,7 +86,8 @@ class UrlModule extends ServletModule {
|
||||
}
|
||||
serve("/cat/*").with(CatServlet.class);
|
||||
|
||||
if (authConfig.getAuthType() != AuthType.OAUTH) {
|
||||
if (authConfig.getAuthType() != AuthType.OAUTH &&
|
||||
authConfig.getAuthType() != AuthType.OPENID) {
|
||||
serve("/logout").with(HttpLogoutServlet.class);
|
||||
serve("/signout").with(HttpLogoutServlet.class);
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ java_library(
|
||||
'//gerrit-server:server',
|
||||
'//lib:guava',
|
||||
'//lib:gwtorm',
|
||||
'//lib/commons:codec',
|
||||
'//lib/guice:guice',
|
||||
'//lib/guice:guice-servlet',
|
||||
'//lib/jgit:jgit',
|
||||
|
@ -22,11 +22,14 @@ import com.google.common.collect.Sets;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.common.PageLinks;
|
||||
import com.google.gerrit.common.auth.openid.OpenIdUrls;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
import com.google.gerrit.httpd.HtmlDomUtil;
|
||||
import com.google.gerrit.httpd.LoginUrlToken;
|
||||
import com.google.gerrit.httpd.template.SiteHeaderFooter;
|
||||
import com.google.gerrit.reviewdb.client.AuthType;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
@ -61,10 +64,13 @@ class LoginForm extends HttpServlet {
|
||||
|
||||
private final ImmutableSet<String> suggestProviders;
|
||||
private final Provider<String> urlProvider;
|
||||
private final Provider<OAuthSessionOverOpenID> oauthSessionProvider;
|
||||
private final OpenIdServiceImpl impl;
|
||||
private final int maxRedirectUrlLength;
|
||||
private final String ssoUrl;
|
||||
private final SiteHeaderFooter header;
|
||||
private final Provider<CurrentUser> currentUserProvider;
|
||||
private final DynamicMap<OAuthServiceProvider> oauthServiceProviders;
|
||||
|
||||
@Inject
|
||||
LoginForm(
|
||||
@ -72,13 +78,19 @@ class LoginForm extends HttpServlet {
|
||||
@GerritServerConfig Config config,
|
||||
AuthConfig authConfig,
|
||||
OpenIdServiceImpl impl,
|
||||
SiteHeaderFooter header) {
|
||||
SiteHeaderFooter header,
|
||||
Provider<OAuthSessionOverOpenID> oauthSessionProvider,
|
||||
Provider<CurrentUser> currentUserProvider,
|
||||
DynamicMap<OAuthServiceProvider> oauthServiceProviders) {
|
||||
this.urlProvider = urlProvider;
|
||||
this.impl = impl;
|
||||
this.header = header;
|
||||
this.maxRedirectUrlLength = config.getInt(
|
||||
"openid", "maxRedirectUrlLength",
|
||||
10);
|
||||
this.oauthSessionProvider = oauthSessionProvider;
|
||||
this.currentUserProvider = currentUserProvider;
|
||||
this.oauthServiceProviders = oauthServiceProviders;
|
||||
|
||||
if (urlProvider == null || Strings.isNullOrEmpty(urlProvider.get())) {
|
||||
log.error("gerrit.canonicalWebUrl must be set in gerrit.config");
|
||||
@ -152,7 +164,23 @@ class LoginForm extends HttpServlet {
|
||||
mode = SignInMode.SIGN_IN;
|
||||
}
|
||||
|
||||
discover(req, res, link, id, remember, token, mode);
|
||||
OAuthServiceProvider oauthProvider = lookupOAuthServiceProvider(id);
|
||||
|
||||
if (oauthProvider == null) {
|
||||
discover(req, res, link, id, remember, token, mode);
|
||||
} else {
|
||||
OAuthSessionOverOpenID oauthSession = oauthSessionProvider.get();
|
||||
if (!currentUserProvider.get().isIdentifiedUser()
|
||||
&& oauthSession.isLoggedIn()) {
|
||||
oauthSession.logout();
|
||||
}
|
||||
if ((isGerritLogin(req)
|
||||
|| oauthSession.isOAuthFinal(req))
|
||||
&& !oauthSession.isLoggedIn()) {
|
||||
oauthSession.setServiceProvider(oauthProvider);
|
||||
oauthSession.login(req, res, oauthProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void discover(HttpServletRequest req, HttpServletResponse res,
|
||||
@ -266,6 +294,20 @@ class LoginForm extends HttpServlet {
|
||||
}
|
||||
a.setAttribute("href", u.toString());
|
||||
}
|
||||
|
||||
// OAuth: Add plugin based providers
|
||||
Element providers = HtmlDomUtil.find(doc, "providers");
|
||||
Set<String> plugins = oauthServiceProviders.plugins();
|
||||
for (String pluginName : plugins) {
|
||||
Map<String, Provider<OAuthServiceProvider>> m =
|
||||
oauthServiceProviders.byPlugin(pluginName);
|
||||
for (Map.Entry<String, Provider<OAuthServiceProvider>> e
|
||||
: m.entrySet()) {
|
||||
addProvider(providers, pluginName, e.getKey(),
|
||||
e.getValue().get().getName());
|
||||
}
|
||||
}
|
||||
|
||||
sendHtml(res, doc);
|
||||
}
|
||||
|
||||
@ -284,6 +326,38 @@ class LoginForm extends HttpServlet {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addProvider(Element form, String pluginName,
|
||||
String id, String serviceName) {
|
||||
Element div = form.getOwnerDocument().createElement("div");
|
||||
div.setAttribute("id", id);
|
||||
Element hyperlink = form.getOwnerDocument().createElement("a");
|
||||
hyperlink.setAttribute("href", String.format("?id=%s_%s",
|
||||
pluginName, id));
|
||||
hyperlink.setTextContent(serviceName +
|
||||
" (" + pluginName + " plugin)");
|
||||
div.appendChild(hyperlink);
|
||||
form.appendChild(div);
|
||||
}
|
||||
|
||||
private OAuthServiceProvider lookupOAuthServiceProvider(String providerId) {
|
||||
if (providerId.startsWith("http://")) {
|
||||
providerId = providerId.substring("http://".length());
|
||||
}
|
||||
Set<String> plugins = oauthServiceProviders.plugins();
|
||||
for (String pluginName : plugins) {
|
||||
Map<String, Provider<OAuthServiceProvider>> m =
|
||||
oauthServiceProviders.byPlugin(pluginName);
|
||||
for (Map.Entry<String, Provider<OAuthServiceProvider>> e
|
||||
: m.entrySet()) {
|
||||
if (providerId.equals(
|
||||
String.format("%s_%s", pluginName, e.getKey()))) {
|
||||
return e.getValue().get();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getLastId(HttpServletRequest req) {
|
||||
Cookie[] cookies = req.getCookies();
|
||||
if (cookies != null) {
|
||||
@ -295,4 +369,9 @@ class LoginForm extends HttpServlet {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isGerritLogin(HttpServletRequest request) {
|
||||
return request.getRequestURI().indexOf(
|
||||
OAuthSessionOverOpenID.GERRIT_LOGIN) >= 0;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2015 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.google.gerrit.httpd.auth.openid;
|
||||
|
||||
import com.google.gerrit.audit.AuditService;
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.extensions.registration.DynamicItem;
|
||||
import com.google.gerrit.httpd.HttpLogoutServlet;
|
||||
import com.google.gerrit.httpd.WebSession;
|
||||
import com.google.gerrit.server.account.AccountManager;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@Singleton
|
||||
class OAuthOverOpenIDLogoutServlet extends HttpLogoutServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Provider<OAuthSessionOverOpenID> oauthSession;
|
||||
|
||||
@Inject
|
||||
OAuthOverOpenIDLogoutServlet(AuthConfig authConfig,
|
||||
DynamicItem<WebSession> webSession,
|
||||
AccountManager accountManager,
|
||||
@CanonicalWebUrl @Nullable Provider<String> urlProvider,
|
||||
AuditService audit,
|
||||
Provider<OAuthSessionOverOpenID> oauthSession) {
|
||||
super(authConfig, webSession, urlProvider, accountManager, audit);
|
||||
this.oauthSession = oauthSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLogout(HttpServletRequest req, HttpServletResponse rsp)
|
||||
throws IOException {
|
||||
super.doLogout(req, rsp);
|
||||
oauthSession.get().logout();
|
||||
}
|
||||
}
|
@ -0,0 +1,216 @@
|
||||
// Copyright (C) 2015 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.google.gerrit.httpd.auth.openid;
|
||||
|
||||
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier;
|
||||
import com.google.gerrit.extensions.registration.DynamicItem;
|
||||
import com.google.gerrit.extensions.restapi.Url;
|
||||
import com.google.gerrit.httpd.CanonicalWebUrl;
|
||||
import com.google.gerrit.httpd.LoginUrlToken;
|
||||
import com.google.gerrit.httpd.WebSession;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.server.account.AccountException;
|
||||
import com.google.gerrit.server.account.AccountManager;
|
||||
import com.google.gerrit.server.account.AuthResult;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.servlet.SessionScoped;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/** OAuth protocol implementation */
|
||||
@SessionScoped
|
||||
class OAuthSessionOverOpenID {
|
||||
static final String GERRIT_LOGIN = "/login";
|
||||
private static final Logger log = LoggerFactory.getLogger(
|
||||
OAuthSessionOverOpenID.class);
|
||||
private static final SecureRandom randomState = newRandomGenerator();
|
||||
private final String state;
|
||||
private final DynamicItem<WebSession> webSession;
|
||||
private final AccountManager accountManager;
|
||||
private final CanonicalWebUrl urlProvider;
|
||||
private OAuthServiceProvider serviceProvider;
|
||||
private OAuthToken token;
|
||||
private OAuthUserInfo user;
|
||||
private String redirectToken;
|
||||
|
||||
@Inject
|
||||
OAuthSessionOverOpenID(DynamicItem<WebSession> webSession,
|
||||
AccountManager accountManager,
|
||||
CanonicalWebUrl urlProvider) {
|
||||
this.state = generateRandomState();
|
||||
this.webSession = webSession;
|
||||
this.accountManager = accountManager;
|
||||
this.urlProvider = urlProvider;
|
||||
}
|
||||
|
||||
boolean isLoggedIn() {
|
||||
return token != null && user != null;
|
||||
}
|
||||
|
||||
boolean isOAuthFinal(HttpServletRequest request) {
|
||||
return Strings.emptyToNull(request.getParameter("code")) != null;
|
||||
}
|
||||
|
||||
boolean login(HttpServletRequest request, HttpServletResponse response,
|
||||
OAuthServiceProvider oauth) throws IOException {
|
||||
if (isLoggedIn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
log.debug("Login " + this);
|
||||
|
||||
if (isOAuthFinal(request)) {
|
||||
if (!checkState(request)) {
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
log.debug("Login-Retrieve-User " + this);
|
||||
token = oauth.getAccessToken(new OAuthVerifier(request.getParameter("code")));
|
||||
|
||||
user = oauth.getUserInfo(token);
|
||||
|
||||
if (isLoggedIn()) {
|
||||
log.debug("Login-SUCCESS " + this);
|
||||
authenticateAndRedirect(request, response);
|
||||
return true;
|
||||
} else {
|
||||
response.sendError(SC_UNAUTHORIZED);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
log.debug("Login-PHASE1 " + this);
|
||||
redirectToken = LoginUrlToken.getToken(request);
|
||||
response.sendRedirect(oauth.getAuthorizationUrl() +
|
||||
"&state=" + state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void authenticateAndRedirect(HttpServletRequest req,
|
||||
HttpServletResponse rsp) throws IOException {
|
||||
com.google.gerrit.server.account.AuthRequest areq =
|
||||
new com.google.gerrit.server.account.AuthRequest(user.getExternalId());
|
||||
AuthResult arsp = null;
|
||||
try {
|
||||
String claimedIdentifier = user.getClaimedIdentity();
|
||||
Account.Id actualId = accountManager.lookup(user.getExternalId());
|
||||
if (!Strings.isNullOrEmpty(claimedIdentifier)) {
|
||||
Account.Id claimedId = accountManager.lookup(claimedIdentifier);
|
||||
if (claimedId != null && actualId != null) {
|
||||
if (claimedId.equals(actualId)) {
|
||||
// Both link to the same account, that's what we expected.
|
||||
} else {
|
||||
// This is (for now) a fatal error. There are two records
|
||||
// for what might be the same user.
|
||||
//
|
||||
log.error("OAuth accounts disagree over user identity:\n"
|
||||
+ " Claimed ID: " + claimedId + " is " + claimedIdentifier
|
||||
+ "\n" + " Delgate ID: " + actualId + " is "
|
||||
+ user.getExternalId());
|
||||
rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
} else if (claimedId != null && actualId == null) {
|
||||
// Claimed account already exists: link to it.
|
||||
//
|
||||
try {
|
||||
accountManager.link(claimedId, areq);
|
||||
} catch (OrmException e) {
|
||||
log.error("Cannot link: " + user.getExternalId()
|
||||
+ " to user identity:\n"
|
||||
+ " Claimed ID: " + claimedId + " is " + claimedIdentifier);
|
||||
rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
areq.setUserName(user.getUserName());
|
||||
areq.setEmailAddress(user.getEmailAddress());
|
||||
areq.setDisplayName(user.getDisplayName());
|
||||
arsp = accountManager.authenticate(areq);
|
||||
} catch (AccountException e) {
|
||||
log.error("Unable to authenticate user \"" + user + "\"", e);
|
||||
rsp.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
return;
|
||||
}
|
||||
|
||||
webSession.get().login(arsp, true);
|
||||
StringBuilder rdr = new StringBuilder(urlProvider.get(req));
|
||||
rdr.append(Url.decode(redirectToken));
|
||||
rsp.sendRedirect(rdr.toString());
|
||||
}
|
||||
|
||||
void logout() {
|
||||
token = null;
|
||||
user = null;
|
||||
redirectToken = null;
|
||||
serviceProvider = null;
|
||||
}
|
||||
|
||||
private boolean checkState(ServletRequest request) {
|
||||
String s = Strings.nullToEmpty(request.getParameter("state"));
|
||||
if (!s.equals(state)) {
|
||||
log.error("Illegal request state '" + s + "' on OAuthProtocol " + this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static SecureRandom newRandomGenerator() {
|
||||
try {
|
||||
return SecureRandom.getInstance("SHA1PRNG");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException(
|
||||
"No SecureRandom available for GitHub authentication", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String generateRandomState() {
|
||||
byte[] state = new byte[32];
|
||||
randomState.nextBytes(state);
|
||||
return Base64.encodeBase64URLSafeString(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OAuthSession [token=" + token + ", user=" + user + "]";
|
||||
}
|
||||
|
||||
public void setServiceProvider(OAuthServiceProvider provider) {
|
||||
this.serviceProvider = provider;
|
||||
}
|
||||
|
||||
public OAuthServiceProvider getServiceProvider() {
|
||||
return serviceProvider;
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
// Copyright (C) 2015 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.google.gerrit.httpd.auth.openid;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
|
||||
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.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
/** OAuth web filter uses active OAuth session to perform OAuth requests */
|
||||
@Singleton
|
||||
class OAuthWebFilterOverOpenID implements Filter {
|
||||
static final String GERRIT_LOGIN = "/login";
|
||||
|
||||
private final Provider<CurrentUser> currentUserProvider;
|
||||
private final Provider<OAuthSessionOverOpenID> oauthSessionProvider;
|
||||
private final DynamicMap<OAuthServiceProvider> oauthServiceProviders;
|
||||
private OAuthServiceProvider ssoProvider;
|
||||
|
||||
@Inject
|
||||
OAuthWebFilterOverOpenID(Provider<CurrentUser> currentUserProvider,
|
||||
DynamicMap<OAuthServiceProvider> oauthServiceProviders,
|
||||
Provider<OAuthSessionOverOpenID> oauthSessionProvider) {
|
||||
this.currentUserProvider = currentUserProvider;
|
||||
this.oauthServiceProviders = oauthServiceProviders;
|
||||
this.oauthSessionProvider = oauthSessionProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
pickSSOServiceProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpSession httpSession = ((HttpServletRequest) request).getSession(false);
|
||||
if (currentUserProvider.get().isIdentifiedUser()) {
|
||||
if (httpSession != null) {
|
||||
httpSession.invalidate();
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
|
||||
OAuthSessionOverOpenID oauthSession = oauthSessionProvider.get();
|
||||
OAuthServiceProvider service = ssoProvider == null
|
||||
? oauthSession.getServiceProvider()
|
||||
: ssoProvider;
|
||||
|
||||
if ((isGerritLogin(httpRequest)
|
||||
|| oauthSession.isOAuthFinal(httpRequest))
|
||||
&& !oauthSession.isLoggedIn()) {
|
||||
if (service == null) {
|
||||
throw new IllegalStateException("service is unknown");
|
||||
}
|
||||
oauthSession.setServiceProvider(service);
|
||||
oauthSession.login(httpRequest, httpResponse, service);
|
||||
} else {
|
||||
chain.doFilter(httpRequest, response);
|
||||
}
|
||||
}
|
||||
|
||||
private void pickSSOServiceProvider()
|
||||
throws ServletException {
|
||||
SortedSet<String> plugins = oauthServiceProviders.plugins();
|
||||
if (plugins.size() == 1) {
|
||||
SortedMap<String, Provider<OAuthServiceProvider>> services =
|
||||
oauthServiceProviders.byPlugin(Iterables.getOnlyElement(plugins));
|
||||
if (services.size() == 1) {
|
||||
ssoProvider = Iterables.getOnlyElement(services.values()).get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGerritLogin(HttpServletRequest request) {
|
||||
return request.getRequestURI().indexOf(GERRIT_LOGIN) >= 0;
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@
|
||||
|
||||
package com.google.gerrit.httpd.auth.openid;
|
||||
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
|
||||
/** Servlets related to OpenID authentication. */
|
||||
@ -21,9 +23,12 @@ public class OpenIdModule extends ServletModule {
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
serve("/login", "/login/*").with(LoginForm.class);
|
||||
serve("/logout").with(OAuthOverOpenIDLogoutServlet.class);
|
||||
filter("/oauth").through(OAuthWebFilterOverOpenID.class);
|
||||
serve("/" + OpenIdServiceImpl.RETURN_URL).with(OpenIdLoginServlet.class);
|
||||
serve("/" + XrdsServlet.LOCATION).with(XrdsServlet.class);
|
||||
filter("/").through(XrdsFilter.class);
|
||||
bind(OpenIdServiceImpl.class);
|
||||
DynamicMap.mapOf(binder(), OAuthServiceProvider.class);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user