Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-9.4.x-3361-thread-safe-setHandlers

This commit is contained in:
Greg Wilkins 2019-03-21 10:05:24 +11:00
commit a2195e5fe3
12 changed files with 467 additions and 61 deletions

View File

@ -21,6 +21,11 @@ package org.eclipse.jetty.security;
import java.io.Serializable;
import java.util.Set;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Authentication.User;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.UserIdentity.Scope;
@ -95,4 +100,23 @@ public abstract class AbstractUserAuthentication implements User, Serializable
return false;
}
@Override
public Authentication logout (ServletRequest request)
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
{
security.logout(this);
Authenticator authenticator = security.getAuthenticator();
if (authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)authenticator).logout(request);
return new LoggedOutAuthentication((LoginAuthenticator)authenticator);
}
}
return Authentication.UNAUTHENTICATED;
}
}

View File

@ -80,7 +80,7 @@ public interface Authenticator
* @param mandatory True if authentication is mandatory.
* @return An Authentication. If Authentication is successful, this will be a {@link org.eclipse.jetty.server.Authentication.User}. If a response has
* been sent by the Authenticator (which can be done for both successful and unsuccessful authentications), then the result will
* implement {@link org.eclipse.jetty.server.Authentication.ResponseSent}. If Authentication is not manditory, then a
* implement {@link org.eclipse.jetty.server.Authentication.ResponseSent}. If Authentication is not mandatory, then a
* {@link org.eclipse.jetty.server.Authentication.Deferred} may be returned.
*
* @throws ServerAuthException if unable to validate request

View File

@ -0,0 +1,60 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.security;
import javax.servlet.ServletRequest;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
/**
* LoggedOutAuthentication
*
* An Authentication indicating that a user has been previously, but is not currently logged in,
* but may be capable of logging in after a call to Request.login(String,String)
*/
public class LoggedOutAuthentication implements Authentication.NonAuthenticated
{
private LoginAuthenticator _authenticator;
public LoggedOutAuthentication (LoginAuthenticator authenticator)
{
_authenticator = authenticator;
}
@Override
public Authentication login(String username, Object password, ServletRequest request)
{
if (username == null)
return null;
UserIdentity identity = _authenticator.login(username, password, request);
if (identity != null)
{
IdentityService identity_service = _authenticator.getLoginService().getIdentityService();
UserAuthentication authentication = new UserAuthentication("API",identity);
if (identity_service != null)
identity_service.associate(identity);
return authentication;
}
return null;
}
}

View File

@ -581,8 +581,11 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
public void logout(Authentication.User user)
{
LOG.debug("logout {}",user);
if (user == null)
return;
LoginService login_service=getLoginService();
if (login_service!=null)
if (login_service != null)
{
login_service.logout(user.getUserIdentity());
}

View File

@ -40,10 +40,9 @@ public class UserAuthentication extends AbstractUserAuthentication
}
@Override
@Deprecated
public void logout()
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
security.logout(this);
}
}

View File

@ -34,6 +34,8 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.LoggedOutAuthentication;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.Authentication;
@ -66,7 +68,6 @@ public class DeferredAuthentication implements Authentication.Deferred
try
{
Authentication authentication = _authenticator.validateRequest(request,__deferredResponse,true);
if (authentication!=null && (authentication instanceof Authentication.User) && !(authentication instanceof Authentication.ResponseSent))
{
LoginService login_service= _authenticator.getLoginService();
@ -131,6 +132,25 @@ public class DeferredAuthentication implements Authentication.Deferred
}
return null;
}
@Override
public Authentication logout (ServletRequest request)
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
{
security.logout(null);
if (_authenticator instanceof LoginAuthenticator)
{
((LoginAuthenticator)_authenticator).logout(request);
return new LoggedOutAuthentication((LoginAuthenticator)_authenticator);
}
}
return Authentication.UNAUTHENTICATED;
}
/* ------------------------------------------------------------ */
public Object getPreviousAssociation()

View File

