Merge branch 'stable-2.6'

* stable-2.6:
  Allow logging in at /login
  Remove login dialogs and replace with /login/ URLs

Change-Id: Id51c94f8bcdfa8927c568d06a5fd0d07a743d1cc
This commit is contained in:
Dave Borowitz
2013-03-28 14:04:10 -04:00
50 changed files with 716 additions and 1592 deletions

View File

@@ -1,30 +0,0 @@
// 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.common.auth.openid;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.AllowCrossSiteRequest;
import com.google.gwtjsonrpc.common.RemoteJsonService;
import com.google.gwtjsonrpc.common.RpcImpl;
import com.google.gwtjsonrpc.common.RpcImpl.Version;
@RpcImpl(version = Version.V2_0)
public interface OpenIdService extends RemoteJsonService {
@AllowCrossSiteRequest
void discover(String openidIdentifier, SignInMode mode,
boolean remember, String returnToken,
AsyncCallback<DiscoveryResult> callback);
}

View File

@@ -1,53 +0,0 @@
// 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.common.auth.userpass;
import com.google.gerrit.reviewdb.client.AuthType;
public class LoginResult {
public boolean success;
public boolean isNew;
protected AuthType authType;
protected Error error;
protected LoginResult() {
}
public LoginResult(final AuthType authType) {
this.authType = authType;
}
public AuthType getAuthType() {
return authType;
}
public void setError(final Error error) {
this.error = error;
success = error == null;
}
public Error getError() {
return error;
}
public static enum Error {
/** Username or password are invalid */
INVALID_LOGIN,
/** The authentication server is unavailable or the query to it timed out */
AUTHENTICATION_UNAVAILABLE
}
}

View File

@@ -1,30 +0,0 @@
// 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.common.auth.userpass;
import com.google.gerrit.common.audit.Audit;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtjsonrpc.common.AllowCrossSiteRequest;
import com.google.gwtjsonrpc.common.RemoteJsonService;
import com.google.gwtjsonrpc.common.RpcImpl;
import com.google.gwtjsonrpc.common.RpcImpl.Version;
@RpcImpl(version = Version.V2_0)
public interface UserPassAuthService extends RemoteJsonService {
@Audit(action = "sign in", obfuscate={1})
@AllowCrossSiteRequest
void authenticate(String username, String password,
AsyncCallback<LoginResult> callback);
}

View File

@@ -14,7 +14,6 @@
package com.google.gerrit.common.data;
import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Account.FieldName;
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
@@ -31,8 +30,6 @@ public class GerritConfig implements Cloneable {
protected String registerText;
protected String httpPasswordUrl;
protected String reportBugUrl;
protected String openIdSsoUrl;
protected List<OpenIdProviderPattern> allowedOpenIDs;
protected GitwebConfig gitweb;
protected boolean useContributorAgreements;
@@ -93,22 +90,6 @@ public class GerritConfig implements Cloneable {
httpPasswordUrl = url;
}
public String getOpenIdSsoUrl() {
return openIdSsoUrl;
}
public void setOpenIdSsoUrl(final String u) {
openIdSsoUrl = u;
}
public List<OpenIdProviderPattern> getAllowedOpenIDs() {
return allowedOpenIDs;
}
public void setAllowedOpenIDs(List<OpenIdProviderPattern> l) {
allowedOpenIDs = l;
}
public AuthType getAuthType() {
return authType;
}

View File

@@ -60,8 +60,6 @@ import com.google.gerrit.client.admin.ProjectDashboardsScreen;
import com.google.gerrit.client.admin.ProjectInfoScreen;
import com.google.gerrit.client.admin.ProjectListScreen;
import com.google.gerrit.client.admin.ProjectScreen;
import com.google.gerrit.client.auth.openid.OpenIdSignInDialog;
import com.google.gerrit.client.auth.userpass.UserPassSignInDialog;
import com.google.gerrit.client.changes.AccountDashboardScreen;
import com.google.gerrit.client.changes.ChangeScreen;
import com.google.gerrit.client.changes.CustomDashboardScreen;
@@ -78,7 +76,6 @@ import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
@@ -633,32 +630,6 @@ public class Dispatcher {
if (matchPrefix("/VE/", token) || matchPrefix("VE,", token))
return new ValidateEmailScreen(skip(token));
if (matchPrefix("/SignInFailure,", token)) {
final String[] args = skip(token).split(",");
final SignInMode mode = SignInMode.valueOf(args[0]);
final String msg = KeyUtil.decode(args[1]);
final String to = MINE;
switch (Gerrit.getConfig().getAuthType()) {
case OPENID:
new OpenIdSignInDialog(mode, to, msg).center();
break;
case LDAP:
case LDAP_BIND:
new UserPassSignInDialog(to, msg).center();
break;
default:
return null;
}
switch (mode) {
case SIGN_IN:
return QueryScreen.forQuery("status:open");
case LINK_IDENTIY:
return new MyIdentitiesScreen();
case REGISTER:
break;
}
}
if (matchExact(SETTINGS_NEW_AGREEMENT, token))
return new NewAgreementScreen();

View File

@@ -15,14 +15,11 @@
package com.google.gerrit.client;
import static com.google.gerrit.common.data.GlobalCapability.ADMINISTRATE_SERVER;
import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
import static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
import com.google.gerrit.client.account.AccountCapabilities;
import com.google.gerrit.client.admin.ProjectScreen;
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;
import com.google.gerrit.client.patches.PatchScreen;
@@ -35,7 +32,6 @@ import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.client.ui.ScreenLoadEvent;
import com.google.gerrit.common.ClientVersion;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.GitwebConfig;
import com.google.gerrit.common.data.HostPageData;
@@ -71,9 +67,9 @@ import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
@@ -273,34 +269,7 @@ public class Gerrit implements EntryPoint {
/** Sign the user into the application. */
public static void doSignIn(String token) {
switch (myConfig.getAuthType()) {
case HTTP:
case HTTP_LDAP:
case CLIENT_SSL_CERT_LDAP:
case CUSTOM_EXTENSION:
Location.assign(loginRedirect(token));
break;
case DEVELOPMENT_BECOME_ANY_ACCOUNT:
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;
case LDAP:
case LDAP_BIND:
new UserPassSignInDialog(token, null).center();
break;
}
Location.assign(loginRedirect(token));
}
public static String loginRedirect(String token) {
@@ -726,8 +695,11 @@ public class Gerrit implements EntryPoint {
case OPENID:
menuRight.addItem(C.menuRegister(), new Command() {
public void execute() {
final String to = History.getToken();
new OpenIdSignInDialog(SignInMode.REGISTER, to, null).center();
String t = History.getToken();
if (t == null) {
t = "";
}
doSignIn(PageLinks.REGISTER + t);
}
});
menuRight.addItem(C.menuSignIn(), new Command() {
@@ -760,7 +732,7 @@ public class Gerrit implements EntryPoint {
break;
case DEVELOPMENT_BECOME_ANY_ACCOUNT:
menuRight.add(anchor("Become", selfRedirect("/become")));
menuRight.add(anchor("Become", loginRedirect("")));
break;
}
}

View File

@@ -1,57 +0,0 @@
// Copyright (C) 2008 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;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.user.client.AutoCenterDialogBox;
/** Prompts the user to sign in to their account. */
public abstract class SignInDialog extends AutoCenterDialogBox {
protected final SignInMode mode;
protected final String token;
/**
* Create a new dialog to handle user sign in.
*
* @param signInMode type of mode the login will perform.
* @param token the token to jump to after sign-in is complete.
*/
protected SignInDialog(final SignInMode signInMode, final String token) {
super(/* auto hide */true, /* modal */true);
setGlassEnabled(true);
this.mode = signInMode;
this.token = token;
switch (signInMode) {
case LINK_IDENTIY:
setText(Gerrit.C.linkIdentityDialogTitle());
break;
case REGISTER:
setText(Gerrit.C.registerDialogTitle());
break;
default:
setText(Gerrit.C.signInDialogTitle());
break;
}
}
@Override
public void show() {
super.show();
GlobalKey.dialog(this);
}
}

View File

@@ -15,19 +15,19 @@
package com.google.gerrit.client.account;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.auth.openid.OpenIdSignInDialog;
import com.google.gerrit.client.auth.openid.OpenIdUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
@@ -59,29 +59,15 @@ public class MyIdentitiesScreen extends SettingsScreen {
});
add(deleteIdentity);
switch (Gerrit.getConfig().getAuthType()) {
case OPENID: {
final Button linkIdentity = new Button(Util.C.buttonLinkIdentity());
linkIdentity.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
final String to = History.getToken();
new OpenIdSignInDialog(SignInMode.LINK_IDENTIY, to, null).center();
}
});
add(linkIdentity);
break;
}
case CLIENT_SSL_CERT_LDAP:
case CUSTOM_EXTENSION:
case DEVELOPMENT_BECOME_ANY_ACCOUNT:
case HTTP:
case HTTP_LDAP:
case LDAP:
case LDAP_BIND:
case OPENID_SSO:
break;
if (Gerrit.getConfig().getAuthType() == AuthType.OPENID) {
Button linkIdentity = new Button(Util.C.buttonLinkIdentity());
linkIdentity.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
Location.assign(Gerrit.loginRedirect(History.getToken()) + "?link");
}
});
add(linkIdentity);
}
}

