/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.dispatcher;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.olat.admin.user.delete.service.UserDeletionManager;
import org.olat.basesecurity.AuthHelper;
import org.olat.basesecurity.BaseSecurityModule;
import org.olat.core.CoreSpringFactory;
import org.olat.core.dispatcher.Dispatcher;
import org.olat.core.dispatcher.DispatcherModule;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.UserRequestImpl;
import org.olat.core.gui.Windows;
import org.olat.core.gui.components.Window;
import org.olat.core.gui.control.ChiefController;
import org.olat.core.gui.exception.MsgFactory;
import org.olat.core.gui.media.ServletUtil;
import org.olat.core.gui.render.StringOutput;
import org.olat.core.gui.render.URLBuilder;
import org.olat.core.id.Identity;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller;
import org.olat.core.util.StringHelper;
import org.olat.core.util.UserSession;
import org.olat.core.util.WebappHelper;
import org.olat.login.OLATAuthenticationController;
import org.olat.login.auth.OLATAuthManager;
/**
* <h3>Description:</h3>
* Login dispatcher that takes a username and password provided by some HTTP
* parameters to authenticat the user. In case of success the user will be
* redirected to the home, in case of failure, the OLAT loginscreen appears and
* an error message is triggered.
* <p>
* The external form must submit the data using the HTTP POST method. GET is not
* supported to prevent logging of logfiles into apache logfiles or caching in
* proxy servers.
* <p>
* The following parameters are used to transport the data:
* <ul>
* <li>username: username</li>
* <li>password: pwd</li>
* </ul>
* <p>
* The following example will open OLAT in a new window without browser toolbars:
* <br>
* <form
* method="post"
* action="http://office.frentix.com:8080/branch/remotelogin/"
* onsubmit="var olat = window.open('','OLAT','location=no,menubar=no,resizable=yes,toolbar=no,statusbar=no,scrollbars=yes')" olat.focus();"
* target="OLAT">
* <input type="text" name="username">
* <input type="password" name="pwd">
* <button>login</button>
* </form>
* <p>An optional parameter named redirect allow a redirect using a businesspath:
* <input type="hidden" name="redirect" value="/olat/url/RepositoryEntry/917504/CourseNode/81254724902921"/>
* <p>
* Initial Date: 05.08.2008 <br>
*
* @author Florian Gnaegi, frentix GmbH, http://www.frentix.com
*/
public class RemoteLoginformDispatcher implements Dispatcher {
private static final String METHOD_POST = "POST";
private static final String PARAM_USERNAME = "username";
private static final String PARAM_PASSWORD = "pwd";
private static final OLog log = Tracing.createLoggerFor(RemoteLoginformDispatcher.class);
/**
* Tries to login the user with the parameters from the POST request and
* redirects to the home screen in case of success. In case of failure,
* redirects to the login screen.
*
* @param request
* @param response
* @param uriPrefix
*/
@Override
public void execute(HttpServletRequest request, HttpServletResponse response) {
UserRequest ureq = null;
try {
String uriPrefix = DispatcherModule.getLegacyUriPrefix(request);
ureq = new UserRequestImpl(uriPrefix, request, response);
if (! request.getMethod().equals(METHOD_POST)) {
log.warn("Wrong HTTP method, only POST allowed, but current method::" + request.getMethod());
DispatcherModule.redirectToDefaultDispatcher(response);
return;
}
String userName = ureq.getParameter(PARAM_USERNAME);
if (! StringHelper.containsNonWhitespace(userName)) {
log.warn("Missing username parameter, use '" + PARAM_USERNAME + "' to submit the login name");
DispatcherModule.redirectToDefaultDispatcher(response);
return;
}
String pwd = ureq.getParameter(PARAM_PASSWORD);
if ( ! StringHelper.containsNonWhitespace(pwd)) {
log.warn("Missing password parameter, use '" + PARAM_PASSWORD + "' to submit the password");
DispatcherModule.redirectToDefaultDispatcher(response);
return;
}
// Authenticate user
OLATAuthManager olatAuthenticationSpi = CoreSpringFactory.getImpl(OLATAuthManager.class);
Identity identity = olatAuthenticationSpi.authenticate(null, userName, pwd);
if (identity == null) {
log.info("Could not authenticate user '" + userName + "', wrong password or user name");
// redirect to OLAT loginscreen, add error parameter so that the loginform can mark itself as errorfull
String loginUrl = WebappHelper.getServletContextPath() + DispatcherModule.getPathDefault() + "?" + OLATAuthenticationController.PARAM_LOGINERROR + "=true";
DispatcherModule.redirectTo(response, loginUrl);
return;
}
UserSession usess = ureq.getUserSession();
//re-init the activity logger to pass the user session and identity
ThreadLocalUserActivityLoggerInstaller.initUserActivityLogger(request);
//sync over the UserSession Instance to prevent double logins
synchronized (usess) {
// Login user, set up everything
int loginStatus = AuthHelper.doLogin(identity, BaseSecurityModule.getDefaultAuthProviderIdentifier(), ureq);
if (loginStatus == AuthHelper.LOGIN_OK) {
// redirect to authenticated environment
UserDeletionManager.getInstance().setIdentityAsActiv(identity);
final String origUri = request.getRequestURI();
String restPart = origUri.substring(uriPrefix.length());
if(request.getParameter("redirect") != null) {
//redirect parameter like: /olat/url/RepositoryEntry/917504/CourseNode/81254724902921
String redirect = request.getParameter("redirect");
DispatcherModule.redirectTo(response, redirect);
} else if(StringHelper.containsNonWhitespace(restPart)) {
//redirect like: http://www.frentix.com/olat/remotelogin/RepositoryEntry/917504/CourseNode/81254724902921
try {
restPart = URLDecoder.decode(restPart, "UTF8");
} catch (UnsupportedEncodingException e) {
log.error("Unsupported encoding", e);
}
String[] split = restPart.split("/");
assert(split.length % 2 == 0);
String businessPath = "";
for (int i = 0; i < split.length; i=i+2) {
String key = split[i];
if(key != null && key.startsWith("path=")) {
key = key.replace("~~", "/");
}
String value = split[i+1];
businessPath += "[" + key + ":" + value +"]";
}
//UserSession usess = UserSession.getUserSession(request);
usess.putEntryInNonClearedStore(AuthenticatedDispatcher.AUTHDISPATCHER_BUSINESSPATH, businessPath);
String url = getRedirectToURL(usess);
DispatcherModule.redirectTo(response, url);
} else {
//redirect
ServletUtil.serveResource(request, response, ureq.getDispatchResult().getResultingMediaResource());
}
} else if (loginStatus == AuthHelper.LOGIN_NOTAVAILABLE) {
DispatcherModule.redirectToServiceNotAvailable(response);
} else {
// error, redirect to login screen
DispatcherModule.redirectToDefaultDispatcher(response);
}
}
} catch (Throwable th) {
try {
ChiefController msgcc = MsgFactory.createMessageChiefController(ureq, th);
// the controller's window must be failsafe also
msgcc.getWindow().dispatchRequest(ureq, true);
// do not dispatch (render only), since this is a new Window created as
// a result of another window's click.
} catch (Throwable t) {
log.error("Sorry, can't handle this remote login request....", t);
}
}
}
private String getRedirectToURL(UserSession usess) {
Window w = Windows.getWindows(usess).getChiefController().getWindow();
URLBuilder ubu = new URLBuilder("", w.getInstanceId(), String.valueOf(w.getTimestamp()));
StringOutput sout = new StringOutput(30);
ubu.buildURI(sout, null, null);
return WebappHelper.getServletContextPath() + DispatcherModule.PATH_AUTHENTICATED + sout.toString();
}
}