@ -192,6 +192,7 @@ public class FormAuthenticator extends LoginAuthenticator
UserIdentity user = super.login(username,password,request);
if (user!=null)
{
HttpSession session = ((HttpServletRequest)request).getSession(true);
Authentication cached=new SessionAuthentication(getAuthMethod(),user,password);
session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
@ -199,7 +200,22 @@ public class FormAuthenticator extends LoginAuthenticator
return user;
}
@Override
public void logout(ServletRequest request)
{
super.logout(request);
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);
if (session == null)
return;
//clean up session
session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
}
/* ------------------------------------------------------------ */
@Override
public void prepareRequest(ServletRequest request)
@ -536,7 +552,8 @@ public class FormAuthenticator extends LoginAuthenticator
}
/* ------------------------------------------------------------ */
/** This Authentication represents a just completed Form authentication.
/**
* This Authentication represents a just completed Form authentication.
* Subsequent requests from the same user are authenticated by the presents
* of a {@link SessionAuthentication} instance in their session.
*/

View File

@ -40,6 +40,8 @@ public abstract class LoginAuthenticator implements Authenticator
protected LoginService _loginService;
protected IdentityService _identityService;
private boolean _renewSession;
protected LoginAuthenticator()
{
@ -63,6 +65,19 @@ public abstract class LoginAuthenticator implements Authenticator
return null;
}
public void logout (ServletRequest request)
{
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession(false);
if (session == null)
return;
session.removeAttribute(Session.SESSION_CREATED_SECURE);
}
@Override
public void setConfiguration(AuthConfiguration configuration)
{

View File

@ -33,18 +33,25 @@ import org.eclipse.jetty.security.AbstractUserAuthentication;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.session.Session;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class SessionAuthentication extends AbstractUserAuthentication implements Serializable, HttpSessionActivationListener, HttpSessionBindingListener
/**
* SessionAuthentication
*
* When a user has been successfully authenticated with some types
* of Authenticator, the Authenticator stashes a SessionAuthentication
* into a HttpSession to remember that the user is authenticated.
*
*/
public class SessionAuthentication extends AbstractUserAuthentication
implements Serializable, HttpSessionActivationListener, HttpSessionBindingListener
{
private static final Logger LOG = Log.getLogger(SessionAuthentication.class);
private static final long serialVersionUID = -4643200685888258706L;
public final static String __J_AUTHENTICATED="org.eclipse.jetty.security.UserIdentity";
private final String _name;
@ -92,23 +99,12 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
}
@Override
@Deprecated
public void logout()
{
if (_session!=null && _session.getAttribute(__J_AUTHENTICATED)!=null)
_session.removeAttribute(__J_AUTHENTICATED);
doLogout();
}
private void doLogout()
{
SecurityHandler security=SecurityHandler.getCurrentSecurityHandler();
if (security!=null)
security.logout(this);
if (_session!=null)
_session.removeAttribute(Session.SESSION_CREATED_SECURE);
}
@Override
public String toString()
{
@ -118,7 +114,6 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
@Override
public void sessionWillPassivate(HttpSessionEvent se)
{
}
@Override
@ -131,18 +126,15 @@ public class SessionAuthentication extends AbstractUserAuthentication implements
}
@Override
@Deprecated
public void valueBound(HttpSessionBindingEvent event)
{
if (_session==null)
{
_session=event.getSession();
}
}
@Override
@Deprecated
public void valueUnbound(HttpSessionBindingEvent event)
{
doLogout();
}
}

View File

