From 5dd35ee70659a9e9d8ecc881909cedff5252d9df Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 8 May 2019 10:20:42 +0200 Subject: [PATCH] Issue #3627 Only renew session id when spnego authentication is fully complete (#3629) * Issue #3627 Only renew session id when spnego authentication is fully complete. Signed-off-by: Jan Bartel --- .../ConfigurableSpnegoAuthenticator.java | 18 ++++++++++++++++++ .../authentication/LoginAuthenticator.java | 13 +++++++++++++ 2 files changed, 31 insertions(+) diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ConfigurableSpnegoAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ConfigurableSpnegoAuthenticator.java index 8a76ad089fe..dc9cd7e1978 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ConfigurableSpnegoAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ConfigurableSpnegoAuthenticator.java @@ -37,6 +37,7 @@ import org.eclipse.jetty.security.SpnegoUserPrincipal; import org.eclipse.jetty.security.UserAuthentication; import org.eclipse.jetty.server.Authentication; import org.eclipse.jetty.server.Authentication.User; +import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -99,6 +100,23 @@ public class ConfigurableSpnegoAuthenticator extends LoginAuthenticator _authenticationDuration = authenticationDuration; } + /** + * Only renew the session id if the user has been fully authenticated, don't + * renew the session for any of the intermediate request/response handshakes. + */ + @Override + public UserIdentity login(String username, Object password, ServletRequest servletRequest) + { + SpnegoUserIdentity user = (SpnegoUserIdentity)_loginService.login(username, password, servletRequest); + if (user != null && user.isEstablished()) + { + Request request = Request.getBaseRequest(servletRequest); + renewSession(request, request == null ? null : request.getResponse()); + } + return user; + } + + @Override public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException { diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java index fd97b2a91e6..66a74773cb6 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java @@ -33,6 +33,7 @@ import org.eclipse.jetty.server.session.Session; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; + public abstract class LoginAuthenticator implements Authenticator { private static final Logger LOG = Log.getLogger(LoginAuthenticator.class); @@ -53,6 +54,18 @@ public abstract class LoginAuthenticator implements Authenticator //empty implementation as the default } + /** + * If the UserIdentity is not null after this method calls {@link LoginService#login(String,Object,ServletRequest)}, it + * is assumed that the user is fully authenticated and we need to change the session id to prevent + * session fixation vulnerability. If the UserIdentity is not necessarily fully + * authenticated, then subclasses must override this method and + * determine when the UserIdentity IS fully authenticated and renew the session id. + * + * @param username the username of the client to be authenticated + * @param password the user's credential + * @param servletRequest the inbound request that needs authentication + * @return + */ public UserIdentity login(String username, Object password, ServletRequest servletRequest) { UserIdentity user = _loginService.login(username, password, servletRequest);