+ * Returning from the external authorization server. If we were successful, + * the header will contain the name of the user who just logged in. + * + * Deal with these possibilities: + * - The header name was not configured in deploy.properties. Complain. + * - No username: the login failed. Complain + * - User corresponds to a User acocunt. Record the login. + * - User corresponds to an Individual (self-editor). + * - User is not recognized. + *+ */ + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (externalAuthUsernameHeader == null) { + complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, + MESSAGE_NO_EXTERNAL_AUTH_USERNAME); + return; + } + + String username = req.getHeader(externalAuthUsernameHeader); + String uri = getAssociatedIndividualUri(username, req); + + if (username == null) { + log.debug("No username."); + complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, + MESSAGE_LOGIN_FAILED); + } else if (getAuthenticator(req).isExistingUser(username)) { + log.debug("Logging in as " + username); + getAuthenticator(req).recordUserIsLoggedIn(username); + removeLoginProcessArtifacts(req); + loginRedirector.redirectLoggedInUser(req, resp); + } else if (uri != null) { + log.debug("Recognize '' as self-editor for " + uri); + removeLoginProcessArtifacts(req); + loginRedirector.redirectSelfEditingUser(req, resp, uri); + } else { + log.debug("User is not recognized: " + username); + removeLoginProcessArtifacts(req); + loginRedirector.redirectUnrecognizedUser(req, resp, username); + } + } + + private String getAssociatedIndividualUri(String username, + HttpServletRequest req) { + if (username == null) { + return null; + } + VitroRequest vreq = new VitroRequest(req); + WebappDaoFactory wdf = vreq.getWebappDaoFactory(); + return wdf.getIndividualDao().getIndividualURIFromNetId(username); + } + + private void removeLoginProcessArtifacts(HttpServletRequest req) { + LoginProcessBean.removeBean(req); + req.getSession().removeAttribute(ATTRIBUTE_REFERRER); + } + + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + doPost(request, response); + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthSetup.java similarity index 61% rename from webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethSetup.java rename to webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthSetup.java index f54f7e6b5..624a281e0 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginExternalAuthSetup.java @@ -19,69 +19,71 @@ import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean; import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message; /** - * Set up the Shibboleth login process. + * Set up the external authorization process. * * Write down the page that triggered the request, so we can get back to it. * - * Send a request to the Shibboleth server that will return us to the - * LoginShibbolethReturn servlet for further processing. + * Send a request to the external authorization server that will return us to + * the LoginExternalAuthReturn servlet for further processing. */ -public class LoginShibbolethSetup extends BaseLoginServlet { +public class LoginExternalAuthSetup extends BaseLoginServlet { private static final Log log = LogFactory - .getLog(LoginShibbolethSetup.class); + .getLog(LoginExternalAuthSetup.class); /** This session attribute tells where we came from. */ - static final String ATTRIBUTE_REFERRER = LoginShibbolethSetup.class + static final String ATTRIBUTE_REFERRER = LoginExternalAuthSetup.class .getName() + ".referrer"; - private static final String RETURN_SERVLET_URL = "/loginShibbolethReturn"; + private static final String RETURN_SERVLET_URL = "/loginExternalAuthReturn"; /** This http header holds the referring page. */ private static final String HEADING_REFERRER = "referer"; - /** The configuration property that points to the Shibboleth server. */ - private static final String PROPERTY_SHIBBOLETH_SERVER_URL = "shibboleth.server.url"; + /** + * The configuration property that points to the external authorization + * server. + */ + private static final String PROPERTY_EXTERNAL_AUTH_SERVER_URL = "externalAuth.serverUrl"; - /** The complaint we make if there is no Shibbolet server property. */ - private static final Message MESSAGE_NO_SHIBBOLETH_SERVER = new LoginProcessBean.Message( + /** + * The complaint we make if there is no external authorization server + * property. + */ + private static final Message MESSAGE_NO_EXTERNAL_AUTH_SERVER = new LoginProcessBean.Message( "deploy.properties doesn't contain a value for '" - + PROPERTY_SHIBBOLETH_SERVER_URL + "'", + + PROPERTY_EXTERNAL_AUTH_SERVER_URL + "'", LoginProcessBean.MLevel.ERROR); - private String shibbolethServerUrl; + private String extrnalAuthServerUrl; /** Get the configuration property. */ @Override public void init() throws ServletException { - shibbolethServerUrl = ConfigurationProperties - .getProperty(PROPERTY_SHIBBOLETH_SERVER_URL); + extrnalAuthServerUrl = ConfigurationProperties + .getProperty(PROPERTY_EXTERNAL_AUTH_SERVER_URL); } /** * Write down the referring page, record that we are logging in, and - * redirect to the shib server URL. + * redirect to the external authorization server URL. */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - // Record where we came from, so we can get back there. storeTheReferringPage(req); - // If we have no URL for the Shibboleth server, give up. - if (shibbolethServerUrl == null) { - log.debug("No shibboleth server in deploy.properties"); + if (extrnalAuthServerUrl == null) { + log.debug("No external authorization server in deploy.properties"); complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, - MESSAGE_NO_SHIBBOLETH_SERVER); + MESSAGE_NO_EXTERNAL_AUTH_SERVER); return; } - // Record that we are in the process of logging in. LoginProcessBean.getBean(req).setState( LoginProcessBean.State.LOGGING_IN); - // Hand over to Shibboleth. - log.debug("Sending to shibboleth server."); - resp.sendRedirect(buildShibbolethRedirectUrl(req)); + log.debug("Sending to external authorization server."); + resp.sendRedirect(buildExternalAuthRedirectUrl(req)); } /** Remember where we came from - we'll need to go back there. */ @@ -95,15 +97,15 @@ public class LoginShibbolethSetup extends BaseLoginServlet { req.getSession().setAttribute(ATTRIBUTE_REFERRER, referrer); } - /** How do we get to the Shibboleth server and back? */ - private String buildShibbolethRedirectUrl(HttpServletRequest req) { + /** How do we get to the external authorization server and back? */ + private String buildExternalAuthRedirectUrl(HttpServletRequest req) { try { String returnUrl = figureHomePageUrl(req) + RETURN_SERVLET_URL; String encodedReturnUrl = URLEncoder.encode(returnUrl, "UTF-8"); - String shibbolethUrl = shibbolethServerUrl + "?target=" + String externalAuthUrl = extrnalAuthServerUrl + "?target=" + encodedReturnUrl; - log.debug("shibbolethURL is '" + shibbolethUrl + "'"); - return shibbolethUrl; + log.debug("externalAuthUrl is '" + externalAuthUrl + "'"); + return externalAuthUrl; } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); // No UTF-8? Really? } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java index e96138c36..b186cd475 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginRedirector.java @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.List; @@ -23,9 +24,23 @@ import edu.cornell.mannlib.vitro.webapp.controller.Controllers; public class LoginRedirector { private static final Log log = LogFactory.getLog(LoginRedirector.class); + public void redirectSelfEditingUser(HttpServletRequest request, + HttpServletResponse response, String uri) throws IOException { + String userHomePage = assembleUserHomePageUrl(request, uri); + log.debug("Redirecting self-editor to " + userHomePage); + response.sendRedirect(userHomePage); + } + + public void redirectUnrecognizedUser(HttpServletRequest request, + HttpServletResponse response, String username) throws IOException { + log.debug("Redirecting unrecognized user: " + username); + response.sendRedirect(request.getContextPath() + + "/unrecognizedUser?username=" + username); + } + /** *
- * Exit: the user is logged in. They might go to: + * The user is logged in. They might go to: * - A one-time redirect, stored in the session, if they had tried to * bookmark to a page that requires login. * - An application-wide redirect, stored in the servlet context. @@ -68,9 +83,8 @@ public class LoginRedirector { Listuris = getAuthenticator(request) .asWhomMayThisUserEdit(user); if (uris != null && uris.size() > 0) { - String userHomePage = request.getContextPath() - + "/individual?uri=" - + URLEncoder.encode(uris.get(0), "UTF-8"); + String userHomePage = assembleUserHomePageUrl(request, + uris.get(0)); log.debug("User is logged in. Redirect as self-editor to " + userHomePage); response.sendRedirect(userHomePage); @@ -106,7 +120,6 @@ public class LoginRedirector { /** What's the URL for the site admin screen? */ private String getSiteAdminUrl(HttpServletRequest request) { - // return Route.SITE_ADMIN.url(); String contextPath = request.getContextPath(); return contextPath + Controllers.SITE_ADMIN; } @@ -116,4 +129,9 @@ public class LoginRedirector { return Authenticator.getInstance(request); } + private String assembleUserHomePageUrl(HttpServletRequest request, + String uri) throws UnsupportedEncodingException { + return request.getContextPath() + "/individual?uri=" + + URLEncoder.encode(uri, "UTF-8"); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethReturn.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethReturn.java deleted file mode 100644 index e8669a85a..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/LoginShibbolethReturn.java +++ /dev/null @@ -1,116 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller.authenticate; - -import static edu.cornell.mannlib.vitro.webapp.controller.authenticate.LoginShibbolethSetup.ATTRIBUTE_REFERRER; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties; -import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean; -import edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.Message; - -/** - * Handle the return from the Shibboleth login server. If we are successful, - * record the login. Otherwise, display the failure. - */ -public class LoginShibbolethReturn extends BaseLoginServlet { - private static final Log log = LogFactory - .getLog(LoginShibbolethReturn.class); - - /** The configuration property that tells what provider name we expect. */ - private static final String PROPERTY_SHIBBOLETH_PROVIDER = "shibboleth.provider"; - - /** On return froma Shibboleth login, this header holds the provider name. */ - private static final String HEADING_SHIBBOLETH_PROVIDER = "shib-identity-provider"; - - /** On return froma Shibboleth login, this header holds the user name. */ - private static final String HEADING_SHIBBOLETH_USERNAME = "glid"; - - private static final Message MESSAGE_LOGIN_FAILED = new LoginProcessBean.Message( - "Shibboleth login failed.", LoginProcessBean.MLevel.ERROR); - - private static final Message MESSAGE_NO_SUCH_USER = new LoginProcessBean.Message( - "Shibboleth login succeeded, but user {0} is unknown to VIVO.", - LoginProcessBean.MLevel.ERROR); - - private static final Message MESSAGE_NO_SHIBBOLETH_PROVIDER = new LoginProcessBean.Message( - "deploy.properties doesn't contain a value for '" - + PROPERTY_SHIBBOLETH_PROVIDER + "'", - LoginProcessBean.MLevel.ERROR); - - private final LoginRedirector loginRedirector = new LoginRedirector(); - private String shibbolethProvider; - - /** Get the configuration properties. */ - @Override - public void init() throws ServletException { - shibbolethProvider = ConfigurationProperties - .getProperty(PROPERTY_SHIBBOLETH_PROVIDER); - } - - /** - * Returning from the Shibboleth server. If we were successful, the headers - * will contain the Shibboleth provider name and the name of the user who - * just logged in. - * - * We report problems if the provider name is missing or we don't know the - * correct value for it. We also report problems if the username is missing - * or if we don't recognize that user. - * - * If there are no problems, record the login and redirect like we would on - * a normal login. - */ - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - String provider = req.getHeader(HEADING_SHIBBOLETH_PROVIDER); - String user = req.getHeader(HEADING_SHIBBOLETH_USERNAME); - log.debug("Info from Shibboleth: user=" + user + ", provider=" - + provider); - - if ((provider == null) || (user == null)) { - complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, - MESSAGE_LOGIN_FAILED); - } else if (shibbolethProvider == null) { - log.debug("No shibboleth provider in deploy.properties"); - complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, - MESSAGE_NO_SHIBBOLETH_PROVIDER); - } else if (!this.shibbolethProvider.equals(provider)) { - log.error("Wrong shibboleth provider: " + provider); - complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, - MESSAGE_LOGIN_FAILED); - } else if (!getAuthenticator(req).isExistingUser(user)) { - log.debug("No such user: " + user); - complainAndReturnToReferrer(req, resp, ATTRIBUTE_REFERRER, - MESSAGE_NO_SUCH_USER, user); - } else { - log.debug("Logging in as " + user); - recordLoginAndRedirect(req, resp, user); - } - } - - /** Success. Record the login and send them to the appropriate page. */ - private void recordLoginAndRedirect(HttpServletRequest req, - HttpServletResponse resp, String username) - throws UnsupportedEncodingException, IOException { - getAuthenticator(req).recordUserIsLoggedIn(username); - LoginProcessBean.removeBean(req); - req.getSession().removeAttribute(ATTRIBUTE_REFERRER); - loginRedirector.redirectLoggedInUser(req, resp); - } - - @Override - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - doPost(request, response); - } -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/UnrecognizedUserController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/UnrecognizedUserController.java new file mode 100644 index 000000000..1721a46d8 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/authenticate/UnrecognizedUserController.java @@ -0,0 +1,35 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.authenticate; + +import java.util.HashMap; +import java.util.Map; + +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHttpServlet; + +/** + * TODO + */ +public class UnrecognizedUserController extends FreemarkerHttpServlet { + private static final String TEMPLATE_DEFAULT = "unrecognizedUser.ftl"; + private static final String PARAMETER_USERNAME = "username"; + + @Override + protected ResponseValues processRequest(VitroRequest vreq) { + Map body = new HashMap (); + + String username = vreq.getParameter(PARAMETER_USERNAME); + if (username != null) { + body.put("username", username); + } + + return new TemplateResponseValues(TEMPLATE_DEFAULT, body); + } + + @Override + protected String getTitle(String siteName) { + return "Unrecognized user " + siteName; + } + +} diff --git a/webapp/web/templates/freemarker/body/unrecognizedUser.ftl b/webapp/web/templates/freemarker/body/unrecognizedUser.ftl new file mode 100644 index 000000000..105f5e199 --- /dev/null +++ b/webapp/web/templates/freemarker/body/unrecognizedUser.ftl @@ -0,0 +1,15 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#-- Template for the Unrecognized User page. --> + + + Unrecognized user
+ ++ For some reason, there is no individual in VIVO that is associated with your Net ID. + Perhaps you should contact your VIVO administrator. +
+ +
+ Continue +