View File

@@ -17,18 +17,6 @@ package com.google.gerrit.client.auth.openid;
import com.google.gwt.i18n.client.Constants;
public interface OpenIdConstants extends Constants {
String buttonSignIn();
String buttonRegister();
String buttonLinkId();
String rememberMe();
String notAllowed();
String noProvider();
String error();
String nameGoogle();
String nameYahoo();
String whatIsOpenIDHtml();
}

View File

@@ -1,20 +1,2 @@
buttonSignIn = Sign In
buttonRegister = Register
buttonLinkId = Link Identity
rememberMe = Remember Me
notAllowed = Provider is not allowed.
noProvider = Provider is not supported, or was incorrectly entered.
error = Unable to connect with OpenID provider.
nameGoogle = Google Account
nameYahoo = Yahoo! ID
whatIsOpenIDHtml = \
<h2 class="smallHeading" style="margin-top: 25px;">What is OpenID?</h2>\
<p>OpenID provides secure single-sign-on, without \
revealing your passwords to this website.</p>\
<p>There are many OpenID providers available. You may already \
be member of one!</p>\
<p><a href="http://openid.net/get/" target="_blank">Get OpenID</a></p>\

View File

@@ -1,27 +0,0 @@
// 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.gwt.i18n.client.Messages;
public interface OpenIdMessages extends Messages {
String signInAt(String hostname);
String registerAt(String hostname);
String linkAt(String hostname);
String signInWith(String who);
String registerWith(String who);
String linkWith(String who);
}

View File

@@ -1,7 +0,0 @@
signInAt = Sign In to Gerrit Code Review at {0}
registerAt = Register with Gerrit Code Review at {0}
linkAt = Link Another Identity to Gerrit Code Review at {0}
signInWith = Sign in with a {0}
registerWith = Register with a {0}
linkWith = Link a {0}

View File

@@ -1,39 +0,0 @@
// 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.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.DataResource;
import com.google.gwt.resources.client.ImageResource;
interface OpenIdResources extends ClientBundle {
static final OpenIdResources I = GWT.create(OpenIdResources.class);
@Source("openid.css")
OpenIdCss css();
@Source("identifierBackground.gif")
DataResource identifierBackground();
@Source("openidLogo.png")
ImageResource openidLogo();
@Source("iconGoogle.gif")
ImageResource iconGoogle();
@Source("iconYahoo.gif")
ImageResource iconYahoo();
}

View File

