From ca8bc3b22a43e2b280aa26412ad717e785586565 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Wed, 21 Dec 2011 18:12:26 +0000 Subject: [PATCH] Add OpenID SSO support. Configuring OPENID_SSO in gerrit.config will allow the admin to specify an SSO entry point URL so that users clicking on "Sign In" are sent directly to that URL. Change-Id: I361b7b74a6f34a199578620540be31d1df0c5fef --- Documentation/config-gerrit.txt | 13 ++++ .../gerrit/common/data/GerritConfig.java | 9 +++ .../java/com/google/gerrit/client/Gerrit.java | 16 +++++ .../client/auth/openid/OpenIdSsoPanel.java | 70 +++++++++++++++++++ .../gerrit/httpd/GerritConfigProvider.java | 4 ++ .../com/google/gerrit/httpd/WebModule.java | 1 + .../java/com/google/gerrit/pgm/Daemon.java | 3 +- .../gerrit/reviewdb/client/AuthType.java | 3 + .../gerrit/server/config/AuthConfig.java | 10 +++ 9 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 0435f4e1e6..8c291c71cf 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -88,6 +88,12 @@ The default setting. Gerrit uses any valid OpenID provider chosen by the end-user. For more information see http://openid.net/[openid.net]. + +* `OpenID_SSO` ++ +Supports OpenID from a single provider. There is no registration +link, and the "Sign In" link sends the user directly to the provider's +SSO entry point. ++ * `HTTP` + Gerrit relies upon data presented in the HTTP request. This includes @@ -229,6 +235,13 @@ order to validate their email address expires. + Default is 12 hours. +[[auth.openIdSsoUrl]]auth.openIdSsoUrl:: ++ +The SSO entry point URL. Only used if `auth.type` was set to +OpenID_SSO. ++ +The "Sign In" link will send users directly to this URL. + [[auth.httpHeader]]auth.httpHeader:: + HTTP header to trust the username from, or unset to select HTTP basic diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java index 07a8534336..89de3b488a 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java @@ -28,6 +28,7 @@ import java.util.Set; public class GerritConfig implements Cloneable { protected String registerUrl; protected String httpPasswordUrl; + protected String openIdSsoUrl; protected List allowedOpenIDs; protected GitwebConfig gitweb; @@ -72,6 +73,14 @@ public class GerritConfig implements Cloneable { httpPasswordUrl = url; } + public String getOpenIdSsoUrl() { + return openIdSsoUrl; + } + + public void setOpenIdSsoUrl(final String u) { + openIdSsoUrl = u; + } + public List getAllowedOpenIDs() { return allowedOpenIDs; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java index 5c2a319092..091fbdcd35 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java @@ -15,6 +15,7 @@ package com.google.gerrit.client; import com.google.gerrit.client.auth.openid.OpenIdSignInDialog; +import com.google.gerrit.client.auth.openid.OpenIdSsoPanel; import com.google.gerrit.client.auth.userpass.UserPassSignInDialog; import com.google.gerrit.client.changes.ChangeConstants; import com.google.gerrit.client.changes.ChangeListScreen; @@ -255,6 +256,13 @@ public class Gerrit implements EntryPoint { Location.assign(selfRedirect("/become")); break; + case OPENID_SSO: + final RootPanel gBody = RootPanel.get("gerrit_body"); + OpenIdSsoPanel singleSignOnPanel = new OpenIdSsoPanel(); + gBody.add(singleSignOnPanel); + singleSignOnPanel.authenticate(SignInMode.SIGN_IN, token); + break; + case OPENID: new OpenIdSignInDialog(SignInMode.SIGN_IN, token, null).center(); break; @@ -617,6 +625,14 @@ public class Gerrit implements EntryPoint { }); break; + case OPENID_SSO: + menuRight.addItem(C.menuSignIn(), new Command() { + public void execute() { + doSignIn(History.getToken()); + } + }); + break; + case LDAP: case LDAP_BIND: case CUSTOM_EXTENSION: diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java new file mode 100644 index 0000000000..3dd54a71b7 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSsoPanel.java @@ -0,0 +1,70 @@ +// Copyright (C) 2012 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.client.auth.openid; + +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.ui.SmallHeading; +import com.google.gerrit.common.auth.SignInMode; +import com.google.gerrit.common.auth.openid.DiscoveryResult; +import com.google.gerrit.common.auth.openid.OpenIdUrls; +import com.google.gwt.dom.client.FormElement; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.Hidden; + +import java.util.Map; + +public class OpenIdSsoPanel extends FlowPanel { + private final FormPanel redirectForm; + private final FlowPanel redirectBody; + private final String ssoUrl; + + public OpenIdSsoPanel() { + super(); + redirectBody = new FlowPanel(); + redirectBody.setVisible(false); + redirectForm = new FormPanel(); + redirectForm.add(redirectBody); + + add(redirectForm); + + ssoUrl = Gerrit.getConfig().getOpenIdSsoUrl(); + } + + public void authenticate(SignInMode requestedMode, final String token) { + OpenIdUtil.SVC.discover(ssoUrl, requestedMode, /* remember */ false, token, + new GerritCallback() { + public void onSuccess(final DiscoveryResult result) { + onDiscovery(result); + } + }); + } + + private void onDiscovery(final DiscoveryResult result) { + switch (result.status) { + case VALID: + redirectForm.setMethod(FormPanel.METHOD_POST); + redirectForm.setAction(result.providerUrl); + redirectBody.clear(); + for (final Map.Entry e : result.providerArgs.entrySet()) { + redirectBody.add(new Hidden(e.getKey(), e.getValue())); + } + FormElement.as(redirectForm.getElement()).setTarget("_top"); + redirectForm.submit(); + break; + } + } +} diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java index f92f13d1c0..72bb0c2f63 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java @@ -90,6 +90,10 @@ class GerritConfigProvider implements Provider { config.setAllowedOpenIDs(authConfig.getAllowedOpenIDs()); break; + case OPENID_SSO: + config.setOpenIdSsoUrl(authConfig.getOpenIdSsoUrl()); + break; + case LDAP: case LDAP_BIND: config.setRegisterUrl(cfg.getString("auth", null, "registerurl")); diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java index 0d14b796d7..1a48bb5841 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java @@ -108,6 +108,7 @@ public class WebModule extends FactoryModule { break; case OPENID: + case OPENID_SSO: // OpenID support is bound in WebAppInitializer and Daemon. case CUSTOM_EXTENSION: break; diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java index 282bbc9fe9..02b0a1d3f3 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Daemon.java @@ -367,7 +367,8 @@ public class Daemon extends SiteProgram { } AuthConfig authConfig = cfgInjector.getInstance(AuthConfig.class); - if (authConfig.getAuthType() == AuthType.OPENID) { + if (authConfig.getAuthType() == AuthType.OPENID || + authConfig.getAuthType() == AuthType.OPENID_SSO) { modules.add(new OpenIdModule()); } modules.add(sysInjector.getInstance(GetUserFilter.Module.class)); diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java index 962426b65a..b615fc574f 100644 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java +++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AuthType.java @@ -18,6 +18,9 @@ public enum AuthType { /** Login relies upon the OpenID standard: {@link "http://openid.net/"} */ OPENID, + /** Login relies upon the OpenID standard: {@link "http://openid.net/"} in Single Sign On mode */ + OPENID_SSO, + /** * Login relies upon the container/web server security. *

diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java index a0f0d365c1..a37fde0115 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/AuthConfig.java @@ -37,6 +37,7 @@ public class AuthConfig { private final String httpHeader; private final boolean trustContainerAuth; private final String logoutUrl; + private final String openIdSsoUrl; private final List trustedOpenIDs; private final List allowedOpenIDs; private final String cookiePath; @@ -51,6 +52,7 @@ public class AuthConfig { authType = toType(cfg); httpHeader = cfg.getString("auth", null, "httpheader"); logoutUrl = cfg.getString("auth", null, "logouturl"); + openIdSsoUrl = cfg.getString("auth", null, "openidssourl"); trustedOpenIDs = toPatterns(cfg, "trustedOpenID"); allowedOpenIDs = toPatterns(cfg, "allowedOpenID"); cookiePath = cfg.getString("auth", null, "cookiepath"); @@ -106,6 +108,10 @@ public class AuthConfig { return logoutUrl; } + public String getOpenIdSsoUrl() { + return openIdSsoUrl; + } + public String getCookiePath() { return cookiePath; } @@ -146,6 +152,10 @@ public class AuthConfig { // return true; + case OPENID_SSO: + // There's only one provider in SSO mode, so it must be okay. + return true; + case OPENID: // All identities must be trusted in order to trust the account. //