@ -34,6 +34,8 @@ import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.servlet.DispatcherType;
import javax.servlet.HttpConstraintElement;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletException;
@ -61,6 +63,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
@ -1053,6 +1056,174 @@ public class ConstraintTest
assertThat(response, startsWith("HTTP/1.1 403"));
assertThat(response, containsString("!role"));
}
/**
* Test Request.login() Request.logout() with FORM authenticator
* @throws Exception
*/
@Test
public void testFormProgrammaticLoginLogout() throws Exception
{
//Test programmatic login/logout within same request:
// login - perform programmatic login that should succeed, next request should be also logged in
// loginfail - perform programmatic login that should fail, next request should not be logged in
// loginfaillogin - perform programmatic login that should fail then another that succeeds, next request should be logged in
// loginlogin - perform successful login then try another that should fail, next request should be logged in
// loginlogout - perform successful login then logout, next request should not be logged in
// loginlogoutlogin - perform successful login then logout then login successfully again, next request should be logged in
_security.setHandler(new ProgrammaticLoginRequestHandler());
_security.setAuthenticator(new FormAuthenticator("/testLoginPage","/testErrorPage",false));
_server.start();
String response;
//login
response = _connector.getResponse("GET /ctx/prog?action=login HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginfail
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginfail HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
if (response.contains("JSESSIONID"))
{
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
}
else
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n\r\n");
assertThat(response, not(containsString("user=admin")));
_server.stop();
//loginfaillogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginfail HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
response = _connector.getResponse("GET /ctx/prog?action=login HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginlogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogin HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=admin"));
_server.stop();
//loginlogout
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogout HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=null"));
_server.stop();
//loginlogoutlogin
_server.start();
response = _connector.getResponse("GET /ctx/prog?action=loginlogoutlogin HTTP/1.0\r\n\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 200 OK"));
assertThat(response, containsString("user=user0"));
_server.stop();
//Test constraint-based login with programmatic login/logout:
// constraintlogin - perform constraint login, followed by programmatic login which should fail (already logged in)
_server.start();
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertThat(response, containsString(" 302 Found"));
assertThat(response, containsString("/ctx/testLoginPage"));
assertThat(response, containsString("JSESSIONID="));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, not(containsString("JSESSIONID=" + session)));
response = _connector.getResponse("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password");
assertThat(response, startsWith("HTTP/1.1 302 "));
assertThat(response, containsString("Location"));
assertThat(response, containsString("/ctx/auth/info"));
assertThat(response, containsString("JSESSIONID="));
assertThat(response, not(containsString("JSESSIONID=" + session)));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?action=constraintlogin HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, startsWith("HTTP/1.1 500 Server Error"));
_server.stop();
// logout - perform constraint login, followed by programmatic logout, which should succeed
_server.start();
response = _connector.getResponse("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertThat(response, containsString(" 302 Found"));
assertThat(response, containsString("/ctx/testLoginPage"));
assertThat(response, containsString("JSESSIONID="));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, not(containsString("JSESSIONID=" + session)));
response = _connector.getResponse("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password");
assertThat(response, startsWith("HTTP/1.1 302 "));
assertThat(response, containsString("Location"));
assertThat(response, containsString("/ctx/auth/info"));
assertThat(response, containsString("JSESSIONID="));
assertThat(response, not(containsString("JSESSIONID=" + session)));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponse("GET /ctx/prog?action=logout HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
response = _connector.getResponse("GET /ctx/prog?x=y HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertThat(response, containsString(" 200 OK"));
assertThat(response, containsString("user=null"));
}
@Test
public void testStrictBasic() throws Exception
@ -1512,6 +1683,72 @@ public class ConstraintTest
}
}
private class ProgrammaticLoginRequestHandler extends AbstractHandler
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
{
baseRequest.setHandled(true);
String action = request.getParameter("action");
if (StringUtil.isBlank(action))
{
response.setStatus(200);
response.setContentType("text/plain; charset=UTF-8");
response.getWriter().println("user="+request.getRemoteUser());
return;
}
else if ("login".equals(action))
{
request.login("admin", "password");
return;
}
else if ("loginfail".equals(action))
{
request.login("admin", "fail");
return;
}
else if ("loginfaillogin".equals(action))
{
try
{
request.login("admin", "fail");
}
catch (ServletException se)
{
request.login("admin", "password");
}
return;
}
else if ("loginlogin".equals(action))
{
request.login("admin", "password");
request.login("foo", "bar");
}
else if ("loginlogout".equals(action))
{
request.login("admin", "password");
request.logout();
}
else if ("loginlogoutlogin".equals(action))
{
request.login("admin", "password");
request.logout();
request.login("user0", "password");
}
else if ("constraintlogin".equals(action))
{
String user = request.getRemoteUser();
request.login("admin", "password");
}
else if ("logout".equals(action))
{
request.logout();
}
else
response.sendError(500);
}
}
private class RoleRefHandler extends HandlerWrapper
{
/* ------------------------------------------------------------ */

View File

@ -45,11 +45,12 @@ public interface Authentication
/* ------------------------------------------------------------ */
/** A successful Authentication with User information.
*/
public interface User extends Authentication
public interface User extends LogoutAuthentication
{
String getAuthMethod();
UserIdentity getUserIdentity();
boolean isUserInRole(UserIdentity.Scope scope,String role);
@Deprecated
void logout();
}
@ -63,31 +64,13 @@ public interface Authentication
HttpServletResponse getHttpServletResponse();
}
/* ------------------------------------------------------------ */
/** A deferred authentication with methods to progress
* the authentication process.
/**
* An authentication that is capable of performing a programmatic login
* operation.
*
*/
public interface Deferred extends Authentication
public interface LoginAuthentication extends Authentication
{
/* ------------------------------------------------------------ */
/** Authenticate if possible without sending a challenge.
* This is used to check credentials that have been sent for
* non-manditory authentication.
* @param request the request
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request);
/* ------------------------------------------------------------ */
/** Authenticate and possibly send a challenge.
* This is used to initiate authentication for previously
* non-manditory authentication.
* @param request the request
* @param response the response
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request,ServletResponse response);
/* ------------------------------------------------------------ */
/** Login with the LOGIN authenticator
@ -98,6 +81,53 @@ public interface Authentication
*/
Authentication login(String username,Object password,ServletRequest request);
}
/**
* An authentication that is capable of performing a programmatic
* logout operation.
*
*/
public interface LogoutAuthentication extends Authentication
{
/* ------------------------------------------------------------ */
/**
* Remove any user information that may be present in the request
* such that a call to getUserPrincipal/getRemoteUser will return null.
*
* @param request the request
* @return NoAuthentication if we successfully logged out
*/
Authentication logout (ServletRequest request);
}
/* ------------------------------------------------------------ */
/** A deferred authentication with methods to progress
* the authentication process.
*/
public interface Deferred extends LoginAuthentication, LogoutAuthentication
{
/* ------------------------------------------------------------ */
/** Authenticate if possible without sending a challenge.
* This is used to check credentials that have been sent for
* non-mandatory authentication.
* @param request the request
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request);
/* ------------------------------------------------------------ */
/** Authenticate and possibly send a challenge.
* This is used to initiate authentication for previously
* non-mandatory authentication.
* @param request the request
* @param response the response
* @return The new Authentication state.
*/
Authentication authenticate(ServletRequest request,ServletResponse response);
}
/* ------------------------------------------------------------ */
@ -127,6 +157,14 @@ public interface Authentication
public interface SendSuccess extends ResponseSent
{
}
/* ------------------------------------------------------------ */
/** After a logout, the authentication reverts to a state
* where it is possible to programmatically log in again.
*/
public interface NonAuthenticated extends LoginAuthentication
{
}
/* ------------------------------------------------------------ */
/** Unauthenticated state.

View File

@ -2432,11 +2432,13 @@ public class Request implements HttpServletRequest
@Override
public void login(String username, String password) throws ServletException
{
if (_authentication instanceof Authentication.Deferred)
if (_authentication instanceof Authentication.LoginAuthentication)
{
_authentication=((Authentication.Deferred)_authentication).login(username,password,this);
if (_authentication == null)
Authentication auth = ((Authentication.LoginAuthentication)_authentication).login(username,password,this);
if (auth == null)
throw new Authentication.Failed("Authentication failed for username '"+username+"'");
else
_authentication = auth;
}
else
{
@ -2448,9 +2450,8 @@ public class Request implements HttpServletRequest
@Override
public void logout() throws ServletException
{
if (_authentication instanceof Authentication.User)
((Authentication.User)_authentication).logout();
_authentication=Authentication.UNAUTHENTICATED;
if (_authentication instanceof Authentication.LogoutAuthentication)
_authentication = ((Authentication.LogoutAuthentication)_authentication).logout(this);
}
/* ------------------------------------------------------------ */