@@ -1,388 +0,0 @@
// 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.SignInDialog;
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.OpenIdProviderPattern;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import java.util.Map;
public class OpenIdSignInDialog extends SignInDialog implements
FormPanel.SubmitHandler {
static {
OpenIdResources.I.css().ensureInjected();
}
private final FlowPanel panelWidget;
private final FormPanel form;
private final FlowPanel formBody;
private final FormPanel redirectForm;
private final FlowPanel redirectBody;
private FlowPanel errorLine;
private InlineLabel errorMsg;
private Button login;
private NpTextBox providerId;
private CheckBox rememberId;
private boolean discovering;
public OpenIdSignInDialog(final SignInMode requestedMode, final String token,
final String initialErrorMsg) {
super(requestedMode, token);
formBody = new FlowPanel();
formBody.setStyleName(OpenIdResources.I.css().loginForm());
form = new FormPanel();
form.setMethod(FormPanel.METHOD_GET);
form.addSubmitHandler(this);
form.add(formBody);
redirectBody = new FlowPanel();
redirectBody.setVisible(false);
redirectForm = new FormPanel();
redirectForm.add(redirectBody);
panelWidget = new FlowPanel();
panelWidget.add(form);
panelWidget.add(redirectForm);
add(panelWidget);
createHeaderLogo();
createHeaderText();
createErrorBox();
createIdentBox();
link(OpenIdUrls.URL_GOOGLE, OpenIdUtil.C.nameGoogle(), OpenIdResources.I
.iconGoogle());
link(OpenIdUrls.URL_YAHOO, OpenIdUtil.C.nameYahoo(), OpenIdResources.I
.iconYahoo());
if (initialErrorMsg != null) {
showError(initialErrorMsg);
}
formBody.add(new HTML(OpenIdUtil.C.whatIsOpenIDHtml()));
}
@Override
public void show() {
super.show();
providerId.selectAll();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
providerId.setFocus(true);
}
});
}
private void createHeaderLogo() {
final FlowPanel headerLogo = new FlowPanel();
headerLogo.setStyleName(OpenIdResources.I.css().logo());
headerLogo.add(new Image(OpenIdResources.I.openidLogo()));
formBody.add(headerLogo);
}
private void createHeaderText() {
final FlowPanel headerText = new FlowPanel();
final String me = Window.Location.getHostName();
final SmallHeading headerLabel = new SmallHeading();
switch (mode) {
case LINK_IDENTIY:
headerLabel.setText(OpenIdUtil.M.linkAt(me));
break;
case REGISTER:
headerLabel.setText(OpenIdUtil.M.registerAt(me));
break;
case SIGN_IN:
default:
headerLabel.setText(OpenIdUtil.M.signInAt(me));
break;
}
headerText.add(headerLabel);
formBody.add(headerText);
}
private void createErrorBox() {
errorLine = new FlowPanel();
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
errorLine.setStyleName(OpenIdResources.I.css().error());
errorMsg = new InlineLabel();
errorLine.add(errorMsg);
formBody.add(errorLine);
}
private void showError(final String msgText) {
errorMsg.setText(msgText);
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "");
}
private void hideError() {
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
}
private void createIdentBox() {
boolean remember = mode == SignInMode.SIGN_IN || mode == SignInMode.REGISTER;
final FlowPanel group = new FlowPanel();
group.setStyleName(OpenIdResources.I.css().loginLine());
final FlowPanel line1 = new FlowPanel();
group.add(line1);
providerId = new NpTextBox();
providerId.setVisibleLength(60);
providerId.setStyleName(OpenIdResources.I.css().identifier());
providerId.setTabIndex(0);
providerId.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
event.preventDefault();
form.submit();
}
}
});
line1.add(providerId);
login = new Button();
switch (mode) {
case LINK_IDENTIY:
login.setText(OpenIdUtil.C.buttonLinkId());
break;
case REGISTER:
login.setText(OpenIdUtil.C.buttonRegister());
break;
case SIGN_IN:
default:
login.setText(OpenIdUtil.C.buttonSignIn());
break;
}
login.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
form.submit();
}
});
login.setTabIndex(remember ? 2 : 1);
line1.add(login);
Button close = new Button(Gerrit.C.signInDialogClose());
close.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
hide();
}
});
close.setTabIndex(remember ? 3 : 2);
line1.add(close);
if (remember) {
rememberId = new CheckBox(OpenIdUtil.C.rememberMe());
rememberId.setTabIndex(1);
group.add(rememberId);
String last = Cookies.getCookie(OpenIdUrls.LASTID_COOKIE);
if (last != null && !"".equals(last)) {
if (last.startsWith("\"") && last.endsWith("\"")) {
// Dequote the value. We shouldn't have to do this, but
// something is causing some Google Account tokens to get
// wrapped up in double quotes when obtained from the cookie.
//
last = last.substring(1, last.length() - 2);
}
providerId.setText(last);
rememberId.setValue(true);
}
}
formBody.add(group);
}
private void link(final String identUrl, final String who,
final ImageResource icon) {
if (!isAllowedProvider(identUrl)) {
return;
}
final ClickHandler i = new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
event.preventDefault();
if (!discovering) {
providerId.setText(identUrl);
form.submit();
}
}
};
final FlowPanel line = new FlowPanel();
line.addStyleName(OpenIdResources.I.css().directLink());
final Image img = new Image(icon);
img.addClickHandler(i);
line.add(img);
final Anchor text = new Anchor();
switch (mode) {
case LINK_IDENTIY:
text.setText(OpenIdUtil.M.linkWith(who));
break;
case REGISTER:
text.setText(OpenIdUtil.M.registerWith(who));
break;
case SIGN_IN:
default:
text.setText(OpenIdUtil.M.signInWith(who));
break;
}
text.setHref(identUrl);
text.addClickHandler(i);
line.add(text);
formBody.add(line);
}
private static boolean isAllowedProvider(final String identUrl) {
for (OpenIdProviderPattern p : Gerrit.getConfig().getAllowedOpenIDs()) {
if (p.matches(identUrl)) {
return true;
}
}
return false;
}
private void enable(final boolean on) {
providerId.setEnabled(on);
login.setEnabled(on);
}
private void onDiscovery(final DiscoveryResult result) {
discovering = false;
switch (result.status) {
case VALID:
// The provider won't support operation inside an IFRAME,
// so we replace our entire application.
//
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;
case NOT_ALLOWED:
showError(OpenIdUtil.C.notAllowed());
enableRetryDiscovery();
break;
case NO_PROVIDER:
showError(OpenIdUtil.C.noProvider());
enableRetryDiscovery();
break;
case ERROR:
default:
showError(OpenIdUtil.C.error());
enableRetryDiscovery();
break;
}
}
private void enableRetryDiscovery() {
enable(true);
providerId.selectAll();
providerId.setFocus(true);
}
@Override
public void onSubmit(final SubmitEvent event) {
event.cancel();
String openidIdentifier = providerId.getText();
if (openidIdentifier == null || openidIdentifier.equals("")) {
enable(true);
return;
}
if (!openidIdentifier.startsWith("http://")
&& !openidIdentifier.startsWith("https://")) {
openidIdentifier = "http://" + openidIdentifier;
}
if (!isAllowedProvider(openidIdentifier)) {
showError(OpenIdUtil.C.notAllowed());
enableRetryDiscovery();
return;
}
discovering = true;
enable(false);
hideError();
final boolean remember = rememberId != null && rememberId.getValue();
OpenIdUtil.SVC.discover(openidIdentifier, mode, remember, token,
new GerritCallback<DiscoveryResult>() {
public void onSuccess(final DiscoveryResult result) {
onDiscovery(result);
}
@Override
public void onFailure(final Throwable caught) {
super.onFailure(caught);
enableRetryDiscovery();
}
});
}
public void onSubmitComplete(final FormSubmitCompleteEvent event) {
}
}

View File

@@ -1,72 +0,0 @@
// 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.common.auth.SignInMode;
import com.google.gerrit.common.auth.openid.DiscoveryResult;
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);
}
});
}
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;
case ERROR:
case NO_PROVIDER:
case NOT_ALLOWED:
break;
}
}
}

View File

