001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.opencmis.bindings; 020 021import java.util.Map; 022 023import javax.security.auth.login.LoginContext; 024import javax.security.auth.login.LoginException; 025import javax.servlet.http.HttpServletRequest; 026import javax.xml.ws.handler.MessageContext; 027import javax.xml.ws.handler.MessageContext.Scope; 028import javax.xml.ws.handler.soap.SOAPMessageContext; 029 030import org.apache.chemistry.opencmis.commons.enums.CmisVersion; 031import org.apache.chemistry.opencmis.commons.server.CallContext; 032import org.apache.chemistry.opencmis.server.impl.webservices.AbstractService; 033import org.apache.chemistry.opencmis.server.impl.webservices.CmisWebServicesServlet; 034import org.apache.chemistry.opencmis.server.shared.CsrfManager; 035import org.apache.commons.logging.Log; 036import org.apache.commons.logging.LogFactory; 037import org.nuxeo.runtime.api.Framework; 038import org.nuxeo.runtime.api.login.Authenticator; 039 040/** 041 * SOAP handler that extracts authentication information from the SOAP headers and propagates it to Nuxeo for login. 042 */ 043public class NuxeoCmisAuthHandler extends CXFAuthHandler implements LoginProvider { 044 045 public static final String NUXEO_LOGIN_CONTEXT = "nuxeo.opencmis.LoginContext"; 046 047 private static final Log log = LogFactory.getLog(NuxeoCmisAuthHandler.class); 048 049 protected LoginProvider loginProvider; 050 051 protected CsrfManager csrfManager = new CsrfManager(null, null); // TODO configure CSRF token 052 053 @Override 054 public boolean handleMessage(SOAPMessageContext context) { 055 boolean res = super.handleMessage(context); 056 057 HttpServletRequest request = (HttpServletRequest) context.get(MessageContext.SERVLET_REQUEST); 058 request.setAttribute(CmisWebServicesServlet.CMIS_VERSION, CmisVersion.CMIS_1_1); 059 request.setAttribute(CmisWebServicesServlet.CSRF_MANAGER, csrfManager); 060 061 @SuppressWarnings("unchecked") 062 Map<String, String> callContextMap = (Map<String, String>) context.get(AbstractService.CALL_CONTEXT_MAP); 063 if (callContextMap != null) { 064 // login to Nuxeo 065 String username = callContextMap.get(CallContext.USERNAME); 066 String password = callContextMap.get(CallContext.PASSWORD); 067 try { 068 LoginContext loginContext = getLoginProvider().login(username, password); 069 // store in message context, for later logout 070 context.put(NUXEO_LOGIN_CONTEXT, loginContext); 071 context.setScope(NUXEO_LOGIN_CONTEXT, Scope.APPLICATION); 072 } catch (LoginException e) { 073 throw new RuntimeException("Login failed for user '" + username + "'", e); 074 } 075 } 076 return res; 077 } 078 079 @Override 080 public void close(MessageContext context) { 081 LoginContext loginContext = (LoginContext) context.get(NUXEO_LOGIN_CONTEXT); 082 if (loginContext != null) { 083 try { 084 loginContext.logout(); 085 } catch (LoginException e) { 086 log.error("Cannot logout", e); 087 } 088 } 089 super.close(context); 090 } 091 092 protected LoginProvider getLoginProvider() { 093 if (loginProvider == null) { 094 loginProvider = this; 095 String className = Framework.getProperty(LoginProvider.class.getName()); 096 if (className != null) { 097 try { 098 Object instance = Class.forName(className).newInstance(); 099 if (instance instanceof LoginProvider) { 100 loginProvider = (LoginProvider) instance; 101 } else { 102 log.error(className + " is not an instance of " + LoginProvider.class.getName()); 103 } 104 } catch (ReflectiveOperationException e) { 105 log.error(e); 106 } 107 } 108 } 109 return loginProvider; 110 } 111 112 // LoginProvider 113 @Override 114 public LoginContext login(String username, String password) { 115 try { 116 // check identity against UserManager 117 if (!getAuthenticator().checkUsernamePassword(username, password)) { 118 throw new RuntimeException("Authentication failed for user '" + username + "'"); 119 } 120 // login to Nuxeo framework 121 return Framework.login(username, password); 122 } catch (LoginException e) { 123 throw new RuntimeException("Login failed for user '" + username + "'", e); 124 } 125 } 126 127 protected static Authenticator getAuthenticator() { 128 return Framework.getService(Authenticator.class); 129 } 130 131}