/** * This work was created by participants in the DataONE project, and is * jointly copyrighted by participating institutions in DataONE. For * more information on DataONE, see our web site at http://dataone.org. * * Copyright ${year} * * 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. * * $Id: IdentityServlet.java 16823 2015-11-05 17:05:28Z leinfelder $ */ package org.dataone.portal.servlets; import java.io.IOException; import java.io.PrintWriter; import java.security.PrivateKey; import java.security.cert.X509Certificate; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dataone.client.v2.itk.D1Client; import org.dataone.client.auth.CertificateManager; import org.dataone.configuration.Settings; import org.dataone.portal.PortalCertificateManager; import org.dataone.portal.TokenGenerator; import org.dataone.service.types.v1.Group; import org.dataone.service.types.v1.Person; import org.dataone.service.types.v1.Session; import org.dataone.service.types.v1.Subject; import org.dataone.service.types.v1.SubjectInfo; import org.dataone.service.types.v1.SubjectList; import edu.uiuc.ncsa.myproxy.oa4mp.client.Asset; /** *

Created by Ben Leinfelder
*/ public class IdentityServlet extends HttpServlet { private static Log log = LogFactory.getLog(IdentityServlet.class); public void init(ServletConfig config) throws ServletException { super.init(config); // augment the properties with configured portal properties file String propertiesFile = config.getServletContext().getInitParameter("portal.properties.file"); if (propertiesFile != null) { try { Settings.augmentConfiguration(propertiesFile); } catch (ConfigurationException e) { // report the exception throw new ServletException(e); } } // these will override values specified in the properties file above // set the CN URL based on the context param String cnURL = config.getServletContext().getInitParameter("D1Client.CN_URL"); if (cnURL != null) { Settings.getConfiguration().setProperty("D1Client.CN_URL", cnURL); } // point to the correct client config file String configFile = config.getServletContext().getInitParameter("oa4mp:client.config.file"); if (configFile != null) { PortalCertificateManager.getInstance().setConfigFile(configFile); } // point to the hazelcast config String hzConfig = config.getServletContext().getInitParameter("hazelcast.config"); if (hzConfig != null) { System.setProperty("hazelcast.config", hzConfig); //Settings.getConfiguration().setProperty("hazelcast.config", hzConfig); } } @Override public void destroy() { super.destroy(); // close the log handlers for uiuc try { PortalCertificateManager.getInstance().closeLoggers(); } catch (Exception e) { // all we can do is complain log.error("Could not shutdown the UIUC loggers", e); } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // use the same method handleRequest(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // use the same method handleRequest(request, response); } public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Session session = null; Subject subject = null; X509Certificate certificate = null; // force UTF-8 // see https://redmine.dataone.org/issues/3416 request.setCharacterEncoding("UTF-8"); log.debug("request characterEncoding: " + request.getCharacterEncoding()); //System.out.println("request characterEncoding: " + request.getCharacterEncoding()); // get the certificate, if we have it try { certificate = PortalCertificateManager.getInstance().getCertificate(request); PrivateKey key = PortalCertificateManager.getInstance().getPrivateKey(request); String subjectDN = CertificateManager.getInstance().getSubjectDN(certificate); // set in the D1client/CertMan CertificateManager.getInstance().registerCertificate(subjectDN , certificate, key); // pass this subject in as the Session so that the certificate can be found later in the process session = new Session(); subject = new Subject(); subject.setValue(subjectDN); session.setSubject(subject); } catch (Exception e) { // some actions do not require the client certificate be found via cookie log.warn("Could not find some parameters -- this may present problems for some actions"); } // process the action accordingly String action = request.getParameter("action"); String msg = null; try { if (action.equalsIgnoreCase("registerAccount")) { // gather the information needed for this method Person person = new Person(); String familyName = request.getParameter("familyName"); log.debug("familyName: " + familyName); String givenName = request.getParameterValues("givenName")[0]; log.debug("givenName: " + givenName); String email = request.getParameterValues("email")[0]; log.debug("email: " + email); person.setFamilyName(familyName); person.addEmail(email); person.addGivenName(givenName); person.setSubject(subject); // register Subject retSubject = D1Client.getCN().registerAccount(session, person); msg = "Account registered: " + retSubject.getValue(); } if (action.equalsIgnoreCase("updateAccount")) { // gather the information needed for this method Person person = new Person(); String familyName = request.getParameter("familyName"); log.debug("familyName: " + familyName); //System.out.println("familyName: " + familyName); String givenName = request.getParameterValues("givenName")[0]; log.debug("givenName: " + givenName); //System.out.println("givenName: " + givenName); String email = request.getParameterValues("email")[0]; log.debug("email: " + email); //System.out.println("email: " + email); person.setFamilyName(familyName); person.addEmail(email); person.addGivenName(givenName); person.setSubject(subject); // update Subject retSubject = D1Client.getCN().updateAccount(session, person); msg = "Account updated: " + retSubject.getValue(); } if (action.equalsIgnoreCase("verifyAccount")) { // gather the information needed for this method String subjectParam = request.getParameter("subject"); Subject subjectToVerify = new Subject(); subjectToVerify.setValue(subjectParam); // verify D1Client.getCN().verifyAccount(session, subjectToVerify); msg = "Account verified: " + subjectToVerify.getValue(); } if (action.equalsIgnoreCase("requestMapIdentity")) { // gather the information needed for this method String subjectParam = request.getParameter("subject"); Subject subjectToMap = new Subject(); subjectToMap.setValue(subjectParam); // verify D1Client.getCN().requestMapIdentity(session, subjectToMap); msg = "Account map requested for: " + subjectToMap.getValue(); } if (action.equalsIgnoreCase("confirmMapIdentity")) { // gather the information needed for this method String subjectParam = request.getParameter("subject"); Subject subjectToMap = new Subject(); subjectToMap.setValue(subjectParam); // confirm D1Client.getCN().confirmMapIdentity(session, subjectToMap); msg = "Account map confirmed for: " + subjectToMap.getValue(); } if (action.equalsIgnoreCase("denyMapIdentity")) { // gather the information needed for this method String subjectParam = request.getParameter("subject"); Subject subjectToMap = new Subject(); subjectToMap.setValue(subjectParam); // deny D1Client.getCN().denyMapIdentity(session, subjectToMap); msg = "Account map denied for: " + subjectToMap.getValue(); } if (action.equalsIgnoreCase("removeMapIdentity")) { // gather the information needed for this method String subjectParam = request.getParameter("subject"); Subject subjectToMap = new Subject(); subjectToMap.setValue(subjectParam); // remove D1Client.getCN().removeMapIdentity(session, subjectToMap); msg = "Account mapping removed for: " + subjectToMap.getValue(); } if (action.equalsIgnoreCase("createGroup")) { // gather the information needed for this method String groupNameParam = request.getParameter("groupName"); Subject groupName = new Subject(); groupName.setValue(groupNameParam); Group group = new Group(); group.setSubject(groupName); group.setGroupName(groupNameParam); Subject retSubject = D1Client.getCN().createGroup(session, group); msg = "Group created: " + retSubject.getValue(); } if (action.equalsIgnoreCase("addGroupMembers")) { // gather the information needed for this method String groupNameParam = request.getParameter("groupName"); Subject groupName = new Subject(); groupName.setValue(groupNameParam); String[] membersParam = request.getParameterValues("members"); SubjectList members = new SubjectList(); for (String m: membersParam) { Subject memberSubject = new Subject(); memberSubject.setValue(m); members.addSubject(memberSubject); } // look up existing group to add members to SubjectInfo groupInfo = D1Client.getCN().getSubjectInfo(session, groupName); Group group = groupInfo.getGroup(0); group.getHasMemberList().addAll(members.getSubjectList()); boolean result = D1Client.getCN().updateGroup(session, group); msg = "Members added to group: " + groupName.getValue(); } if (action.equalsIgnoreCase("removeGroupMembers")) { // gather the information needed for this method String groupNameParam = request.getParameter("groupName"); Subject groupName = new Subject(); groupName.setValue(groupNameParam); String[] membersParam = request.getParameterValues("members"); SubjectList members = new SubjectList(); for (String m: membersParam) { Subject memberSubject = new Subject(); memberSubject.setValue(m); members.addSubject(memberSubject); } // look up existing group to remove members from SubjectInfo groupInfo = D1Client.getCN().getSubjectInfo(session, groupName); Group group = groupInfo.getGroup(0); group.getHasMemberList().removeAll(members.getSubjectList()); boolean result = D1Client.getCN().updateGroup(session, group); msg = "Members removed from group: " + groupName.getValue(); } if (action.equalsIgnoreCase("getCookie")) { // we need to return the cookie value so other apps can use it to validate authentication Cookie cookie = PortalCertificateManager.getInstance().getCookie(request); if (cookie != null) { msg = cookie.getValue(); } } if (action.equalsIgnoreCase("getToken")) { // we need to return the token so other apps can use it to validate authentication String userId = session.getSubject().getValue(); String fullName = null; try { Person person = session.getSubjectInfo().getPerson(0); fullName = person.getGivenName(0) + " " + person.getFamilyName(); // TODO: include more details from SubjectInfo in the JWT token? } catch (Exception e) { log.warn(e.getMessage(), e); } String token = TokenGenerator.getInstance().getJWT(userId, fullName); // write the response immediately response.setContentType("text/plain; charset=UTF-8"); PrintWriter pw = response.getWriter(); // just print the plain text for AJAX pw.print(token); pw.flush(); return; } if (action.equalsIgnoreCase("getSubject")) { String token = request.getParameter("token"); if (token != null) { // look up via the token, not the cookie certificate = PortalCertificateManager.getInstance().getCredentials(token).getCertificates()[0]; } // tell them who is logged in with that certificate if (certificate != null) { msg = CertificateManager.getInstance().getSubjectDN(certificate); } } if (action.equalsIgnoreCase("isAuthenticated")) { msg = Boolean.FALSE.toString(); // check for the certificate by token String token = request.getParameter("token"); Asset credentials = PortalCertificateManager.getInstance().getCredentials(token); if (credentials != null && credentials.getCertificates() != null) { msg = Boolean.TRUE.toString(); } } if (action.equalsIgnoreCase("logout")) { // remove the cookie for D1 PortalCertificateManager.getInstance().removeCookie(response); msg = "Logout successful for: " + subject.getValue(); } } catch (Exception e) { // print to response while debugging e.printStackTrace(response.getWriter()); } // is there a non-empty target URL to redirect to? String target = request.getParameter("target"); if (target != null && target.length() > 0) { response.sendRedirect(target); return; } // write the response response.setContentType("text/html; charset=UTF-8"); PrintWriter pw = response.getWriter(); // just print the plain text for AJAX pw.println(msg); pw.flush(); } }