@@ -14,19 +14,12 @@
package com.google.gerrit.client.auth.openid;
import com.google.gerrit.common.auth.openid.OpenIdService;
import com.google.gwt.core.client.GWT;
import com.google.gwtjsonrpc.client.JsonUtil;
public class OpenIdUtil {
public static final OpenIdConstants C;
public static final OpenIdMessages M;
public static final OpenIdService SVC;
static {
C = GWT.create(OpenIdConstants.class);
M = GWT.create(OpenIdMessages.class);
SVC = GWT.create(OpenIdService.class);
JsonUtil.bind(SVC, "rpc/OpenIdService");
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 B

View File

@@ -1,69 +0,0 @@
/* 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.
*/
@external .gwt-Button;
@url identifierBackground identifierBackground;
.loginForm {
margin-left: 10px;
margin-right: 10px;
}
.logo {
text-align: right;
}
.loginLine {
margin-bottom: 10px;
}
.loginLine div {
white-space: nowrap;
}
.loginLine .gwt-Button {
margin-left: 2px;
}
.identifier {
background: #ffffff identifierBackground no-repeat scroll 5px 50%;
padding-left: 25px;
border: 1px solid #999999;
}
.directLink {
vertical-align: middle;
margin-right: 5px;
color: blue;
cursor: pointer;
}
.directLink:hover {
text-decoration: underline;
}
.directLink img {
margin-right: 3px;
border: 0 none;
}
.error {
padding-top: 5px;
padding-bottom: 5px;
}
.error span {
padding-top: 4px;
padding-bottom: 4px;
padding-left: 10px;
padding-right: 10px;
background: #fff1a8;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,26 +0,0 @@
// 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.userpass;
import com.google.gwt.i18n.client.Constants;
public interface UserPassConstants extends Constants {
String buttonSignIn();
String username();
String password();
String invalidLogin();
String usernameRequired();
String passwordRequired();
}

View File

@@ -1,6 +0,0 @@
buttonSignIn = Sign In
username = Username
password = Password
invalidLogin = Incorrect username or password.
usernameRequired = Please enter a username.
passwordRequired = Please enter a password.

View File

@@ -1,22 +0,0 @@
// 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.userpass;
import com.google.gwt.resources.client.CssResource;
public interface UserPassCss extends CssResource {
String loginForm();
String error();
}

View File

@@ -1,23 +0,0 @@
// 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.userpass;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gwt.i18n.client.Messages;
public interface UserPassMessages extends Messages {
String signInAt(String hostname);
String authenticationUnavailable(AuthType authType);
}

View File

@@ -1,2 +0,0 @@
signInAt = Sign In to Gerrit Code Review at {0}
authenticationUnavailable = {0} authentication unavailable

View File

@@ -1,25 +0,0 @@
// 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.userpass;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
interface UserPassResources extends ClientBundle {
static final UserPassResources I = GWT.create(UserPassResources.class);
@Source("userpass.css")
UserPassCss css();
}

View File

@@ -1,240 +0,0 @@
// 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.userpass;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.SignInDialog;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.auth.userpass.LoginResult;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.NpTextBox;
public class UserPassSignInDialog extends SignInDialog {
static {
UserPassResources.I.css().ensureInjected();
}
private final FlowPanel formBody;
private FlowPanel errorLine;
private InlineLabel errorMsg;
private Button login;
private Button close;
private TextBox username;
private TextBox password;
public UserPassSignInDialog(final String token, final String initialErrorMsg) {
super(SignInMode.SIGN_IN, token);
setAutoHideEnabled(false);
formBody = new FlowPanel();
formBody.setStyleName(UserPassResources.I.css().loginForm());
add(formBody);
createHeaderText();
createErrorBox();
createUsernameBox();
if (initialErrorMsg != null) {
showError(initialErrorMsg);
}
}
@Override
public void show() {
super.show();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
username.setFocus(true);
}
});
}
private void createHeaderText() {
final FlowPanel headerText = new FlowPanel();
final SmallHeading headerLabel = new SmallHeading();
headerLabel.setText(Util.M.signInAt(Location.getHostName()));
headerText.add(headerLabel);
formBody.add(headerText);
}
private void createErrorBox() {
errorLine = new FlowPanel();
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
errorLine.setStyleName(UserPassResources.I.css().error());
errorMsg = new InlineLabel();
errorLine.add(errorMsg);
formBody.add(errorLine);
}
private void showError(final String msgText) {
errorMsg.setText(msgText);
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "");
}
private void hideError() {
DOM.setStyleAttribute(errorLine.getElement(), "visibility", "hidden");
}
private void createUsernameBox() {
username = new NpTextBox();
username.setVisibleLength(25);
username.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
event.preventDefault();
password.selectAll();
password.setFocus(true);
}
}
});
password = new PasswordTextBox();
password.setVisibleLength(25);
password.addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
password.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
event.preventDefault();
onLogin();
}
}
});
final FlowPanel buttons = new FlowPanel();
buttons.setStyleName(Gerrit.RESOURCES.css().errorDialogButtons());
login = new Button();
login.setText(Util.C.buttonSignIn());
login.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
onLogin();
}
});
buttons.add(login);
close = new Button();
DOM.setStyleAttribute(close.getElement(), "marginLeft", "45px");
close.setText(Gerrit.C.signInDialogClose());
close.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
hide();
}
});
buttons.add(close);
final Grid formGrid = new Grid(3, 2);
formGrid.setText(0, 0, Util.C.username());
formGrid.setText(1, 0, Util.C.password());
formGrid.setWidget(0, 1, username);
formGrid.setWidget(1, 1, password);
formGrid.setWidget(2, 1, buttons);
formBody.add(formGrid);
username.setTabIndex(1);
password.setTabIndex(2);
login.setTabIndex(3);
close.setTabIndex(4);
}
private void enable(final boolean on) {
username.setEnabled(on);
password.setEnabled(on);
login.setEnabled(on);
}
private void onLogin() {
hideError();
final String user = username.getText();
if (user == null || user.equals("")) {
showError(Util.C.usernameRequired());
username.setFocus(true);
return;
}
final String pass = password.getText();
if (pass == null || pass.equals("")) {
showError(Util.C.passwordRequired());
password.setFocus(true);
return;
}
enable(false);
Util.SVC.authenticate(user, pass, new GerritCallback<LoginResult>() {
public void onSuccess(final LoginResult result) {
if (result.success) {
String to = token;
if (!to.startsWith("/")) {
to = "/" + to;
}
if (result.isNew && !token.startsWith(PageLinks.REGISTER + "/")) {
to = PageLinks.REGISTER + to;
}
Location.replace(Location.getPath() + "login" + to);
} else {
final String message;
switch (result.getError()) {
case AUTHENTICATION_UNAVAILABLE:
message = Util.M.authenticationUnavailable(result.getAuthType());
break;
case INVALID_LOGIN:
default:
message = Util.C.invalidLogin();
}
showError(message);
enable(true);
password.selectAll();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
password.setFocus(true);
}
});
}
}
@Override
public void onFailure(final Throwable caught) {
super.onFailure(caught);
enable(true);
}
});
}
}

View File

@@ -1,30 +0,0 @@
// 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.userpass;
import com.google.gerrit.common.auth.userpass.UserPassAuthService;
import com.google.gwt.core.client.GWT;
import com.google.gwtjsonrpc.client.JsonUtil;
public class Util {
public static final UserPassConstants C = GWT.create(UserPassConstants.class);
public static final UserPassMessages M = GWT.create(UserPassMessages.class);
public static final UserPassAuthService SVC;
static {
SVC = GWT.create(UserPassAuthService.class);
JsonUtil.bind(SVC, "rpc/UserPassAuthService");
}
}

View File

@@ -1,32 +0,0 @@
/* 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.
*/
.loginForm {
margin-left: 10px;
margin-right: 10px;
}
.error {
padding-top: 5px;
padding-bottom: 5px;
}
.error span {
padding-top: 4px;
padding-bottom: 4px;
padding-left: 10px;
padding-right: 10px;
background: #fff1a8;
}

View File

