Index: xwiki-core/pom.xml
===================================================================
--- xwiki-core/pom.xml (revision 11817)
+++ xwiki-core/pom.xml (working copy)
@@ -332,6 +332,13 @@
2.0
+
+
+ org.openid4java
+ openid4java
+ 0.9.3
+
+
dom4j
Index: xwiki-core/src/main/java/com/xpn/xwiki/plugin/openid/OpenIdHelper.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/plugin/openid/OpenIdHelper.java (revision 0)
+++ xwiki-core/src/main/java/com/xpn/xwiki/plugin/openid/OpenIdHelper.java (revision 0)
@@ -0,0 +1,278 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ */
+package com.xpn.xwiki.plugin.openid;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openid4java.consumer.ConsumerException;
+import org.openid4java.consumer.ConsumerManager;
+
+import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.objects.BaseObject;
+import com.xpn.xwiki.objects.classes.BaseClass;
+import com.xpn.xwiki.store.query.Query;
+import com.xpn.xwiki.store.query.QueryManager;
+
+/**
+ * OpenID helper class. This singleton class contains various helper methods used for OpenID related tasks.
+ *
+ * @author Markus Lanthaler
+ */
+public class OpenIdHelper
+{
+ private static final Log log = LogFactory.getLog(OpenIdHelper.class);
+
+ private static OpenIdHelper instance;
+
+ private ConsumerManager manager;
+
+ /**
+ * The constructor instantiates a ConsumerManager object.
+ *
+ * @throws ConsumerException
+ */
+ private OpenIdHelper() throws ConsumerException
+ {
+ manager = new ConsumerManager();
+ }
+
+ /**
+ * Gets the unique consumer manager class.
+ *
+ * @return the unique ConsumerManager instance
+ * @throws ConsumerException
+ */
+ public static ConsumerManager getConsumerManager() throws ConsumerException
+ {
+ if (instance == null)
+ instance = new OpenIdHelper();
+
+ return instance.manager;
+ }
+
+ /**
+ * Converts an OpenID identifier to an user name which can be used as a XWiki document name. This method
+ * doesn't check if that user already exists!
+ *
+ * @param openid_identifier the OpenID identifier to convert
+ * @param context the context
+ * @return the converted OpenID identifier
+ */
+ public static String openIdIdentifierToUsername(String openid_identifier, XWikiContext context)
+ {
+ return "OpenID-" + context.getWiki().clearName(openid_identifier, true, true, context) + "-"
+ + openid_identifier.hashCode();
+ }
+
+ /**
+ * Finds the user belonging to a specific OpenID identifier.
+ *
+ * @param openid_identifier the OpenID identifier to search for
+ * @param context the context
+ * @return the full document name for the user belonging to the OpenID identifier or null
if the
+ * OpenID identifier was not found.
+ */
+ public static String findUser(String openid_identifier, XWikiContext context) throws XWikiException
+ {
+ XWiki xwiki = context.getWiki();
+
+ QueryManager qm = xwiki.getStore().getQueryManager();
+ Query search_user = qm.getNamedQuery("getUserDocByOpenIdIdentifier");
+
+ if (search_user == null)
+ throw new RuntimeException("Named query 'getUserDocByOpenIdIdentifier' was not found!");
+
+ search_user.bindValue("identifier", openid_identifier);
+
+ List found_users = search_user.setLimit(1).execute();
+ if (found_users.size() > 0) {
+ if (log.isDebugEnabled()) {
+ log.debug("OpenID " + openid_identifier + " already registered.");
+ }
+ return found_users.get(0);
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates a new OpenID user with a random password. The user doesn't need to know the password - in fact he even
+ * doesn't need to know of its existence. It's just used to use the {@link PersistentLoginManager} and the
+ * Authenticator as they are implemented at the moment.
+ *
+ * @param openid_identifier the OpenID identifier
+ * @param firstname users first name
+ * @param lastname users last name
+ * @param email users email address
+ * @param context the context
+ * @return a code which describes the success or failure of the method
+ * @throws XWikiException
+ */
+ public static int createUser(String openid_identifier, String firstname, String lastname, String email,
+ XWikiContext context) throws XWikiException
+ {
+ XWiki xwiki = context.getWiki();
+ String xwikiname = openIdIdentifierToUsername(openid_identifier, context);
+
+ // Generate a unique document name for the new user
+ XWikiDocument userdoc = xwiki.getDocument("XWiki." + xwikiname, context);
+ while (userdoc.isNew() == false) {
+ userdoc = xwiki.getDocument("XWiki." + xwikiname + "-" + xwiki.generateRandomString(5), context);
+ }
+
+ if (userdoc.isNew()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Creating user for OpenID " + openid_identifier);
+ }
+
+ String content = "#includeForm(\"XWiki.XWikiUserSheet\")";
+ String parent = "XWiki.XWikiUsers";
+ HashMap map = new HashMap();
+ map.put("active", "1");
+ if (firstname == null || firstname.trim().isEmpty())
+ map.put("first_name", openid_identifier);
+ else
+ map.put("first_name", firstname);
+
+ if (lastname != null)
+ map.put("last_name", lastname);
+
+ if (email != null)
+ map.put("email", email);
+
+ String password = xwiki.generateRandomString(255);
+ map.put("password", password);
+
+ int result;
+ if ((result = xwiki.createUser(xwikiname, map, parent, content, "edit", context)) == 1) {
+ // change the return value to output a different message for OpenID users
+ result = 3;
+
+ userdoc = xwiki.getDocument("XWiki." + xwikiname, context);
+
+ if (attachOpenIdToUser(userdoc, openid_identifier, context) == false) {
+ if (log.isDebugEnabled()) {
+ log.debug("Deleting previously created document for OpenID user " + openid_identifier
+ + ". OpenID identifier is already in use.");
+ }
+ xwiki.deleteDocument(userdoc, false, context);
+ result = -13;
+ }
+ }
+ return result;
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("User page already exists for OpenID " + openid_identifier);
+ }
+ return -3;
+ }
+ }
+
+ /**
+ * Attaches an OpenID identifier to a document. The method assures that the identifier is unique. If it is already
+ * used, the method fails and returns false
. The document is automatically saved by this
+ * method.
+ *
+ * @param doc document to which the OpenID identifier should be attached
+ * @param openid_identifier the OpenID identifier to attach
+ * @param context the context
+ * @return true
if attaching the OpenID identifier was successful, otherwise false
.
+ * @throws XWikiException
+ */
+ public static synchronized boolean attachOpenIdToUser(XWikiDocument doc, String openid_identifier,
+ XWikiContext context) throws XWikiException
+ {
+ XWiki xwiki = context.getWiki();
+
+ if (findUser(openid_identifier, context) != null) {
+ if (log.isDebugEnabled()) {
+ log.debug("OpenID " + openid_identifier + " is already registered");
+ }
+ return false;
+ }
+
+ BaseClass baseclass = getOpenIdIdentifierClass(context);
+ BaseObject newobject = (BaseObject) baseclass.newObject(context);
+ newobject.setName(doc.getFullName());
+ newobject.setStringValue("identifier", openid_identifier);
+
+ doc.addObject(baseclass.getName(), newobject);
+ xwiki.saveDocument(doc, context.getMessageTool().get("core.comment.addedOpenIdIdentifier"), context);
+
+ return true;
+ }
+
+ /**
+ * Retrieves the password for an OpenID identifier. Since for all OpenID users a random password which the user
+ * doesn't know is created automatically, we need some way to retrieve it. This method does exactly that.
+ *
+ * @param openid_identifier the OpenID identifier
+ * @param context the context
+ * @return the internal used password for the OpenID user or null
if the user was not found
+ */
+ public static String getOpenIdUserPassword(String openid_identifier, XWikiContext context) throws XWikiException
+ {
+ String xwikiname = findUser(openid_identifier, context);
+
+ XWikiDocument doc = context.getWiki().getDocument(xwikiname, context);
+ // We only allow empty password from users having a XWikiUsers object.
+ if (doc.getObject("XWiki.OpenIdIdentifier") != null && doc.getObject("XWiki.XWikiUsers") != null) {
+ return doc.getStringValue("XWiki.XWikiUsers", "password");
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the OpenIDIdentifer class. Verifies if the XWiki.OpenIdIdentifier
page exists and that it
+ * contains all the required configuration properties to make the OpenID feature work properly. If some properties
+ * are missing they are created and saved in the database.
+ *
+ * @param context the XWiki Context
+ * @return the OpenIdIdentifier Base Class object containing the properties
+ * @throws XWikiException if an error happens while saving
+ */
+ public static BaseClass getOpenIdIdentifierClass(XWikiContext context) throws XWikiException
+ {
+ XWiki xwiki = context.getWiki();
+ XWikiDocument doc;
+ boolean needs_update = false;
+
+ doc = xwiki.getDocument("XWiki.OpenIdIdentifier", context);
+
+ BaseClass bclass = doc.getxWikiClass();
+ bclass.setName("XWiki.OpenIdIdentifier");
+
+ needs_update |= bclass.addTextField("identifier", "Identifier", 2048);
+ needs_update |= bclass.addTextField("password", "Password", 255);
+
+ if (needs_update)
+ xwiki.saveDocument(doc, context);
+
+ return bclass;
+ }
+}
Index: xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/MyFormAuthenticator.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/MyFormAuthenticator.java (revision 11817)
+++ xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/MyFormAuthenticator.java (working copy)
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.security.Principal;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -30,6 +31,14 @@
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+import org.openid4java.OpenIDException;
+import org.openid4java.consumer.ConsumerManager;
+import org.openid4java.consumer.VerificationResult;
+import org.openid4java.discovery.DiscoveryInformation;
+import org.openid4java.discovery.Identifier;
+import org.openid4java.message.AuthRequest;
+import org.openid4java.message.ParameterList;
import org.securityfilter.authenticator.Authenticator;
import org.securityfilter.authenticator.FormAuthenticator;
import org.securityfilter.filter.SecurityRequestWrapper;
@@ -37,7 +46,9 @@
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.plugin.openid.OpenIdHelper;
import com.xpn.xwiki.web.SavedRequestRestorerFilter;
+import com.xpn.xwiki.web.XWikiServletURLFactory;
public class MyFormAuthenticator extends FormAuthenticator implements Authenticator, XWikiAuthenticator
{
@@ -116,7 +127,7 @@
}
} catch (Exception e) {
// in case of exception we continue on Form Auth.
- // we don't want this to interfere with the most common behavior
+ // we don't want this to interfere with the most common behaviour
}
// process any persistent login information, if user is not already logged in,
@@ -139,13 +150,27 @@
}
}
- // process login form submittal
+ // process login form data
if ((this.loginSubmitPattern != null) && request.getMatchableURL().endsWith(this.loginSubmitPattern)) {
- String username = convertUsername(request.getParameter(FORM_USERNAME), context);
- String password = request.getParameter(FORM_PASSWORD);
- String rememberme = request.getParameter(FORM_REMEMBERME);
- rememberme = (rememberme == null) ? "false" : rememberme;
- return processLogin(username, password, rememberme, request, response, context);
+ if (request.getParameter("authentication_method") != null
+ && request.getParameter("authentication_method").equalsIgnoreCase("openid")) {
+ // OpenID login
+ String openid_identifier = request.getParameter("openid_identifier");
+ String rememberme = request.getParameter(FORM_REMEMBERME);
+ rememberme = (rememberme == null) ? "false" : rememberme;
+ return processOpenIdLogin(openid_identifier, rememberme, request, response, context);
+ } else if (request.getParameter("authentication_method") != null
+ && request.getParameter("authentication_method").equalsIgnoreCase("useraccount")) {
+ // Normal user account login
+ String username = convertUsername(request.getParameter(FORM_USERNAME), context);
+ String password = request.getParameter(FORM_PASSWORD);
+ String rememberme = request.getParameter(FORM_REMEMBERME);
+ rememberme = (rememberme == null) ? "false" : rememberme;
+ return processLogin(username, password, rememberme, request, response, context);
+ } else if (request.getParameter("openid.mode") != null) {
+ // OpenID: OP response
+ return processOpenIdLoginResponse(request, response, context);
+ }
}
return false;
}
@@ -155,6 +180,9 @@
* abort further processing after the method completes (for example, if a redirect was sent as part of the login
* processing).
*
+ * @param username
+ * @param password
+ * @param rememberme
* @param request
* @param response
* @return true if the filter should return after this method ends, false otherwise
@@ -169,7 +197,8 @@
log.info("User " + principal.getName() + " has been logged-in");
}
- // invalidate old session if the user was already authenticated, and they logged in as a different user
+ // invalidate old session if the user was already authenticated, and they logged in as a
+ // different user
if (request.getUserPrincipal() != null && !username.equals(request.getRemoteUser())) {
request.getSession().invalidate();
}
@@ -190,7 +219,8 @@
Boolean bAjax = (Boolean) context.get("ajax");
if ((bAjax == null) || (!bAjax.booleanValue())) {
String continueToURL = getContinueToURL(request);
- // This is the url that the user was initially accessing before being prompted for login.
+ // This is the url that the user was initially accessing before being prompted for
+ // login.
response.sendRedirect(response.encodeRedirectURL(continueToURL));
}
} else {
@@ -215,6 +245,173 @@
}
/**
+ * Processes an OpenID login. It redirects the user as part of a normal OpenID login process to the OpenID provider.
+ * The response is handled by {@link MyFormAuthenticator#processOpenIdLoginResponse processOpenIdLoginResponse}.
+ * Returns true if SecurityFilter should abort further processing after the method completes (for example, if a
+ * redirect was sent as part of the login processing which is the normal behaviour).
+ *
+ * @param openid_identifier the OpenID identifier
+ * @param rememberme "true"
if the login should be persistent, null
or
+ * "false"
otherwise.
+ * @param request the request object
+ * @param response the response object
+ * @return true if the filter should return after this method ends, false otherwise
+ */
+ public boolean processOpenIdLogin(String openid_identifier, String rememberme, SecurityRequestWrapper request,
+ HttpServletResponse response, XWikiContext context) throws Exception
+ {
+ if (openid_identifier == null || openid_identifier.trim().equals("")) {
+ context.put("message", "noopenid");
+ return false;
+ }
+
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ String return_to_url =
+ context.getWiki().getExternalURL("XWikiLogin", "loginsubmit", "rememberme=" + rememberme, context);
+
+ List discoveries = manager.discover(openid_identifier);
+ DiscoveryInformation discovered = manager.associate(discoveries);
+
+ // store the discovery information in the user's session
+ request.getSession().setAttribute("openid-discovery", discovered);
+
+ AuthRequest auth_request = manager.authenticate(discovered, return_to_url);
+
+ // set the realm
+ auth_request.setRealm(((XWikiServletURLFactory) context.getURLFactory()).getServerURL(context).toString()
+ + ((XWikiServletURLFactory) context.getURLFactory()).getContextPath());
+
+ if (log.isInfoEnabled()) {
+ log.info("Redirecting user to OP (OpenID identifier: " + openid_identifier + ")");
+ }
+
+ if (discovered.isVersion2()) {
+ // OpenID 2.0 supports HTML FORM Redirection which allows payloads >2048 bytes
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+ vcontext.put("op_endpoint", auth_request.getDestinationUrl(false));
+ vcontext.put("openid_parameters", auth_request.getParameterMap());
+
+ String redirect_form = context.getWiki().parseTemplate("openid_form_redirect.vm", context);
+
+ response.getOutputStream().print(redirect_form);
+
+ // Close the output stream - otherwise the login form documented is also written to it
+ response.getOutputStream().close();
+ } else {
+ // The only method supported in OpenID 1.x is a HTTP-redirect (GET) to the OpenID Provider endpoint (the
+ // redirect-URL usually limited ~2048 bytes)
+ response.sendRedirect(auth_request.getDestinationUrl(true));
+ }
+ } catch (OpenIDException e) {
+ if (log.isInfoEnabled()) {
+ log.info("OpenID discovery failed: " + e.getMessage());
+ }
+
+ // present error to the user
+ context.put("message", "loginfailed");
+ }
+
+ return true;
+ }
+
+ /**
+ * Processes the response of an OpenID provider to complete the login process. Checks the response of the OP and in
+ * case of success it logs in the user. Otherwise an error message is put into the context and shown to the user
+ * afterwards.
+ *
+ * @param request the request object
+ * @param response the response object
+ * @param context the context
+ * @return true if the filter should return after this method ends, false otherwise
+ */
+ public boolean processOpenIdLoginResponse(SecurityRequestWrapper request, HttpServletResponse response,
+ XWikiContext context) throws Exception
+ {
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ // extract the parameters from the authentication response which come in as a HTTP request from the OpenID
+ // provider
+ ParameterList openid_response = new ParameterList(request.getParameterMap());
+
+ // retrieve the previously stored discovery information
+ DiscoveryInformation discovered =
+ (DiscoveryInformation) request.getSession().getAttribute("openid-discovery");
+
+ // verify the response
+ StringBuffer receivingURL = request.getRequestURL();
+ String queryString = request.getQueryString();
+ if (queryString != null && queryString.length() > 0)
+ receivingURL.append("?").append(request.getQueryString());
+
+ VerificationResult verification = manager.verify(receivingURL.toString(), openid_response, discovered);
+ Identifier verified = verification.getVerifiedId();
+
+ if (verified != null) {
+ String username = OpenIdHelper.findUser(verified.getIdentifier(), context);
+
+ if (username == null) {
+ // no user was found for this OpenID identifier
+ if (log.isInfoEnabled()) {
+ log.info("No user for OpenID " + verified.getIdentifier() + " found.");
+ }
+
+ context.put("message", "openid_not_associated");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ return true;
+ }
+
+ // The current authentication mechanisms is implemented in a very restrictive manner, we have to
+ // retrieve the user password (which is generated randomly during registration for OpenID users) and use
+ // it in order to authenticate the user.
+ String password = OpenIdHelper.getOpenIdUserPassword(verified.getIdentifier(), context);
+ Principal principal = authenticate(username, password, context);
+ if (principal != null) {
+ // invalidate old session if the user was already authenticated and logged in as a different user
+ if (request.getUserPrincipal() != null) {
+ request.getSession().invalidate();
+ }
+
+ // manage persistent login info if persistent login management is enabled
+ String rememberme = request.getParameter(FORM_REMEMBERME);
+ rememberme = (rememberme == null) ? "false" : rememberme;
+
+ if (this.persistentLoginManager != null) {
+ if (rememberme != null) {
+ this.persistentLoginManager.rememberLogin(request, response, username, password);
+ } else {
+ this.persistentLoginManager.forgetLogin(request, response);
+ }
+ }
+
+ request.setUserPrincipal(principal);
+
+ String continueToURL = getContinueToURL(request);
+ response.sendRedirect(response.encodeRedirectURL(continueToURL));
+ }
+ } else {
+ // authentication failed, show and log error message
+ if (openid_response.getParameter("openid.mode") != null
+ && openid_response.getParameter("openid.mode").getValue().equals("cancel")) {
+ context.put("message", "openidlogin_cancelled");
+ } else {
+ if (log.isInfoEnabled() && openid_response.getParameter("error") != null) {
+ log.info("OpenID login failed (error: "
+ + openid_response.getParameter("openid.error").getValue() + ")");
+ }
+ context.put("message", "loginfailed");
+ }
+ }
+ } catch (OpenIDException e) {
+ context.put("message", "loginfailed");
+ }
+
+ return true;
+ }
+
+ /**
* FormAuthenticator has a special case where the user should be sent to a default page if the user spontaneously
* submits a login request.
*
Index: xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java (revision 11817)
+++ xwiki-core/src/main/java/com/xpn/xwiki/user/impl/xwiki/XWikiAuthServiceImpl.java (working copy)
@@ -242,7 +242,7 @@
String sql =
"delete from XWikiLock as lock where lock.userName=:userName";
Query query = session.createQuery(sql);
- String localName = user.getName().substring(user.getName().indexOf(":") + 1);
+ String localName = user.getName().substring(user.getName().indexOf(":") + 1);
query.setString("userName", localName);
query.executeUpdate();
} catch (Exception e) {
@@ -475,18 +475,23 @@
return user;
}
- protected boolean checkPassword(String username, String password, XWikiContext context)
- throws XWikiException
+ protected boolean checkPassword(String username, String password, XWikiContext context) throws XWikiException
{
try {
boolean result = false;
XWikiDocument doc = context.getWiki().getDocument(username, context);
- // We only allow empty password from users having a XWikiUsers object.
- if (doc.getObject("XWiki.XWikiUsers") != null) {
+ if (doc.getObject("XWiki.OpenIdIdentifier") != null) {
+ // For users having an OpenID the password doesn't need to be adjusted because it is set to the current
+ // value during the login process
String passwd = doc.getStringValue("XWiki.XWikiUsers", "password");
+ result = (password.equals(passwd));
+ }
+ if (result == false && doc.getObject("XWiki.XWikiUsers") != null) {
+ // We only allow empty password from users having a XWikiUsers object.
+ String passwd = doc.getStringValue("XWiki.XWikiUsers", "password");
password =
- ((PasswordClass) context.getWiki().getClass("XWiki.XWikiUsers", context)
- .getField("password")).getEquivalentPassword(passwd, password);
+ ((PasswordClass) context.getWiki().getClass("XWiki.XWikiUsers", context).getField("password"))
+ .getEquivalentPassword(passwd, password);
result = (password.equals(passwd));
}
Index: xwiki-core/src/main/java/com/xpn/xwiki/web/AttachOpenIdAction.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/web/AttachOpenIdAction.java (revision 0)
+++ xwiki-core/src/main/java/com/xpn/xwiki/web/AttachOpenIdAction.java (revision 0)
@@ -0,0 +1,286 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ */
+package com.xpn.xwiki.web;
+
+import java.util.List;
+
+import com.xpn.xwiki.XWiki;
+import com.xpn.xwiki.XWikiContext;
+import com.xpn.xwiki.XWikiException;
+import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.objects.BaseObject;
+import com.xpn.xwiki.objects.classes.PasswordClass;
+import com.xpn.xwiki.plugin.openid.OpenIdHelper;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.velocity.VelocityContext;
+
+import org.openid4java.consumer.ConsumerManager;
+import org.openid4java.consumer.VerificationResult;
+import org.openid4java.discovery.Identifier;
+import org.openid4java.discovery.DiscoveryInformation;
+import org.openid4java.message.ax.AxMessage;
+import org.openid4java.message.ax.FetchRequest;
+import org.openid4java.message.ax.FetchResponse;
+import org.openid4java.message.sreg.SRegMessage;
+import org.openid4java.message.sreg.SRegRequest;
+import org.openid4java.message.sreg.SRegResponse;
+import org.openid4java.message.*;
+import org.openid4java.OpenIDException;
+
+/**
+ * Action used to attach an OpenID to already existing users.
+ *
+ * @author Markus Lanthaler
+ */
+public class AttachOpenIdAction extends XWikiAction
+{
+ private static final Log log = LogFactory.getLog(AttachOpenIdAction.class);
+
+ private String template = "attach_openid";
+
+ public boolean action(XWikiContext context) throws XWikiException
+ {
+ // TODO Make sure that the user is signed in!
+
+ XWikiRequest request = context.getRequest();
+ XWikiResponse response = context.getResponse();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+
+ template = "attach_openid";
+
+ String attach_openid = request.getParameter("attach_openid");
+ if ((attach_openid != null) && (attach_openid.equals("discover-openid"))) {
+ if (discoverOpenID(context))
+ return false;
+ } else if ((attach_openid != null) && (attach_openid.equals("confirm"))) {
+ vcontext.put("status", new Integer(confirmAttachingOpenId(context)));
+ } else if ((attach_openid != null) && (attach_openid.equals("attach-openid"))) {
+ vcontext.put("status", new Integer(attachOpenID(context)));
+ } else {
+ // Check if the user has already attached an OpenID
+ XWikiDocument user_doc;
+ user_doc = context.getWiki().getDocument(context.getXWikiUser().getUser(), context);
+
+ if (user_doc.getObject("XWiki.OpenIdIdentifier") != null) {
+ vcontext.put("status", new Integer(-3)); // Error! User needs to delete his OpenID first
+ }
+ }
+
+ String redirect = Utils.getRedirect(request, null);
+ if (redirect == null)
+ return true;
+ else {
+ sendRedirect(response, redirect);
+ return false;
+ }
+ }
+
+ public String render(XWikiContext context) throws XWikiException
+ {
+ return template;
+ }
+
+ /**
+ * Starts the process of attaching an OpenID to an existing user. The OpenID provider belonging to the entered
+ * OpenID identifier is searched and the user is redirected to it to authenticate there. This processed is used to
+ * assure that the entered OpenID is valid and in possession of that user. If discovery fails, an error message is
+ * shown.
+ *
+ * @param context
+ * @return returns true if a redirect was sent, otherwise false.
+ */
+ protected boolean discoverOpenID(XWikiContext context)
+ {
+ XWikiRequest request = context.getRequest();
+ XWikiResponse response = context.getResponse();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+
+ // Check for empty OpenID identifier
+ String openid_identifier = request.getParameter("openid_identifier");
+ if (openid_identifier == null || openid_identifier.equals("")) {
+ vcontext.put("status", new Integer(-14));
+ return false;
+ }
+
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ String return_to_url =
+ context.getWiki().getExternalURL("AttachOpenID", "attachopenid", "attach_openid=confirm",
+ context);
+
+ // perform discovery on the user-supplied identifier
+ List discoveries = manager.discover(openid_identifier);
+
+ // attempt to associate with the OpenID provider and retrieve one service endpoint for authentication
+ DiscoveryInformation discovered = manager.associate(discoveries);
+ request.getSession().setAttribute("openid-discovery", discovered);
+
+ // obtain a AuthRequest message to be sent to the OpenID provider
+ AuthRequest auth_request = manager.authenticate(discovered, return_to_url);
+
+ // set the realm
+ auth_request.setRealm(((XWikiServletURLFactory) context.getURLFactory()).getServerURL(context).toString()
+ + ((XWikiServletURLFactory) context.getURLFactory()).getContextPath());
+
+ if (discovered.isVersion2()) {
+ // OpenID 2.0 supports HTML form redirection which allows payloads >2048 bytes
+ vcontext.put("op_endpoint", auth_request.getDestinationUrl(false));
+ vcontext.put("openid_parameters", auth_request.getParameterMap());
+ template = "openid_form_redirect";
+ return false;
+ } else {
+ // the only method supported in OpenID 1.x is a HTTP-redirect (GET) to the OpenID Provider endpoint (the
+ // redirect-URL usually limited ~2048 bytes)
+ sendRedirect(response, auth_request.getDestinationUrl(true));
+ return true;
+ }
+ } catch (OpenIDException e) {
+ context.put("message", "register_openid_discovery_failed");
+ } catch (Exception e) {
+ context.put("message", "register_openid_discovery_failed");
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks the response of the OpenID provider (OP) and outputs a confirmation form. If the OP returns an error or
+ * the user cancelled at its site, an error message is shown to the user.
+ *
+ * @param context
+ * @throws XWikiException
+ */
+ protected int confirmAttachingOpenId(XWikiContext context) throws XWikiException
+ {
+ XWikiRequest request = context.getRequest();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ // extract the parameters from the authentication response
+ // (which comes in as a HTTP request from the OpenID provider)
+ ParameterList openid_response = new ParameterList(request.getParameterMap());
+
+ // retrieve the previously stored discovery information
+ DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute("openid-discovery");
+
+ // extract the receiving URL from the HTTP request
+ StringBuffer receiving_url = request.getRequestURL();
+ String query_string = request.getQueryString();
+ if (query_string != null && query_string.length() > 0)
+ receiving_url.append("?").append(request.getQueryString());
+
+ // verify the response; ConsumerManager needs to be the same
+ // (static) instance used to place the authentication request
+ VerificationResult verification = manager.verify(receiving_url.toString(), openid_response, discovered);
+
+ // examine the verification result and extract the verified identifier
+ Identifier verified = verification.getVerifiedId();
+
+ if (verified != null) {
+ // check if this OpenID is already registered
+ if (OpenIdHelper.findUser(verified.getIdentifier(), context) != null) {
+ vcontext.put("openid_identifier", verified.getIdentifier());
+ return -3;
+ }
+
+ // OpenID not used yet, continue with registration (ask the user for confirmation)
+ vcontext.put("openid_identifier", verified.getIdentifier());
+ return 1;
+ } else {
+ // authentication failed, show and log error message
+ if (openid_response.getParameter("openid.mode") != null
+ && openid_response.getParameter("openid.mode").getValue().equals("cancel")) {
+ return -5; // OpenID discovery cancelled
+ } else {
+ if (log.isInfoEnabled() && openid_response.getParameter("error") != null) {
+ log.info("OpenID login failed (error: "
+ + openid_response.getParameter("openid.error").getValue() + ")");
+ }
+ return -6; // OpenID discovery failed
+ }
+ }
+ } catch (OpenIDException e) {
+ return -6; // OpenID discovery failed
+ }
+ }
+
+ /**
+ * Attaches an OpenID to an existing user. The method checks if the password is correct and if so the OpenID is
+ * attached to the user.
+ *
+ * @param context
+ * @return an status code describing the success or failure of the process
+ * @throws XWikiException
+ */
+ protected int attachOpenID(XWikiContext context) throws XWikiException
+ {
+ XWikiRequest request = context.getRequest();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+ String openid_identifier = request.getParameter("openid_identifier");
+ String password = request.getParameter("password");
+
+ if (openid_identifier == null || openid_identifier.length() == 0) {
+ return -2; // No OpenID passed
+ }
+
+ if (password == null || password.length() == 0) {
+ vcontext.put("openid_identifier", openid_identifier);
+ return -4; // Empty passwords are not allowed
+ }
+
+ // Get the user document
+ XWikiDocument user_doc;
+ user_doc = context.getWiki().getDocument(context.getXWikiUser().getUser(), context);
+
+ // Check if the user has already attached an OpenID
+ if (user_doc.getObject("XWiki.OpenIdIdentifier") != null) {
+ return -3; // Error! User needs to delete his OpenID first
+ }
+
+ // Check if the passed password is valid
+ if (user_doc.getObject("XWiki.XWikiUsers") != null) {
+ String passwd = user_doc.getStringValue("XWiki.XWikiUsers", "password");
+ password =
+ ((PasswordClass) context.getWiki().getClass("XWiki.XWikiUsers", context).getField("password"))
+ .getEquivalentPassword(passwd, password);
+
+ if (password.equals(passwd) == false) {
+ vcontext.put("openid_identifier", openid_identifier);
+ return -4; // Wrong password
+ }
+ }
+
+ // Attach the OpenID
+ if (OpenIdHelper.attachOpenIdToUser(user_doc, openid_identifier, context) == false) {
+ return -5; // Internal error
+ }
+
+ // Successfully attached the OpenID to the user account
+ vcontext.put("username", context.getWiki().getUserName(context.getXWikiUser().getUser(), context));
+ vcontext.put("openid_identifier", openid_identifier);
+ return 2;
+ }
+}
Index: xwiki-core/src/main/java/com/xpn/xwiki/web/RegisterAction.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/web/RegisterAction.java (revision 11817)
+++ xwiki-core/src/main/java/com/xpn/xwiki/web/RegisterAction.java (working copy)
@@ -20,41 +20,284 @@
*/
package com.xpn.xwiki.web;
+import java.util.List;
+
import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
-import com.xpn.xwiki.doc.XWikiDocument;
+import com.xpn.xwiki.plugin.openid.OpenIdHelper;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
-public class RegisterAction extends XWikiAction {
- public boolean action(XWikiContext context) throws XWikiException {
+import org.openid4java.consumer.ConsumerManager;
+import org.openid4java.consumer.VerificationResult;
+import org.openid4java.discovery.Identifier;
+import org.openid4java.discovery.DiscoveryInformation;
+import org.openid4java.message.ax.AxMessage;
+import org.openid4java.message.ax.FetchRequest;
+import org.openid4java.message.ax.FetchResponse;
+import org.openid4java.message.sreg.SRegMessage;
+import org.openid4java.message.sreg.SRegRequest;
+import org.openid4java.message.sreg.SRegResponse;
+import org.openid4java.message.*;
+import org.openid4java.OpenIDException;
+
+/**
+ * Action used to register new users. This action implements both, registration for classical user accounts with user
+ * name and password and users using OpenID.
+ */
+public class RegisterAction extends XWikiAction
+{
+ private static final Log log = LogFactory.getLog(RegisterAction.class);
+
+ private String template = "register";
+
+ public boolean action(XWikiContext context) throws XWikiException
+ {
XWiki xwiki = context.getWiki();
XWikiRequest request = context.getRequest();
XWikiResponse response = context.getResponse();
- XWikiDocument doc = context.getDoc();
+ template = "register";
+
String register = request.getParameter("register");
- if ((register!=null)&&(register.equals("1"))) {
+ if ((register != null) && (register.equals("1"))) {
int useemail = xwiki.getXWikiPreferenceAsInt("use_email_verification", 0, context);
int result;
- if (useemail==1)
- result = xwiki.createUser(true, "edit", context);
+ if (useemail == 1)
+ result = xwiki.createUser(true, "edit", context);
else
- result = xwiki.createUser(context);
+ result = xwiki.createUser(context);
VelocityContext vcontext = (VelocityContext) context.get("vcontext");
vcontext.put("reg", new Integer(result));
+ } else if ((register != null) && (register.equals("openid-discover"))) {
+ if (discoverOpenId(context))
+ return false;
+ } else if ((register != null) && (register.equals("openid-confirm"))) {
+ String confirm = request.getParameter("register-confirm");
+ if ("1".equals(confirm) == false) {
+ confirmOpenIdRegistration(context);
+ return true;
+ } else {
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+ vcontext.put("reg", new Integer(registerOpenId(context)));
+ }
}
String redirect = Utils.getRedirect(request, null);
- if (redirect==null)
+ if (redirect == null)
return true;
else {
sendRedirect(response, redirect);
return false;
}
- }
-
- public String render(XWikiContext context) throws XWikiException {
- return "register";
- }
+ }
+
+ public String render(XWikiContext context) throws XWikiException
+ {
+ return template;
+ }
+
+ /**
+ * Starts registration of an OpenID user. The OpenID provider belonging to the entered OpenID identifier is searched
+ * and the user is redirected to it to authenticate there. This processed is used to assure that the entered OpenID
+ * is valid and in possession of that user. If discovery fails, an error message is shown.
+ *
+ * @param context
+ * @return returns true if a redirect was sent, otherwise false.
+ * @author Markus Lanthaler
+ */
+ protected boolean discoverOpenId(XWikiContext context)
+ {
+ XWikiRequest request = context.getRequest();
+ XWikiResponse response = context.getResponse();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+
+ // Check for empty OpenID identifier
+ String openid_identifier = request.getParameter("openid_identifier");
+ if (openid_identifier == null || openid_identifier.equals("")) {
+ vcontext.put("reg", new Integer(-14));
+ return false;
+ }
+
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ String return_to_url =
+ context.getWiki().getExternalURL("Register", "register", "register=openid-confirm", context);
+
+ // perform discovery on the user-supplied identifier
+ List discoveries = manager.discover(openid_identifier);
+
+ // attempt to associate with the OpenID provider and retrieve one service endpoint for authentication
+ DiscoveryInformation discovered = manager.associate(discoveries);
+ request.getSession().setAttribute("openid-discovery", discovered);
+
+ // obtain a AuthRequest message to be sent to the OpenID provider
+ AuthRequest auth_request = manager.authenticate(discovered, return_to_url);
+
+ // set the realm
+ auth_request.setRealm(((XWikiServletURLFactory) context.getURLFactory()).getServerURL(context).toString()
+ + ((XWikiServletURLFactory) context.getURLFactory()).getContextPath());
+
+ // attribute exchange (request user data from the OP to speed-up the registration process)
+ FetchRequest att_exchange = FetchRequest.createFetchRequest();
+ att_exchange.addAttribute("email", "http://schema.openid.net/contact/email", true);
+ att_exchange.addAttribute("firstname", "http://axschema.org/namePerson/first", true);
+ att_exchange.addAttribute("lastname", "http://axschema.org/namePerson/last", true);
+
+ SRegRequest simple_reg_req = SRegRequest.createFetchRequest();
+ simple_reg_req.addAttribute("fullname", true);
+ simple_reg_req.addAttribute("firstname", true);
+ simple_reg_req.addAttribute("lastname", true);
+ simple_reg_req.addAttribute("nickname", true);
+ simple_reg_req.addAttribute("email", true);
+
+ auth_request.addExtension(att_exchange);
+ auth_request.addExtension(simple_reg_req);
+
+ if (discovered.isVersion2()) {
+ // OpenID 2.0 supports HTML form redirection which allows payloads >2048 bytes
+ vcontext.put("op_endpoint", auth_request.getDestinationUrl(false));
+ vcontext.put("openid_parameters", auth_request.getParameterMap());
+ template = "openid_form_redirect";
+ return false;
+ } else {
+ // the only method supported in OpenID 1.x is a HTTP-redirect (GET) to the OpenID Provider endpoint (the
+ // redirect-URL usually limited ~2048 bytes)
+ sendRedirect(response, auth_request.getDestinationUrl(true));
+ return true;
+ }
+ } catch (OpenIDException e) {
+ context.put("message", "register_openid_discovery_failed");
+ } catch (Exception e) {
+ context.put("message", "register_openid_discovery_failed");
+ }
+
+ return false;
+ }
+
+ /**
+ * Checks the response of the OpenID provider (OP) and outputs a confirmation form. If the OP returns an error or
+ * the user cancelled at its site, an error message is shown to the user.
+ *
+ * @param context
+ * @throws XWikiException
+ * @author Markus Lanthaler
+ */
+ protected void confirmOpenIdRegistration(XWikiContext context) throws XWikiException
+ {
+ XWikiRequest request = context.getRequest();
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+
+ try {
+ ConsumerManager manager = OpenIdHelper.getConsumerManager();
+
+ // extract the parameters from the authentication response
+ // (which comes in as a HTTP request from the OpenID provider)
+ ParameterList openid_response = new ParameterList(request.getParameterMap());
+
+ // retrieve the previously stored discovery information
+ DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute("openid-discovery");
+
+ // extract the receiving URL from the HTTP request
+ StringBuffer receiving_url = request.getRequestURL();
+ String query_string = request.getQueryString();
+ if (query_string != null && query_string.length() > 0)
+ receiving_url.append("?").append(request.getQueryString());
+
+ // verify the response; ConsumerManager needs to be the same
+ // (static) instance used to place the authentication request
+ VerificationResult verification = manager.verify(receiving_url.toString(), openid_response, discovered);
+
+ // examine the verification result and extract the verified identifier
+ Identifier verified = verification.getVerifiedId();
+
+ if (verified != null) {
+ // check if this OpenID is already registered
+ if (OpenIdHelper.findUser(verified.getIdentifier(), context) != null) {
+ vcontext.put("reg", new Integer(-13));
+ vcontext.put("openid_identifier", verified.getIdentifier());
+ return;
+ }
+
+ // OpenID not used yet, continue with registration (ask the user for confirmation)
+ vcontext.put("reg", new Integer(2));
+ vcontext.put("openid_identifier", verified.getIdentifier());
+
+ AuthSuccess auth_success = (AuthSuccess) verification.getAuthResponse();
+
+ String email = null;
+ String firstname = null;
+ String lastname = null;
+
+ if (auth_success.hasExtension(AxMessage.OPENID_NS_AX)) {
+ FetchResponse fetch_resp = (FetchResponse) auth_success.getExtension(AxMessage.OPENID_NS_AX);
+ email = (String) fetch_resp.getAttributeValues("email").get(0);
+ firstname = (String) fetch_resp.getAttributeValues("firstname").get(0);
+ lastname = (String) fetch_resp.getAttributeValues("lastname").get(0);
+ }
+
+ if (auth_success.getExtension(SRegMessage.OPENID_NS_SREG) instanceof SRegResponse) {
+ SRegResponse simple_reg_resp = (SRegResponse) auth_success.getExtension(SRegMessage.OPENID_NS_SREG);
+
+ if (email == null)
+ email = simple_reg_resp.getAttributeValue("email");
+
+ if (firstname == null && lastname == null)
+ firstname = simple_reg_resp.getAttributeValue("fullname");
+ }
+
+ vcontext.put("email", email);
+ vcontext.put("first_name", firstname);
+ vcontext.put("last_name", lastname);
+ } else {
+ // authentication failed, show and log error message
+ if (openid_response.getParameter("openid.mode") != null
+ && openid_response.getParameter("openid.mode").getValue().equals("cancel")) {
+ context.put("message", "register_openid_discovery_cancelled");
+ } else {
+ if (log.isInfoEnabled() && openid_response.getParameter("error") != null) {
+ log.info("OpenID login failed (error: "
+ + openid_response.getParameter("openid.error").getValue() + ")");
+ }
+ context.put("message", "register_openid_discovery_failed");
+ }
+ }
+ } catch (OpenIDException e) {
+ context.put("message", "register_openid_discovery_failed");
+ }
+ }
+
+ /**
+ * Completes the registration of an OpenID user. The user name is created automatically based on the OpenID
+ * identifier by {@link OpenIdHelper#openIdIdentifierToUsername}.
+ *
+ * @param context
+ * @return an status code describing the success or failure of the registration
+ * @throws XWikiException
+ * @author Markus Lanthaler
+ * @see OpenIdHelper#openIdIdentifierToUsername
+ */
+ protected int registerOpenId(XWikiContext context) throws XWikiException
+ {
+ XWikiRequest request = context.getRequest();
+ String openid_identifier = request.getParameter("openid_identifier");
+ String firstname = request.getParameter("register_first_name");
+ String lastname = request.getParameter("register_last_name");
+ String email = request.getParameter("register_email");
+
+ int result = OpenIdHelper.createUser(openid_identifier, firstname, lastname, email, context);
+ if (result == 3) {
+ // user registration successful
+ VelocityContext vcontext = (VelocityContext) context.get("vcontext");
+ vcontext.put("username", context.getWiki().getUserName(OpenIdHelper.findUser(openid_identifier, context),
+ context));
+ vcontext.put("openid_identifier", openid_identifier);
+ }
+
+ return result;
+ }
}
Index: xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java
===================================================================
--- xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java (revision 11817)
+++ xwiki-core/src/main/java/com/xpn/xwiki/web/XWikiServletURLFactory.java (working copy)
@@ -134,12 +134,12 @@
return servletPath;
}
- private URL getServerURL(XWikiContext context) throws MalformedURLException
+ public URL getServerURL(XWikiContext context) throws MalformedURLException
{
return getServerURL(context.getDatabase(), context);
}
- private URL getServerURL(String xwikidb, XWikiContext context) throws MalformedURLException
+ public URL getServerURL(String xwikidb, XWikiContext context) throws MalformedURLException
{
URL serverURL = this.serverURL;
if (context.getRequest() != null) { // necessary to the tests
Index: xwiki-core/src/main/resources/ApplicationResources.properties
===================================================================
--- xwiki-core/src/main/resources/ApplicationResources.properties (revision 11817)
+++ xwiki-core/src/main/resources/ApplicationResources.properties (working copy)
@@ -527,12 +527,48 @@
admin.adminappnotinstalled=The administration application is not installed. Since XWiki Enterprise 1.5 the Administration is distributed as an application. You can download it from {0}.
#login
+login_username_password_desc=with your username and password
+login_openid_desc=... or with your OpenID
nousername=No user name given
+noopenid=Please enter your OpenID identifier to log in
nopassword=No password given
wronguser=Wrong user name
wrongpassword=Wrong password
loginfailed=Internal error
+openidlogin_cancelled=The login process was cancelled at the OpenID provider site
+openid_not_associated=No user was found for this OpenID
+#openid
+openid.common.discovery_cancelled=The login process was cancelled at the OpenID provider site
+openid.common.discovery_failed=The discovery of the OpenID failed
+openid.common.identifier_field_label=OpenID
+
+#openid form redirect
+openid.form_redirect.title=OpenID login in progress
+openid.form_redirect.description=You are redirected to your OpenID provider in a few seconds. Please wait...
+openid.form_redirect.button=Continue...
+
+#openid registration form
+openid.registration.welcome=If you have an OpenID or i-name you can speed-up your registration by entering it here
+openid.registration.discovery_submit=Register with OpenID
+openid.registration.confirmation=Verify the form below and complete your OpenID registration
+openid.registration.confirmation_submit=Create OpenID account
+openid.registration.invalidOpenID=Enter a valid OpenID to continue with registration
+openid.registration.openIdAlreadyRegistered=The OpenID "{0}" is already registered. You can directly log in if it is in your possession.
+openid.registration.successful=Successfully registered user {0} ({1}).
+
+#attach openid to existing user
+openid.attach.title=Associate an OpenID with your user account
+openid.attach.welcome=Enter your OpenID to attach it to your user account.
+openid.attach.confirm=Enter your password to attach the OpenID shown below to your user account.
+openid.attach.submit=Attach OpenID
+openid.attach.alreadyAssociatedOpenId=You have already associated an OpenID with your user account.
+openid.attach.openIdAlreadyRegistered=The OpenID "{0}" is already registered with another user account. You can directly log in if it is in your possession.
+openid.attach.passwordInvalid=The entered password is invalid
+openid.attach.internalError=An internal error occurred and the OpenID could not be associated with you user account. Please contact the administrator.
+openid.attach.successful=Successfully attached the OpenID "{0}" to {0}.
+
+
switchto=Switch to
sectionEdit=Sectional Editing
@@ -619,6 +655,8 @@
registerfailed=Registration has failed
registerfailedcode=code
registersuccessful=Registration successful
+register_openid_discovery_cancelled=The registration with OpenID was cancelled at the OpenID provider site
+register_openid_discovery_failed=The registration with OpenID failed due to an internal error
leftPanels=Left Panels
rightPanels=Right Panels
@@ -764,6 +802,7 @@
core.comment.updateClassPropertyName=Updated class property name
core.comment.createdUser=Created user
core.comment.addedUserToGroup=Added user to group
+core.comment.addedOpenIdIdentifier=Added OpenID identifier
core.comment.rollback=Rollback to version {0}
core.comment.updateContent=Update Content
core.comment.uploadAttachmentComment=Upload new attachment {0}
Index: xwiki-core/src/main/resources/JcrQueries.properties
===================================================================
--- xwiki-core/src/main/resources/JcrQueries.properties (revision 11817)
+++ xwiki-core/src/main/resources/JcrQueries.properties (working copy)
@@ -3,3 +3,4 @@
getAllDocuments=//element(*, xwiki:document)/@fullName
listGroupsForUser=//element(*, xwiki:document)[obj/XWiki/XWikiGroups[@xp:member=:{username} or @xp:member=:{shortname} or @xp:member=:{veryshortname}]/@fullName
getAllUsers=//element(*, xwiki:document)[obj/XWiki/XWikiUsers]/@fullName
+getUserDocByOpenIdIdentifier=//element(*, xwiki:document)[obj/XWiki/OpenIdIdentifier/@xp:identifier=:{identifier}]/@fullName
Index: xwiki-core/src/main/resources/queries.hbm.xml
===================================================================
--- xwiki-core/src/main/resources/queries.hbm.xml (revision 11817)
+++ xwiki-core/src/main/resources/queries.hbm.xml (working copy)
@@ -23,4 +23,7 @@
select doc.fullName from XWikiDocument as doc, BaseObject as obj
where obj.name=doc.fullName and obj.className='XWiki.XWikiUsers'
+
+ select doc.fullName from XWikiDocument as doc, BaseObject as obj, StringProperty as prop where doc.fullName=obj.name and obj.className='XWiki.OpenIdIdentifier' and obj.id=prop.id.id and prop.id.name='identifier' and prop.value=:identifier
+