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.
This commit is contained in:
James E. Blair 2011-07-20 16:55:26 +00:00
parent bd1ee1ad12
commit 1e35b2096f
8 changed files with 132 additions and 0 deletions

View File

@ -40,6 +40,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
@ -165,6 +171,13 @@ to express their setting:
+
Default is -1, permitting infinite time between authentications.
[[auth.openIdSsoUrl]]auth.openIdSsoUrl::
+
The SSO entry point URL. Only used if `auth.type` was set to
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

View File

@ -26,6 +26,7 @@ import java.util.Set;
public class GerritConfig implements Cloneable {
protected String registerUrl;
protected String openIdSsoUrl;
protected List<OpenIdProviderPattern> allowedOpenIDs;
protected GitwebLink gitweb;
@ -50,6 +51,14 @@ public class GerritConfig implements Cloneable {
registerUrl = u;
}
public String getOpenIdSsoUrl() {
return openIdSsoUrl;
}
public void setOpenIdSsoUrl(final String u) {
openIdSsoUrl = u;
}
public List<OpenIdProviderPattern> getAllowedOpenIDs() {
return allowedOpenIDs;
}

View File

@ -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.ChangeListScreen;
import com.google.gerrit.client.rpc.GerritCallback;
@ -81,6 +82,7 @@ public class Gerrit implements EntryPoint {
private static RootPanel siteHeader;
private static RootPanel siteFooter;
private static SearchPanel searchPanel;
private static OpenIdSsoPanel singleSignOnPanel;
private static final Dispatcher dispatcher = new Dispatcher();
private static ViewSite<Screen> body;
@ -221,6 +223,10 @@ public class Gerrit implements EntryPoint {
Location.assign(Location.getPath() + "become");
break;
case OPENID_SSO:
singleSignOnPanel.authenticate(SignInMode.SIGN_IN, token);
break;
case OPENID:
new OpenIdSignInDialog(SignInMode.SIGN_IN, token, null).center();
break;
@ -359,6 +365,7 @@ public class Gerrit implements EntryPoint {
menuLeft = new TabPanel();
menuRight = new LinkMenuBar();
searchPanel = new SearchPanel();
singleSignOnPanel = new OpenIdSsoPanel();
menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
menuLine.setStyleName(RESOURCES.css().topmenu());
gTopMenu.add(menuLine);
@ -366,6 +373,7 @@ public class Gerrit implements EntryPoint {
menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
menuRightPanel.add(menuRight);
menuRightPanel.add(searchPanel);
menuRightPanel.add(singleSignOnPanel);
menuLine.setWidget(0, 0, menuLeft);
menuLine.setWidget(0, 1, new FlowPanel());
menuLine.setWidget(0, 2, menuRightPanel);
@ -509,6 +517,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:
if (cfg.getRegisterUrl() != null) {

View File

@ -0,0 +1,76 @@
// Copyright (C) 2009 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<DiscoveryResult>() {
public void onSuccess(final DiscoveryResult result) {
onDiscovery(result);
}
@Override
public void onFailure(final Throwable caught) {
super.onFailure(caught);
}
});
}
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<String, String> e : result.providerArgs.entrySet()) {
redirectBody.add(new Hidden(e.getKey(), e.getValue()));
}
FormElement.as(redirectForm.getElement()).setTarget("_top");
redirectForm.submit();
break;
}
}
}

View File

@ -88,6 +88,10 @@ class GerritConfigProvider implements Provider<GerritConfig> {
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"));

View File

@ -94,6 +94,7 @@ public class WebModule extends FactoryModule {
switch (authType) {
case OPENID:
case OPENID_SSO:
install(new OpenIdModule());
break;

View File

@ -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.
* <p>

View File

@ -37,6 +37,7 @@ public class AuthConfig {
private final AuthType authType;
private final String httpHeader;
private final String logoutUrl;
private final String openIdSsoUrl;
private final List<OpenIdProviderPattern> trustedOpenIDs;
private final List<OpenIdProviderPattern> allowedOpenIDs;
private final String cookiePath;
@ -54,6 +55,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");
@ -101,6 +103,10 @@ public class AuthConfig {
return logoutUrl;
}
public String getOpenIdSsoUrl() {
return openIdSsoUrl;
}
public String getCookiePath() {
return cookiePath;
}
@ -145,6 +151,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.
//