001/* 002 * Copyright 2020 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.plugins.mobileapp.action; 017 018import java.io.IOException; 019import java.util.Map; 020 021import org.apache.avalon.framework.service.ServiceException; 022import org.apache.avalon.framework.service.ServiceManager; 023import org.apache.cocoon.environment.Request; 024import org.apache.excalibur.source.SourceResolver; 025 026import org.ametys.core.authentication.AuthenticateAction; 027import org.ametys.core.authentication.CredentialProvider; 028import org.ametys.core.user.UserIdentity; 029import org.ametys.core.user.population.UserPopulation; 030import org.ametys.plugins.core.impl.authentication.FormCredentialProvider; 031 032/** 033 * Authenticates a user based on login and password form parameters. 034 */ 035public class GetTokenFromFormAction extends AbstractGetTokenAction 036{ 037 private SourceResolver _sourceResolver; 038 039 @Override 040 public void service(ServiceManager smanager) throws ServiceException 041 { 042 super.service(smanager); 043 _sourceResolver = (SourceResolver) smanager.lookup(SourceResolver.class.getName()); 044 } 045 046 @Override 047 protected UserIdentity tryConnect(Map<String, Object> params, Request request, String context, UserPopulation userPopulation, CredentialProvider credentialProvider, int credentialProviderIndex) 048 { 049 if (credentialProvider instanceof FormCredentialProvider) 050 { 051 try 052 { 053 String login = (String) getParameter("login", params, request); 054 String password = (String) getParameter("password", params, request); 055 056 request.setAttribute(AuthenticateAction.REQUEST_ATTRIBUTE_AUTHENTICATED, "false"); 057 058 // To respect RFC we should encode each parameter using URIUtils.encodeParameter 059 // But in internal request, the org.apache.cocoon.environment.wrapper.RequestParameters#parseName method is badly implemented and does not support UTF-8 encoding. 060 // For example the £ character is encoded as %C2%A3 but the parseName method will decode it as ã. So we have to encode the parameters using a very partial encoding. 061 // This partial encoding could be ISO-8859-1, but as we stay in java, we only need to encode & and = characters. 062 // This hack should be removed when the RUNTIME-4357 would be fixed 063 064 String loginParameters = "Username=" + _veryPartialEncode(login); 065 loginParameters += "&Password=" + _veryPartialEncode(password); 066 loginParameters += "&UserPopulation=" + _veryPartialEncode(userPopulation.getId()); 067 loginParameters += "&CredentialProviderIndex=" + credentialProviderIndex; 068 loginParameters += "&context=" + _veryPartialEncode(context); 069 070 _sourceResolver.resolveURI("cocoon:/authenticate?" + loginParameters); 071 072 return _currentUserProvider.getUser(); 073 } 074 catch (IOException e) 075 { 076 getLogger().error("Impossible to test logins on population '" + userPopulation.getId() + "' using credential provider at position '" + credentialProviderIndex + "'"); 077 } 078 } 079 080 return null; 081 } 082 083 private String _veryPartialEncode(String value) 084 { 085 return value.replace("&", "%26").replace("=", "%3D"); 086 } 087 088}