@@ -83,14 +83,6 @@ class GerritConfigProvider implements Provider<GerritConfig> {
private GerritConfig create() throws MalformedURLException {
final GerritConfig config = new GerritConfig();
switch (authConfig.getAuthType()) {
case OPENID:
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"));
@@ -109,6 +101,8 @@ class GerritConfigProvider implements Provider<GerritConfig> {
case DEVELOPMENT_BECOME_ANY_ACCOUNT:
case HTTP:
case HTTP_LDAP:
case OPENID:
case OPENID_SSO:
break;
}
config.setUseContributorAgreements(cfg.getBoolean("auth",

View File

@@ -20,7 +20,7 @@ import static com.google.inject.Scopes.SINGLETON;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.webui.WebUiPlugin;
import com.google.gerrit.httpd.auth.become.BecomeAnyAccountLoginServlet;
import com.google.gerrit.httpd.auth.become.BecomeAnyAccountModule;
import com.google.gerrit.httpd.auth.container.HttpAuthModule;
import com.google.gerrit.httpd.auth.container.HttpsClientSslCertModule;
import com.google.gerrit.httpd.auth.ldap.LdapAuthModule;
@@ -45,7 +45,6 @@ import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.ProvisionException;
import com.google.inject.servlet.RequestScoped;
import com.google.inject.servlet.ServletModule;
import java.net.SocketAddress;
@@ -103,12 +102,7 @@ public class WebModule extends FactoryModule {
break;
case DEVELOPMENT_BECOME_ANY_ACCOUNT:
install(new ServletModule() {
@Override
protected void configureServlets() {
serve("/become").with(BecomeAnyAccountLoginServlet.class);
}
});
install(new BecomeAnyAccountModule());
break;
case OPENID:

View File

@@ -16,6 +16,8 @@ package com.google.gerrit.httpd.auth.become;
import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.httpd.WebSession;
@@ -52,7 +54,7 @@ import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
@Singleton
public class BecomeAnyAccountLoginServlet extends HttpServlet {
class BecomeAnyAccountLoginServlet extends HttpServlet {
private static final boolean IS_DEV = Boolean.getBoolean("Gerrit.GwtDevMode");
private final SchemaFactory<ReviewDb> schema;
@@ -114,7 +116,9 @@ public class BecomeAnyAccountLoginServlet extends HttpServlet {
if (res != null) {
webSession.get().login(res, false);
final StringBuilder rdr = new StringBuilder();
rdr.append(req.getContextPath());
rdr.append(Objects.firstNonNull(
Strings.emptyToNull(req.getContextPath()),
"/"));
if (IS_DEV && req.getParameter("gwt.codesvr") != null) {
if (rdr.indexOf("?") < 0) {
rdr.append("?");

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2009 The Android Open Source Project
// 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.
@@ -12,15 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.client.auth.openid;
package com.google.gerrit.httpd.auth.become;
import com.google.gwt.resources.client.CssResource;
import com.google.inject.servlet.ServletModule;
interface OpenIdCss extends CssResource {
String loginForm();
String logo();
String loginLine();
String identifier();
String directLink();
String error();
public class BecomeAnyAccountModule extends ServletModule {
@Override
protected void configureServlets() {
serve("/login", "/login/*").with(BecomeAnyAccountLoginServlet.class);
}
}

View File

@@ -21,6 +21,6 @@ public class HttpAuthModule extends ServletModule {
@Override
protected void configureServlets() {
filter("/").through(HttpAuthFilter.class);
serve("/login/*").with(HttpLoginServlet.class);
serve("/login", "/login/*").with(HttpLoginServlet.class);
}
}

View File

@@ -21,6 +21,6 @@ public class HttpsClientSslCertModule extends ServletModule {
@Override
protected void configureServlets() {
filter("/").through(HttpsClientSslCertAuthFilter.class);
serve("/login/*").with(HttpsClientSslCertLoginServlet.class);
serve("/login", "/login/*").with(HttpsClientSslCertLoginServlet.class);
}
}

View File

@@ -14,20 +14,12 @@
package com.google.gerrit.httpd.auth.ldap;
import com.google.gerrit.httpd.rpc.RpcServletModule;
import com.google.gerrit.httpd.rpc.UiRpcModule;
import com.google.inject.servlet.ServletModule;
/** RPC support related to username/password LDAP authentication. */
/** Configure username/password LDAP authentication. */
public class LdapAuthModule extends ServletModule {
@Override
protected void configureServlets() {
serve("/login/*").with(LoginRedirectServlet.class);
install(new RpcServletModule(UiRpcModule.PREFIX) {
@Override
protected void configureServlets() {
rpc(UserPassAuthServiceImpl.class);
}
});
serve("/login", "/login/*").with(LdapLoginServlet.class);
}
}

View File

@@ -0,0 +1,166 @@
// 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.httpd.auth.ldap;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountUserNameException;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.auth.AuthenticationUnavailableException;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.IOException;
import javax.annotation.Nullable;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Handles username/password based authentication against the directory. */
@SuppressWarnings("serial")
@Singleton
class LdapLoginServlet extends HttpServlet {
private static final Logger log = LoggerFactory
.getLogger(LdapLoginServlet.class);
private final AccountManager accountManager;
private final Provider<WebSession> webSession;
private final Provider<String> urlProvider;
@Inject
LdapLoginServlet(AccountManager accountManager,
Provider<WebSession> webSession,
@CanonicalWebUrl @Nullable Provider<String> urlProvider) {
this.accountManager = accountManager;
this.webSession = webSession;
this.urlProvider = urlProvider;
if (Strings.isNullOrEmpty(urlProvider.get())) {
log.error("gerrit.canonicalWebUrl must be set in gerrit.config");
}
}
private void sendForm(HttpServletRequest req, HttpServletResponse res,
@Nullable String errorMessage) throws IOException {
String self = req.getRequestURI();
String cancel = Objects.firstNonNull(urlProvider.get(), "/");
String token = getToken(req);
if (!token.equals("/")) {
cancel += "#" + token;
}
Document doc =
HtmlDomUtil.parseFile(LdapLoginServlet.class, "LoginForm.html");
HtmlDomUtil.find(doc, "hostName").setTextContent(req.getServerName());
HtmlDomUtil.find(doc, "login_form").setAttribute("action", self);
HtmlDomUtil.find(doc, "cancel_link").setAttribute("href", cancel);
Element emsg = HtmlDomUtil.find(doc, "error_message");
if (Strings.isNullOrEmpty(errorMessage)) {
emsg.getParentNode().removeChild(emsg);
} else {
emsg.setTextContent(errorMessage);
}
byte[] bin = HtmlDomUtil.toUTF8(doc);
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
res.setContentType("text/html");
res.setCharacterEncoding("UTF-8");
res.setContentLength(bin.length);
ServletOutputStream out = res.getOutputStream();
try {
out.write(bin);
} finally {
out.close();
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
sendForm(req, res, null);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String username = Strings.nullToEmpty(req.getParameter("username")).trim();
String password = Strings.nullToEmpty(req.getParameter("password"));
String remember = Strings.nullToEmpty(req.getParameter("rememberme"));
if (username.isEmpty() || password.isEmpty()) {
sendForm(req, res, "Invalid username or password.");
return;
}
AuthRequest areq = AuthRequest.forUser(username);
areq.setPassword(password);
AuthResult ares;
try {
ares = accountManager.authenticate(areq);
} catch (AccountUserNameException e) {
sendForm(req, res, e.getMessage());
return;
} catch (AuthenticationUnavailableException e) {
sendForm(req, res, "Authentication unavailable at this time.");
return;
} catch (AccountException e) {
log.info(String.format("'%s' failed to sign in: %s", username, e.getMessage()));
sendForm(req, res, "Invalid username or password.");
return;
} catch (RuntimeException e) {
log.error("LDAP authentication failed", e);
sendForm(req, res, "Authentication unavailable at this time.");
return;
}
String token = getToken(req);
StringBuilder dest = new StringBuilder();
dest.append(urlProvider.get());
dest.append('#');
dest.append(token);
CacheHeaders.setNotCacheable(res);
webSession.get().login(ares, "1".equals(remember));
res.sendRedirect(dest.toString());
}
private static String getToken(final HttpServletRequest req) {
String token = req.getPathInfo();
if (token == null || token.isEmpty()) {
token = PageLinks.MINE;
} else if (!token.startsWith("/")) {
token = "/" + token;
}
return token;
}
}

View File

@@ -1,84 +0,0 @@
// 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.httpd.auth.ldap;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet bound to {@code /login/*} to redirect after user/pass sign-in.
* <p>
* This servlet is required because user authentication is done over RPC, but if
* the RPC is successful we need to force the host page to fully reload to pick
* up the account information, as we don't support updating the UI on the fly
* after a sign-in.
*/
@Singleton
class LoginRedirectServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private final Provider<WebSession> webSession;
private final Provider<String> urlProvider;
@Inject
LoginRedirectServlet(final Provider<WebSession> webSession,
@CanonicalWebUrl @Nullable final Provider<String> urlProvider) {
this.webSession = webSession;
this.urlProvider = urlProvider;
}
@Override
protected void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
final String token;
if (webSession.get().isSignedIn()) {
token = getToken(req);
} else {
final String msg = "Session cookie not available.";
token = "/SignInFailure," + SignInMode.SIGN_IN + "," + msg;
}
final StringBuilder rdr = new StringBuilder();
rdr.append(urlProvider.get());
rdr.append('#');
rdr.append(token);
CacheHeaders.setNotCacheable(rsp);
rsp.sendRedirect(rdr.toString());
}
private String getToken(final HttpServletRequest req) {
String token = req.getPathInfo();
if (token == null || token.isEmpty()) {
token = PageLinks.MINE;
} else if (!token.startsWith("/")) {
token = "/" + token;
}
return token;
}
}

View File

@@ -1,92 +0,0 @@
// 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.httpd.auth.ldap;
import com.google.gerrit.common.auth.userpass.LoginResult;
import com.google.gerrit.common.auth.userpass.UserPassAuthService;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AccountUserNameException;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.AuthResult;
import com.google.gerrit.server.auth.AuthenticationUnavailableException;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class UserPassAuthServiceImpl implements UserPassAuthService {
private final Provider<WebSession> webSession;
private final AccountManager accountManager;
private final AuthType authType;
private static final Logger log = LoggerFactory
.getLogger(UserPassAuthServiceImpl.class);
@Inject
UserPassAuthServiceImpl(final Provider<WebSession> webSession,
final AccountManager accountManager, final AuthConfig authConfig) {
this.webSession = webSession;
this.accountManager = accountManager;
this.authType = authConfig.getAuthType();
}
@Override
public void authenticate(String username, final String password,
final AsyncCallback<LoginResult> callback) {
LoginResult result = new LoginResult(authType);
if (username == null || "".equals(username.trim()) //
|| password == null || "".equals(password)) {
result.setError(LoginResult.Error.INVALID_LOGIN);
callback.onSuccess(result);
return;
}
username = username.trim();
final AuthRequest req = AuthRequest.forUser(username);
req.setPassword(password);
final AuthResult res;
try {
res = accountManager.authenticate(req);
} catch (AccountUserNameException e) {
// entered user name and password were correct, but user name could not be
// set for the newly created account and this is why the login fails,
// error screen with error message should be shown to the user
callback.onFailure(e);
return;
} catch (AuthenticationUnavailableException e) {
result.setError(LoginResult.Error.AUTHENTICATION_UNAVAILABLE);
callback.onSuccess(result);
return;
} catch (AccountException e) {
log.info(String.format("'%s' failed to sign in: %s", username, e.getMessage()));
result.setError(LoginResult.Error.INVALID_LOGIN);
callback.onSuccess(result);
return;
}
result.success = true;
result.isNew = res.isNew();
webSession.get().login(res, true /* persistent cookie */);
callback.onSuccess(result);
}
}

View File

@@ -0,0 +1,75 @@
<html>
<head>
<title>Gerrit Code Review - Sign In</title>
<style>
#error_message {
padding: 5px;
margin: 2em;
width: 20em;
background-color: rgb(255, 255, 116);
font-weight: bold;
}
#cancel_link {
margin-left: 45px;
}
</style>
</head>
<body>
<h1>Sign In to Gerrit Code Review at <span id="hostName">example.com</span></h1>
<div id="error_message">Invalid username or password.</div>
<form method="POST" action="#" id="login_form">
<table style="border: 0;">
<tr>
<th>Username</th>
<td><input name="username" id="f_user"
type="text"
size="25"
tabindex="1" /></td>
</tr>
<tr>
<th>Password</th>
<td><input name="password" id="f_pass"
type="password"
size="25"
tabindex="2" /></td>
</tr>
<tr>
<td></td>
<td>
<input name="rememberme" id="f_remember"
type="checkbox"
value="1"
tabindex="3" />
<label for="f_remember">Remember me</label>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Sign In" tabindex="4"/>
<a href="../" id="cancel_link">Cancel</a>
</td>
</tr>
</table>
</form>
<script type="text/javascript" language="javascript">
var login_form = document.getElementById('login_form');
var f_user = document.getElementById('f_user');
var f_pass = document.getElementById('f_pass');
f_user.onkeydown = function(e) {
if (e.keyCode == 13) {
f_pass.focus();
return false;
}
}
f_pass.onkeydown = function(e) {
if (e.keyCode == 13) {
login_form.submit();
return false;
}
}
f_user.focus();
</script>
</body>
</html>

View File

@@ -12,18 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.common.auth.openid;
package com.google.gerrit.httpd.auth.openid;
import java.util.Map;
public final class DiscoveryResult {
public static enum Status {
final class DiscoveryResult {
static enum Status {
/** Provider was discovered and {@code providerUrl} is valid. */
VALID,
/** The identifier is not allowed to be used, by site configuration. */
NOT_ALLOWED,
/** Identifier isn't for an OpenID provider. */
NO_PROVIDER,
@@ -31,20 +28,20 @@ public final class DiscoveryResult {
ERROR;
}
public Status status;
public String providerUrl;
public Map<String, String> providerArgs;
Status status;
String providerUrl;
Map<String, String> providerArgs;
protected DiscoveryResult() {
DiscoveryResult() {
}
public DiscoveryResult(final String redirect, final Map<String, String> args) {
DiscoveryResult(String redirect, Map<String, String> args) {
status = Status.VALID;
providerUrl = redirect;
providerArgs = args;
}
public DiscoveryResult(final Status s) {
DiscoveryResult(Status s) {
status = s;
}
}

View File

@@ -0,0 +1,306 @@
// 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.httpd.auth.openid;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.httpd.HtmlDomUtil;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Handles OpenID based login flow. */
@SuppressWarnings("serial")
@Singleton
class LoginForm extends HttpServlet {
private static final Logger log = LoggerFactory.getLogger(LoginForm.class);
private static final ImmutableMap<String, String> ALL_PROVIDERS = ImmutableMap.of(
"google", OpenIdUrls.URL_GOOGLE,
"yahoo", OpenIdUrls.URL_YAHOO);
private final ImmutableSet<String> suggestProviders;
private final Provider<String> urlProvider;
private final OpenIdServiceImpl impl;
private final int maxRedirectUrlLength;
private final String ssoUrl;
@Inject
LoginForm(
@CanonicalWebUrl @Nullable Provider<String> urlProvider,
@GerritServerConfig Config config,
AuthConfig authConfig,
OpenIdServiceImpl impl) {
this.urlProvider = urlProvider;
this.impl = impl;
this.maxRedirectUrlLength = config.getInt(
"openid", "maxRedirectUrlLength",
10);
if (Strings.isNullOrEmpty(urlProvider.get())) {
log.error("gerrit.canonicalWebUrl must be set in gerrit.config");
}
if (authConfig.getAuthType() == AuthType.OPENID_SSO) {
suggestProviders = ImmutableSet.of();
ssoUrl = authConfig.getOpenIdSsoUrl();
} else {
Set<String> providers = Sets.newHashSet();
for (Map.Entry<String, String> e : ALL_PROVIDERS.entrySet()) {
if (impl.isAllowedOpenID(e.getValue())) {
providers.add(e.getKey());
}
}
suggestProviders = ImmutableSet.copyOf(providers);
ssoUrl = null;
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException {
if (ssoUrl != null) {
String token = getToken(req);
SignInMode mode;
if (PageLinks.REGISTER.equals(token)) {
mode = SignInMode.REGISTER;
token = PageLinks.MINE;
} else {
mode = SignInMode.SIGN_IN;
}
discover(req, res, false, ssoUrl, false, token, mode);
} else {
String id = Strings.nullToEmpty(req.getParameter("id")).trim();
if (!id.isEmpty()) {
doPost(req, res);
} else {
boolean link = req.getParameter("link") != null;
sendForm(req, res, link, null);
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException {
boolean link = req.getParameter("link") != null;
String id = Strings.nullToEmpty(req.getParameter("id")).trim();
if (id.isEmpty()) {
sendForm(req, res, link, null);
return;
}
if (!id.startsWith("http://") && !id.startsWith("https://")) {
id = "http://" + id;
}
if ((ssoUrl != null && !ssoUrl.equals(id)) || !impl.isAllowedOpenID(id)) {
sendForm(req, res, link, "OpenID provider not permitted by site policy.");
return;
}
boolean remember = "1".equals(req.getParameter("rememberme"));
String token = getToken(req);
SignInMode mode;
if (link) {
mode = SignInMode.LINK_IDENTIY;
} else if (PageLinks.REGISTER.equals(token)) {
mode = SignInMode.REGISTER;
token = PageLinks.MINE;
} else {
mode = SignInMode.SIGN_IN;
}
discover(req, res, link, id, remember, token, mode);
}
private void discover(HttpServletRequest req, HttpServletResponse res,
boolean link, String id, boolean remember, String token, SignInMode mode)
throws IOException {
if (ssoUrl != null) {
remember = false;
}
DiscoveryResult r = impl.discover(id, mode, remember, token);
switch (r.status) {
case VALID:
redirect(r, res);
break;
case NO_PROVIDER:
sendForm(req, res, link,
"Provider is not supported, or was incorrectly entered.");
break;
case ERROR:
sendForm(req, res, link, "Unable to connect with OpenID provider.");
break;
}
}
private void redirect(DiscoveryResult r, HttpServletResponse res)
throws IOException {
StringBuilder url = new StringBuilder();
url.append(r.providerUrl);
if (r.providerArgs != null && !r.providerArgs.isEmpty()) {
boolean first = true;
for(Map.Entry<String, String> arg : r.providerArgs.entrySet()) {
if (first) {
url.append('?');
first = false;
} else {
url.append('&');
}
url.append(Url.encode(arg.getKey()))
.append('=')
.append(Url.encode(arg.getValue()));
}
}
if (url.length() <= maxRedirectUrlLength) {
res.sendRedirect(url.toString());
return;
}
Document doc = HtmlDomUtil.parseFile(LoginForm.class, "RedirectForm.html");
Element form = HtmlDomUtil.find(doc, "redirect_form");
form.setAttribute("action", r.providerUrl);
if (r.providerArgs != null && !r.providerArgs.isEmpty()) {
for (Map.Entry<String, String> arg : r.providerArgs.entrySet()) {
Element in = doc.createElement("input");
in.setAttribute("type", "hidden");
in.setAttribute("name", arg.getKey());
in.setAttribute("value", arg.getValue());
form.appendChild(in);
}
}
sendHtml(res, doc);
}
private static String getToken(HttpServletRequest req) {
String token = req.getPathInfo();
if (token == null || token.isEmpty()) {
token = PageLinks.MINE;
} else if (!token.startsWith("/")) {
token = "/" + token;
}
return token;
}
private void sendForm(HttpServletRequest req, HttpServletResponse res,
boolean link, @Nullable String errorMessage) throws IOException {
String self = req.getRequestURI();
String cancel = Objects.firstNonNull(urlProvider.get(), "/");
String token = getToken(req);
if (!token.equals("/")) {
cancel += "#" + token;
}
Document doc = HtmlDomUtil.parseFile(LoginForm.class, "LoginForm.html");
HtmlDomUtil.find(doc, "hostName").setTextContent(req.getServerName());
HtmlDomUtil.find(doc, "login_form").setAttribute("action", self);
HtmlDomUtil.find(doc, "cancel_link").setAttribute("href", cancel);
if (!link || ssoUrl != null) {
Element input = HtmlDomUtil.find(doc, "f_link");
input.getParentNode().removeChild(input);
}
String last = getLastId(req);
if (last != null) {
HtmlDomUtil.find(doc, "f_openid").setAttribute("value", last);
}
Element emsg = HtmlDomUtil.find(doc, "error_message");
if (Strings.isNullOrEmpty(errorMessage)) {
emsg.getParentNode().removeChild(emsg);
} else {
emsg.setTextContent(errorMessage);
}
for (String name : ALL_PROVIDERS.keySet()) {
Element div = HtmlDomUtil.find(doc, "provider_" + name);
if (div == null) {
continue;
}
if (!suggestProviders.contains(name)) {
div.getParentNode().removeChild(div);
continue;
}
Element a = HtmlDomUtil.find(div, "id_" + name);
if (a == null) {
div.getParentNode().removeChild(div);
continue;
}
StringBuilder u = new StringBuilder();
u.append(self).append(a.getAttribute("href"));
if (link) {
u.append("&link");
}
a.setAttribute("href", u.toString());
}
sendHtml(res, doc);
}
private void sendHtml(HttpServletResponse res, Document doc)
throws IOException {
byte[] bin = HtmlDomUtil.toUTF8(doc);
res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
res.setContentType("text/html");
res.setCharacterEncoding("UTF-8");
res.setContentLength(bin.length);
ServletOutputStream out = res.getOutputStream();
try {
out.write(bin);
} finally {
out.close();
}
}
private static String getLastId(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if (OpenIdUrls.LASTID_COOKIE.equals(c.getName())) {
return c.getValue();
}
}
}
return null;
}
}

View File

@@ -14,22 +14,16 @@
package com.google.gerrit.httpd.auth.openid;
import com.google.gerrit.httpd.rpc.RpcServletModule;
import com.google.inject.servlet.ServletModule;
/** Servlets and RPC support related to OpenID authentication. */
/** Servlets related to OpenID authentication. */
public class OpenIdModule extends ServletModule {
@Override
protected void configureServlets() {
serve("/login", "/login/*").with(LoginForm.class);
serve("/" + OpenIdServiceImpl.RETURN_URL).with(OpenIdLoginServlet.class);
serve("/" + XrdsServlet.LOCATION).with(XrdsServlet.class);
filter("/").through(XrdsFilter.class);
install(new RpcServletModule(RpcServletModule.PREFIX) {
@Override
protected void configureServlets() {
rpc(OpenIdServiceImpl.class);
}
});
bind(OpenIdServiceImpl.class);
}
}

View File

@@ -15,10 +15,6 @@
package com.google.gerrit.httpd.auth.openid;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.auth.openid.DiscoveryResult;
import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.common.auth.openid.OpenIdService;
import com.google.gerrit.common.auth.openid.OpenIdUrls;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.reviewdb.client.Account;
@@ -26,11 +22,11 @@ import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.UrlEncoded;
import com.google.gerrit.server.account.AccountException;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gwtjsonrpc.common.AsyncCallback;
import com.google.gwtorm.client.KeyUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -73,7 +69,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Singleton
class OpenIdServiceImpl implements OpenIdService {
class OpenIdServiceImpl {
private static final Logger log =
LoggerFactory.getLogger(OpenIdServiceImpl.class);
@@ -149,19 +145,12 @@ class OpenIdServiceImpl implements OpenIdService {
}
@SuppressWarnings("unchecked")
public void discover(final String openidIdentifier, final SignInMode mode,
final boolean remember, final String returnToken,
final AsyncCallback<DiscoveryResult> cb) {
if (!isAllowedOpenID(openidIdentifier)) {
cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NOT_ALLOWED));
return;
}
DiscoveryResult discover(final String openidIdentifier, final SignInMode mode,
final boolean remember, final String returnToken) {
final State state;
state = init(openidIdentifier, mode, remember, returnToken);
if (state == null) {
cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.NO_PROVIDER));
return;
return new DiscoveryResult(DiscoveryResult.Status.NO_PROVIDER);
}
final AuthRequest aReq;
@@ -189,16 +178,15 @@ class OpenIdServiceImpl implements OpenIdService {
}
} catch (MessageException e) {
log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
return;
return new DiscoveryResult(DiscoveryResult.Status.ERROR);
} catch (ConsumerException e) {
log.error("Cannot create OpenID redirect for " + openidIdentifier, e);
cb.onSuccess(new DiscoveryResult(DiscoveryResult.Status.ERROR));
return;
return new DiscoveryResult(DiscoveryResult.Status.ERROR);
}
cb.onSuccess(new DiscoveryResult(aReq.getDestinationUrl(false), //
aReq.getParameterMap()));
return new DiscoveryResult(
aReq.getDestinationUrl(false),
aReq.getParameterMap());
}
private boolean requestRegistration(final AuthRequest aReq) {
@@ -209,7 +197,6 @@ class OpenIdServiceImpl implements OpenIdService {
// registration information, in case the identity is new to us.
//
return true;
}
// We might already have this account on file. Look for it.
@@ -222,7 +209,7 @@ class OpenIdServiceImpl implements OpenIdService {
}
}
/** Called by {@link OpenIdLoginServlet} doGet, doPost */
/** Called by {@link OpenIdLoginForm} doGet, doPost */
void doAuth(final HttpServletRequest req, final HttpServletResponse rsp)
throws Exception {
if (OMODE_CANCEL.equals(req.getParameter(OPENID_MODE))) {
@@ -436,7 +423,7 @@ class OpenIdServiceImpl implements OpenIdService {
arsp = accountManager.authenticate(areq);
final Cookie lastId = new Cookie(OpenIdUrls.LASTID_COOKIE, "");
lastId.setPath(req.getContextPath() + "/");
lastId.setPath(req.getContextPath() + "/login/");
if (remember) {
lastId.setValue(rediscoverIdentifier);
lastId.setMaxAge(LASTID_AGE);
@@ -559,7 +546,7 @@ class OpenIdServiceImpl implements OpenIdService {
return new State(discovered, retTo, contextUrl);
}
private boolean isAllowedOpenID(final String id) {
boolean isAllowedOpenID(final String id) {
for (final OpenIdProviderPattern pattern : allowedOpenIDs) {
if (pattern.matches(id)) {
return true;

View File

@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.common.auth;
package com.google.gerrit.httpd.auth.openid;
public enum SignInMode {
enum SignInMode {
SIGN_IN, LINK_IDENTIY, REGISTER;
}

View File

@@ -0,0 +1,82 @@
<html>
<head>
<title>Gerrit Code Review - Sign In</title>
<style>
#error_message {
padding: 5px;
margin-left: 5px;
margin-bottom: 5px;
width: 20em;
background-color: rgb(255, 255, 116);
font-weight: bold;
}
#cancel_link {
margin-left: 45px;
}
#logo_box {
padding-left: 160px;
}
#logo_img {
width: 200px;
height: 80px;
background: url('data:image/png;base64,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') no-repeat 0px 0px;
}
#f_openid {
padding-left: 25px;
border: 1px solid #999;
background: #fff url('data:image/gif;base64,R0lGODlhEAAQAMQAAO3t7eHh4srKyvz8/P5pDP9rENLS0v/28P/17tXV1dHEvPDw8M3Nzfn5+d3d3f5jA97Syvnv6MfLzcfHx/1mCPx4Kc/S1Pf189C+tP+xgv/k1N3OxfHy9NLV1/39/f///yH5BAAAAAAALAAAAAAQABAAAAVq4CeOZGme6KhlSDoexdO6H0IUR+otwUYRkMDCUwIYJhLFTyGZJACAwQcgEAQ4kVuEE2AIGAOPQQAQwXCfS8KQGAwMjIYIUSi03B7iJ+AcnmclHg4TAh0QDzIpCw4WGBUZeikDFzk0lpcjIQA7') no-repeat scroll 5px 50%
}
</style>
</head>
<body>
<h1>Sign In to Gerrit Code Review at <span id="hostName">example.com</span></h1>
<form method="POST" action="#" id="login_form">
<input type="hidden" name="link" id="f_link" value="1" />
<div id="logo_box"><div id="logo_img"></div></div>
<div id="error_message">Invalid OpenID identifier.</div>
<div>
<input type="text"
name="id"
id="f_openid"
size="60"
tabindex="1" />
</div>
<div>
<input name="rememberme" id="f_remember"
type="checkbox"
value="1"
tabindex="2" />
<label for="f_remember">Remember me</label>
</div>
<div style="margin-bottom: 25px;">
<input type="submit" value="Sign In" id="f_submit" tabindex="3" />
<a href="../" id="cancel_link">Cancel</a>
</div>
<div id="provider_google">
<img height="16" width="16" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABsUlEQVR42rWSy0sbYRRH88fYhW5KQXThIkUQN6ISJFBBW6FFBN2UqlC78LVKFlHIoqWGakF8gUZ8gajVzKSKZpQmAWtK0pBmhkxmSgPuiuaYmRKhSEwU/ODyDZfzO8ydOxbLQx1NB0H4y8FBlmMpy9LyOavrKUoKB4IXvBsIIopRPJ441dY/2Fr8fAtFSxO0dkRy4eA1PDp+TkVlmGhMKS5IJOFpbYgj6fQalhV4UhVm0esvLojELimv1JiYOPwPflS2gM93WNoIXZ1nPC4/IRDQzYDTqTA0PM2dtuCZ8vGmV6SvP5srL/da5c+4TnNLFlvTMYmEVrpkazuM2x1naOQ7Dc1fqLOmaayXkaSz4hLHewm7fY+Z2R0iP+JmYGpym/q6DDb76u0CwR+g9+0FHz4u3wAdLh9VNWu5UX4VlqysfaXRDoODNz+aw7nDs9ZPpNPpwgJV1WhvF6m1/qb79T6fpwXm5kVGRnd5/mIdQSzwH2iahq7/27nxiq5xLy9fbdDWsUtPzyausRVC4VMMzmAMNv9syTdkWTZLVVUymYx5J5NJs5dKpVAUxaw8Z/SM7BV+fz9Uc4yYRAAAAABJRU5ErkJggg==" />
<a href="?id=https://www.google.com/accounts/o8/id" id="id_google">Sign in with a Google Account</a>
</div>
<div id="provider_yahoo">
<img height="16" width="16" src="data:image/gif;base64,R0lGODlhEAAQAPECAAAAAP8AAP///8zMzCH5BAEAAAMALAAAAAAQABAAAAIqnI+py30BY3AgAjCkfJDjiIAQlgUkNxqWkqrm0honKk7KhZOzw/f+fygAADs=" />
<a href="?id=https://me.yahoo.com" id="id_yahoo">Sign in with a Yahoo! ID</a>
</div>
<div style="margin-top: 25px;">
<h2>What is OpenID?</h2>
<p>OpenID provides secure single-sign-on, without revealing your passwords to this website.</p>
<p>There are many OpenID providers available. You may already be member of one!</p>
<p><a href="http://openid.net/get/" target="_blank">Get OpenID</a></p>
</div>
</form>
<script type="text/javascript" language="javascript">
var f_openid = document.getElementById('f_openid');
var f_submit = document.getElementById('f_submit');
if (f_openid.value == '')
f_openid.focus();
else
f_submit.focus();
</script>
</body>
</html>

View File

@@ -0,0 +1,16 @@
<html>
<head>
<title>Gerrit Code Review - Redirecting ...</title>
</head>
<body>
<div>Redirecting ...</div>
<form method="POST" action="#" id="redirect_form">
<input type="submit" value="Continue" />
</form>
<script type="text/javascript" language="javascript">
var r = document.getElementById('redirect_form');
r.style.display = 'none';
r.submit();
</script>
</body>
</html>

View File

@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.common.auth.openid;
package com.google.gerrit.server.auth.openid;
import com.google.gerrit.reviewdb.client.AccountExternalId;

View File

@@ -14,9 +14,9 @@
package com.google.gerrit.server.config;
import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
import com.google.gerrit.reviewdb.client.AccountExternalId;
import com.google.gerrit.reviewdb.client.AuthType;
import com.google.gerrit.server.auth.openid.OpenIdProviderPattern;
import com.google.gwtjsonrpc.server.SignedToken;
import com.google.gwtjsonrpc.server.XsrfException;
import com.google.inject.Inject;