Skip to content

Commit

Permalink
fix:[CO-440] properly de-register authToken
Browse files Browse the repository at this point in the history
- properly remove account AuthToken to invalidate the session cookie
in Soap EndSession
  • Loading branch information
keshavbhatt committed Nov 16, 2022
1 parent f2238fa commit d21c91d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 77 deletions.
5 changes: 3 additions & 2 deletions store/src/java/com/zimbra/cs/account/ZimbraAuthToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import com.google.common.base.MoreObjects;
import com.zimbra.common.account.Key.AccountBy;
import com.zimbra.common.account.ZAttrProvisioning;
import com.zimbra.common.auth.ZAuthToken;
import com.zimbra.common.localconfig.LC;
import com.zimbra.common.service.ServiceException;
Expand Down Expand Up @@ -334,8 +335,8 @@ public void deRegister() throws AuthTokenException {
Account acct = Provisioning.getInstance().getAccountById(properties.getAccountId());
if (acct != null) {
acct.removeAuthTokens(
String.valueOf(properties.getTokenID()), properties.getServerVersion());
if (acct.getBooleanAttr(Provisioning.A_zimbraLogOutFromAllServers, false)) {
String.valueOf(properties.getTokenID()), String.valueOf(properties.getServerVersion()));
if (acct.getBooleanAttr(ZAttrProvisioning.A_zimbraLogOutFromAllServers, false)) {
AuthTokenRegistry.addTokenToQueue(this);
}
}
Expand Down
154 changes: 79 additions & 75 deletions store/src/java/com/zimbra/cs/service/account/EndSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,6 @@

package com.zimbra.cs.service.account;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zimbra.common.service.ServiceException;
import com.zimbra.common.soap.AccountConstants;
import com.zimbra.common.soap.Element;
Expand All @@ -28,82 +19,95 @@
import com.zimbra.soap.SoapServlet;
import com.zimbra.soap.ZimbraSoapContext;
import com.zimbra.soap.account.message.EndSessionRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* End the current session immediately cleaning up all resources used by the session
* including the notification buffer and logging the session out from IM if applicable
* End the current session immediately cleaning up all resources used by the session including the
* notification buffer and logging the session out from IM if applicable
*/
public class EndSession extends AccountDocumentHandler {

@Override
public Element handle(Element request, Map<String, Object> context)
throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
EndSessionRequest req = JaxbUtil.elementToJaxb(request);
String sessionId = req.getSessionId();
boolean clearCookies = req.isLogOff();
boolean clearAllSessions = req.isClearAllSoapSessions();
boolean excludeCurrrentSession = req.isExcludeCurrentSession();
Account account = getAuthenticatedAccount(zsc);
@Override
public Element handle(Element request, Map<String, Object> context) throws ServiceException {
ZimbraSoapContext zsc = getZimbraSoapContext(context);
EndSessionRequest req = JaxbUtil.elementToJaxb(request);
String sessionId = req.getSessionId();
final boolean clearCookies = req.isLogOff();
final boolean clearAllSessions = req.isClearAllSoapSessions();
final boolean excludeCurrentSession = req.isExcludeCurrentSession();
Account account = getAuthenticatedAccount(zsc);

if (clearAllSessions) {
String currentSessionId = null;
if (excludeCurrrentSession && zsc.hasSession()) {
Session currentSession = getSession(zsc);
currentSessionId = currentSession.getSessionId();
}
Collection<Session> sessionCollection = SessionCache.getSoapSessions(account.getId());
if (sessionCollection != null) {
List<Session> sessions = new ArrayList<Session>(sessionCollection);
Iterator<Session> itr = sessions.iterator();
while (itr.hasNext()) {
Session session = itr.next();
itr.remove();
clearSession(session, currentSessionId);
}
}
} else if (!StringUtil.isNullOrEmpty(sessionId)) {
Session s = SessionCache.lookup(sessionId, account.getId());
if (s == null) {
throw ServiceException.FAILURE("Failed to find session with given sessionId", null);
} else {
clearSession(s, null);
}
} else {
if (zsc.hasSession()) {
Session s = getSession(zsc);
endSession(s);
}
if (clearCookies || account.isForceClearCookies()) {
context.put(SoapServlet.INVALIDATE_COOKIES, true);
try {
AuthToken at = zsc.getAuthToken();
HttpServletRequest httpReq = (HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
HttpServletResponse httpResp = (HttpServletResponse) context.get(SoapServlet.SERVLET_RESPONSE);
at.encode(httpReq, httpResp, true);
at.deRegister();
} catch (AuthTokenException e) {
throw ServiceException.FAILURE("Failed to de-register an auth token", e);
}
}
if (clearAllSessions) {
clearAllSessions(zsc, excludeCurrentSession, account);
} else if (!StringUtil.isNullOrEmpty(sessionId)) {
Session s = SessionCache.lookup(sessionId, account.getId());
if (s == null) {
throw ServiceException.FAILURE("Failed to find session with given sessionId", null);
} else {
clearSession(s, null);
}
} else {
if (zsc.hasSession()) {
Session s = getSession(zsc);
endSession(s);
}
if (clearCookies || account.isForceClearCookies()) {
context.put(SoapServlet.INVALIDATE_COOKIES, true);
try {
AuthToken at = zsc.getAuthToken();
HttpServletRequest httpReq =
(HttpServletRequest) context.get(SoapServlet.SERVLET_REQUEST);
HttpServletResponse httpResp =
(HttpServletResponse) context.get(SoapServlet.SERVLET_RESPONSE);
at.encode(httpReq, httpResp, true);
at.deRegister();
} catch (AuthTokenException e) {
throw ServiceException.FAILURE("Failed to de-register an auth token", e);
}
}
}

return zsc.createElement(AccountConstants.END_SESSION_RESPONSE);
}

Element response = zsc.createElement(AccountConstants.END_SESSION_RESPONSE);
return response;
private void clearAllSessions(
final ZimbraSoapContext zsc, boolean excludeCurrentSession, Account account)
throws ServiceException {
String currentSessionId = null;
if (excludeCurrentSession && zsc.hasSession()) {
Session currentSession = getSession(zsc);
currentSessionId = currentSession.getSessionId();
}
Collection<Session> sessionCollection = SessionCache.getSoapSessions(account.getId());
if (sessionCollection != null) {
List<Session> sessions = new ArrayList<>(sessionCollection);
Iterator<Session> itr = sessions.iterator();
while (itr.hasNext()) {
Session session = itr.next();
itr.remove();
clearSession(session, currentSessionId);
}
}
}

private void clearSession(Session session, String currentSessionId) throws ServiceException {
if(session instanceof SoapSession && !session.getSessionId().equalsIgnoreCase(currentSessionId)) {
AuthToken at = ((SoapSession) session).getAuthToken();
if (at != null) {
try {
at.deRegister();
} catch (AuthTokenException e) {
throw ServiceException.FAILURE("Failed to de-register an auth token", e);
}
}
endSession(session);
private void clearSession(Session session, String currentSessionId) throws ServiceException {
if (session instanceof SoapSession
&& !session.getSessionId().equalsIgnoreCase(currentSessionId)) {
AuthToken at = ((SoapSession) session).getAuthToken();
if (at != null) {
try {
at.deRegister();
} catch (AuthTokenException e) {
throw ServiceException.FAILURE("Failed to de-register an auth token", e);
}
}
endSession(session);
}

}
}

0 comments on commit d21c91d

Please sign in to comment.