001/*
002 * (C) Copyright 2010-2016 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 *     Nuxeo - initial API and implementation
018 */
019package org.nuxeo.ecm.platform.ui.web.auth.cas2;
020
021import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.LOGINCONTEXT_KEY;
022import static org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants.SSO_INITIAL_URL_REQUEST_KEY;
023
024import java.io.IOException;
025import java.security.Principal;
026import java.util.Set;
027
028import javax.security.auth.Subject;
029import javax.security.auth.login.LoginContext;
030import javax.servlet.ServletException;
031import javax.servlet.http.Cookie;
032import javax.servlet.http.HttpServletRequest;
033import javax.servlet.http.HttpServletResponse;
034
035import org.nuxeo.ecm.core.api.NuxeoException;
036import org.nuxeo.ecm.core.api.NuxeoPrincipal;
037import org.nuxeo.ecm.platform.ui.web.auth.NXAuthConstants;
038import org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService;
039import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService;
040import org.nuxeo.ecm.platform.url.api.DocumentView;
041import org.nuxeo.ecm.platform.web.common.exceptionhandling.DefaultNuxeoExceptionHandler;
042import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper;
043import org.nuxeo.runtime.api.Framework;
044
045public class SecurityExceptionHandler extends DefaultNuxeoExceptionHandler {
046
047    public static final String CAS_REDIRECTION_URL = "/cas2.jsp";
048
049    public static final String COOKIE_NAME_LOGOUT_URL = "cookie.name.logout.url";
050
051    Cas2Authenticator cas2Authenticator;
052
053    public SecurityExceptionHandler() {
054    }
055
056    @Override
057    public void handleException(HttpServletRequest request, HttpServletResponse response, Throwable t)
058            throws IOException, ServletException {
059
060        if (response.containsHeader("Cache-Control")) {
061            response.setHeader("Cache-Control", "no-cache");
062        }
063
064        Throwable unwrappedException = ExceptionHelper.unwrapException(t);
065
066        if (!ExceptionHelper.isSecurityError(unwrappedException)
067                && !response.containsHeader(SSO_INITIAL_URL_REQUEST_KEY)) {
068            super.handleException(request, response, t);
069            return;
070        }
071
072        Principal principal = request.getUserPrincipal();
073        if (principal == null) {
074            LoginContext loginContext = (LoginContext) request.getAttribute(LOGINCONTEXT_KEY);
075            Subject subject = loginContext.getSubject();
076            if (subject != null) {
077                Set<Principal> principals = subject.getPrincipals();
078                if (principals != null && !principals.isEmpty()) {
079                    principal = (Principal) principals.toArray()[0];
080                }
081            }
082        }
083        if (principal instanceof NuxeoPrincipal) {
084            NuxeoPrincipal nuxeoPrincipal = (NuxeoPrincipal) principal;
085            // redirect to login than to requested page
086            if (nuxeoPrincipal.isAnonymous()) {
087                response.resetBuffer();
088
089                String urlToReach = getURLToReach(request);
090                Cookie cookieUrlToReach = new Cookie(NXAuthConstants.SSO_INITIAL_URL_REQUEST_KEY, urlToReach);
091                cookieUrlToReach.setPath("/");
092                cookieUrlToReach.setMaxAge(60);
093                response.addCookie(cookieUrlToReach);
094
095                if (!response.isCommitted()) {
096                    request.getRequestDispatcher(CAS_REDIRECTION_URL).forward(request, response);
097                }
098                parameters.getListener().responseComplete();
099                return;
100            }
101        }
102        // go back to default handler
103        super.handleException(request, response, t);
104    }
105
106    protected Cas2Authenticator getCasAuthenticator() {
107        if (cas2Authenticator != null) {
108            return cas2Authenticator;
109        }
110
111        PluggableAuthenticationService service = (PluggableAuthenticationService) Framework.getRuntime().getComponent(
112                PluggableAuthenticationService.NAME);
113        if (service == null) {
114            throw new NuxeoException("Can't initialize Nuxeo Pluggable Authentication Service");
115        }
116
117        cas2Authenticator = (Cas2Authenticator) service.getPlugin("CAS2_AUTH");
118
119        if (cas2Authenticator == null) {
120            throw new NuxeoException("Can't get CAS authenticator");
121        }
122        return cas2Authenticator;
123    }
124
125    protected String getURLToReach(HttpServletRequest request) {
126        DocumentView docView = (DocumentView) request.getAttribute(URLPolicyService.DOCUMENT_VIEW_REQUEST_KEY);
127
128        if (docView != null) {
129            String urlToReach = getURLPolicyService().getUrlFromDocumentView(docView, "");
130
131            if (urlToReach != null) {
132                return urlToReach;
133            }
134        }
135        return request.getRequestURL().toString() + "?" + request.getQueryString();
136    }
137
138    protected URLPolicyService getURLPolicyService() {
139        return Framework.getService(URLPolicyService.class);
140    }
141
142}