001/*
002 *  Copyright 2016 Anyware Services
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 */
016package org.ametys.site;
017
018import java.util.Arrays;
019import java.util.Collection;
020import java.util.List;
021import java.util.Map;
022import java.util.regex.Pattern;
023
024import org.apache.avalon.framework.parameters.Parameters;
025import org.apache.cocoon.environment.ObjectModelHelper;
026import org.apache.cocoon.environment.Redirector;
027import org.apache.cocoon.environment.Request;
028import org.apache.cocoon.environment.Session;
029import org.apache.cocoon.environment.http.HttpCookie;
030import org.apache.http.client.methods.HttpGet;
031import org.apache.http.impl.client.CloseableHttpClient;
032
033import org.ametys.core.authentication.AuthenticateAction;
034import org.ametys.core.authentication.CredentialProvider;
035import org.ametys.core.user.UserIdentity;
036import org.ametys.plugins.site.Site;
037import org.ametys.runtime.config.Config;
038import org.ametys.runtime.workspace.WorkspaceMatcher;
039
040/**
041 * The authenticate action for front side 
042 */
043public class FrontAuthenticateAction extends AuthenticateAction
044{
045    /** url requires for authentication */
046    protected Collection<Pattern> _acceptedSiteUrlPatterns = Arrays.asList(new Pattern[]{Pattern.compile("^plugins/site/authenticate/[0-9]+$")});
047    
048    @Override
049    protected boolean _acceptedUrl(Request request)
050    {
051        // URL without server context and leading slash.
052        String url = (String) request.getAttribute(WorkspaceMatcher.IN_WORKSPACE_URL);
053        for (Pattern pattern : _acceptedSiteUrlPatterns)
054        {
055            if (pattern.matcher(url).matches())
056            {
057                // Anonymous request
058                request.setAttribute(REQUEST_ATTRIBUTE_GRANTED, true);
059
060                return true;
061            }
062        }
063        
064        return false;
065    }
066
067    @Override
068    protected void _setUserIdentityInSession(Request request, UserIdentity userIdentity, CredentialProvider credentialProvider, boolean blockingMode)
069    {
070        setUserIdentityInSession(request, userIdentity, credentialProvider, blockingMode);
071    }
072    
073    /**
074     * Save user identity in request
075     * @param request The request
076     * @param userIdentity The useridentity to save
077     * @param credentialProvider The credential provider used to connect
078     * @param blockingMode The mode used for the credential provider
079     */
080    public static void setUserIdentityInSession(Request request, UserIdentity userIdentity, CredentialProvider credentialProvider, boolean blockingMode)
081    {
082        Site site = (Site) request.getAttribute("site");
083        String siteName = site.getName();
084        
085        Session session = request.getSession(true);
086        _resetConnectingStateToSession(request);
087        session.setAttribute(SESSION_USERIDENTITY + "-" + siteName, userIdentity);
088        session.setAttribute(SESSION_CREDENTIALPROVIDER + "-" + siteName, credentialProvider);
089        session.setAttribute(SESSION_CREDENTIALPROVIDER_MODE + "-" + siteName, blockingMode);
090    }
091    
092    @Override
093    protected UserIdentity _getUserIdentityFromSession(Request request)
094    {
095        return getUserIdentityFromSession(request);
096    }
097    
098    /**
099     * Get the user identity of the connected user from the session 
100     * @param request The request
101     * @return The connected useridentity or null
102     */
103    public static UserIdentity getUserIdentityFromSession(Request request)
104    {
105        Site site = (Site) request.getAttribute("site");
106        String siteName = site.getName();
107        
108        return getUserIdentityFromSession(request, siteName);
109    }
110    
111    /**
112     * Get the user identity of the connected user from the session 
113     * @param request The request
114     * @param siteName The current site name
115     * @return The connected useridentity or null
116     */
117    public static UserIdentity getUserIdentityFromSession(Request request, String siteName)
118    {
119        Session session = request.getSession(false);
120        if (session != null)
121        {
122            return (UserIdentity) session.getAttribute(SESSION_USERIDENTITY + "-" + siteName);
123        }
124        return null;
125    }
126    
127    @Override
128    protected CredentialProvider _getCredentialProviderFromSession(Request request)
129    {
130        return getCredentialProviderFromSession(request);
131    }
132    
133    /**
134     * Get the credential provider used for the current connection
135     * @param request The request 
136     * @return The credential provider used or null
137     */
138    public static CredentialProvider getCredentialProviderFromSession(Request request)
139    {
140        Site site = (Site) request.getAttribute("site");
141        String siteName = site.getName();
142        
143        return getCredentialProviderFromSession(request, siteName);
144    }
145    
146    /**
147     * Get the credential provider used for the current connection
148     * @param request The request 
149     * @param siteName The current site name
150     * @return The credential provider used or null
151     */
152    public static CredentialProvider getCredentialProviderFromSession(Request request, String siteName)
153    {
154        Session session = request.getSession(false);
155        if (session != null)
156        {
157            return (CredentialProvider) session.getAttribute(SESSION_CREDENTIALPROVIDER + "-" + siteName);
158        }
159        return null;
160    }
161    
162    @Override
163    protected Boolean _getCredentialProviderModeFromSession(Request request)
164    {
165        return getCredentialProviderModeFromSession(request);
166    }
167    
168    /**
169     * Get the credential provider mode used for the current connection
170     * @param request The request 
171     * @return The credential provider mode used or null
172     */
173    public static Boolean getCredentialProviderModeFromSession(Request request)
174    {
175        Site site = (Site) request.getAttribute("site");
176        String siteName = site.getName();
177        
178        return getCredentialProviderModeFromSession(request, siteName);
179    }
180    
181    /**
182     * Get the credential provider mode used for the current connection
183     * @param request The request 
184     * @param siteName The current site name
185     * @return The credential provider mode used or null
186     */
187    public static Boolean getCredentialProviderModeFromSession(Request request, String siteName)
188    {
189        Session session = request.getSession(false);
190        if (session != null)
191        {
192            return (Boolean) session.getAttribute(SESSION_CREDENTIALPROVIDER_MODE + "-" + siteName);
193        }
194        return null;
195    }
196    
197    @Override
198    protected List<String> _getContexts(Request request, Parameters parameters)
199    {
200        Site site = (Site) request.getAttribute("site");
201        String siteName = site.getName();
202        return Arrays.asList("/sites/" + siteName, "/sites-fo/" + siteName);
203    }
204
205    @Override
206    protected String getLoginURL(Request request)
207    {
208        Site site = (Site) request.getAttribute("site");
209        String siteName = site.getName();
210        
211        return getLoginURLParameters(request, "cocoon://_generate/plugins/web/frontoffice-formbasedauthentication/login/login/" + siteName);
212    }
213    
214    @Override
215    protected String getLogoutURL(Request request)
216    {
217        Site site = (Site) request.getAttribute("site");
218        String siteName = site.getName();
219        return "cocoon://_generate/plugins/web/frontoffice-formbasedauthentication/login/logout/" + siteName;
220    }
221    
222    @Override
223    protected boolean _handleLogout(Redirector redirector, Map objectModel, String source, Parameters parameters) throws Exception
224    {
225        boolean logout = super._handleLogout(redirector, objectModel, source, parameters);
226        if (logout)
227        {
228            // Additionally we need to destroy potential server side session
229            Request request = ObjectModelHelper.getRequest(objectModel);
230            HttpCookie sessionId = (HttpCookie) request.getCookieMap().get(GeneratePageAction.__BACKOFFICE_JSESSION_ID);
231            if (sessionId != null)
232            {
233                try (CloseableHttpClient httpClient = BackOfficeRequestHelper.getHttpClient())
234                {
235                    String cmsURL = Config.getInstance().getValueAsString("org.ametys.site.bo");
236                    HttpGet httpGet = new HttpGet(cmsURL + "/logout.html");
237                    httpGet.addHeader("Cookie", "JSESSIONID=" + sessionId.getValue());
238                    httpClient.execute(httpGet);
239                }
240            }
241        }
242        return logout;
243    }
244}