package fi.otavanopisto.pyramus.plugin.openid;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.openid4java.association.AssociationException;
import org.openid4java.consumer.ConsumerException;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryException;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.MessageException;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import fi.internetix.smvc.SmvcRuntimeException;
import fi.internetix.smvc.controllers.RequestContext;
import fi.otavanopisto.pyramus.dao.DAOFactory;
import fi.otavanopisto.pyramus.dao.users.UserDAO;
import fi.otavanopisto.pyramus.dao.users.UserVariableDAO;
import fi.otavanopisto.pyramus.domainmodel.users.User;
import fi.otavanopisto.pyramus.plugin.auth.AuthenticationException;
import fi.otavanopisto.pyramus.plugin.auth.ExternalAuthenticationProvider;
public class OpenIDAuthorizationStrategy implements ExternalAuthenticationProvider {
public OpenIDAuthorizationStrategy() {
// try {
consumerManager = new ConsumerManager();
// } catch (ConsumerException e) {
// throw new SmvcRuntimeException(e);
// }
}
public String getName() {
return "OpenID";
}
public void performDiscovery(RequestContext requestContext) {
try {
HttpSession session = requestContext.getRequest().getSession();
// perform discovery on the user-supplied identifier
List<?> discoveries = consumerManager.discover(System.getProperty("authentication.OpenID.identifier"));
// attempt to associate with the OpenID provider
// and retrieve one service endpoint for authentication
DiscoveryInformation discovered = consumerManager.associate(discoveries);
// store the discovery information in the user's session for later use
session.setAttribute("discovered", discovered);
// Construct a path back to users/externallogin.page in Pyramus
String currentURL = requestContext.getRequest().getRequestURL().toString();
String pathInfo = requestContext.getRequest().getRequestURI();
String baseURL = currentURL.substring(0, currentURL.length() - pathInfo.length());
StringBuilder returnURL = new StringBuilder(baseURL)
.append(requestContext.getRequest().getContextPath())
.append("/users/externallogin.page");
// obtain a AuthRequest message to be sent to the OpenID provider
AuthRequest authReq = consumerManager.authenticate(discovered, returnURL.toString());
// Attribute Exchange example: fetching the 'email' attribute
FetchRequest fetch = FetchRequest.createFetchRequest();
fetch.addAttribute("email",
// attribute alias
"http://schema.openid.net/contact/email", // type URI
true); // required
// attach the extension to the authentication request
authReq.addExtension(fetch);
requestContext.setRedirectURL(authReq.getDestinationUrl(true));
} catch (DiscoveryException e) {
throw new SmvcRuntimeException(e);
} catch (MessageException e) {
throw new SmvcRuntimeException(e);
} catch (ConsumerException e) {
throw new SmvcRuntimeException(e);
}
}
@SuppressWarnings("unchecked")
public User processResponse(RequestContext requestContext) throws AuthenticationException {
UserDAO userDAO = DAOFactory.getInstance().getUserDAO();
try {
HttpSession session = requestContext.getRequest().getSession();
// extract the parameters from the authentication response
// (which comes in as a HTTP request from the OpenID provider)
ParameterList openidResp = new ParameterList(requestContext.getRequest().getParameterMap());
// retrieve the previously stored discovery information
DiscoveryInformation discovered = (DiscoveryInformation) session.getAttribute("discovered");
// extract the receiving URL from the HTTP request
StringBuffer receivingURL = requestContext.getRequest().getRequestURL();
String queryString = requestContext.getRequest().getQueryString();
if (queryString != null && queryString.length() > 0) {
receivingURL.append("?").append(requestContext.getRequest().getQueryString());
}
// verify the response
VerificationResult verification = consumerManager.verify(receivingURL.toString(), openidResp, discovered);
// examine the verification result and extract the verified identifier
Identifier verified = verification.getVerifiedId();
if (verified != null) {
AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse();
List<String> emails = null;
if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
FetchResponse fetchResp = (FetchResponse) authSuccess.getExtension(AxMessage.OPENID_NS_AX);
emails = fetchResp.getAttributeValues("email");
}
UserVariableDAO userVariableDAO = DAOFactory.getInstance().getUserVariableDAO();
User user = userDAO.findByExternalIdAndAuthProvider(verified.getIdentifier(), getName());
if (user == null) {
user = userDAO.findByEmail(emails.get(0));
if (user != null) {
String expectedLoginServer = userVariableDAO.findByUserAndKey(user, "openid.expectedlogin");
String loginServer = verification.getAuthResponse().getParameterValue("openid.op_endpoint");
if (!StringUtils.isBlank(expectedLoginServer) && expectedLoginServer.equals(loginServer)) {
userVariableDAO.setUserVariable(user, "openid.expectedlogin", null);
userDAO.updateExternalId(user, verified.getIdentifier());
} else {
throw new AuthenticationException(AuthenticationException.LOCAL_USER_MISSING);
}
} else {
throw new AuthenticationException(AuthenticationException.LOCAL_USER_MISSING);
}
}
return user;
} else {
return null;
}
} catch (MessageException e) {
throw new SmvcRuntimeException(e);
} catch (DiscoveryException e) {
throw new SmvcRuntimeException(e);
} catch (AssociationException e) {
throw new SmvcRuntimeException(e);
}
}
private ConsumerManager consumerManager;
}