73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: SessionID.java,v 1.10 2009/10/02 23:45:42 qcheng Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
aae5a841fc16f04abaab7e36461c1c7e5cf485e1sachiko * Portions Copyrighted 2011-2016 ForgeRock AS.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.iplanet.dpro.session;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.io.ByteArrayOutputStream;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.io.DataOutputStream;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.io.Serializable;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.net.URL;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.security.AccessController;
1c3134bddb7b413373d1668cbc4b7d95c2477667Mark de Reeperimport java.security.NoSuchAlgorithmException;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.security.NoSuchProviderException;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.security.SecureRandom;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport java.util.Map;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport javax.servlet.http.HttpServletRequest;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport org.forgerock.openam.utils.PerThreadCache;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport org.forgerock.openam.utils.StringUtils;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Maddenimport org.forgerock.util.Reject;
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.am.util.SystemProperties;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottimport com.iplanet.dpro.session.service.SessionServerConfig;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.dpro.session.share.SessionEncodeURL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.iplanet.services.naming.WebtopNaming;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottimport com.iplanet.services.util.Crypt;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshottimport com.sun.identity.security.EncodeAction;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.Constants;
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshottimport com.sun.identity.shared.debug.Debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.encode.Base64;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.encode.CookieUtils;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The <code>SessionID</code> class is used to identify a Session object. It
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * contains a random String and the name of the session server. The random
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * String in the Session ID is unique on a given session server.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see com.iplanet.dpro.session.Session
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class SessionID implements Serializable {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public static final String SHANDLE_SCHEME_PREFIX = "shandle:";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String encryptedString = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean comingFromAuth = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String sessionServerProtocol = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String sessionServer = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String sessionServerPort = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String sessionServerURI = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected String sessionDomain = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String sessionServerID = "";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String cookieName = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static Debug debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Boolean cookieMode = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott private transient boolean isParsed = false; // Should not be persisted to enable parsing
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott private transient String tail = null; // Instantiated by SessionID#parseSessionString
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott private transient SessionIDExtensions extensions; // Instantiated by SessionID#parseSessionString
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieName = System.getProperty("com.iplanet.am.cookie.name");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cookieName == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieName = SystemProperties.get("com.iplanet.am.cookie.name");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug = Debug.getInstance("amSession");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott private static final PerThreadCache<SecureRandom, RuntimeException> secureRandom =
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott new PerThreadCache<SecureRandom, RuntimeException>(Integer.MAX_VALUE) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott @Override
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott protected SecureRandom initialValue() {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott try {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott try {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return SecureRandom.getInstance("SHA1PRNG", "SUN");
1c3134bddb7b413373d1668cbc4b7d95c2477667Mark de Reeper } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return SecureRandom.getInstance("SHA1PRNG");
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott } catch (Exception e) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott throw new IllegalStateException("Need SHA1PRNG algorithm to continue");
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott };
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Constructs a <code>SessionID</code> object based on a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>HttpServletRequest</code> object. but if cookie is not found it
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * checks the URL for session ID.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param request <code>HttpServletRequest</code> object which contains
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the encrypted session string.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public SessionID(HttpServletRequest request) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String cookieValue;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cookieName == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieName = SystemProperties.get("com.iplanet.am.cookie.name");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cookieName != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // check if this is a forward from authentication service case.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // if yes, find Session ID in the request URL first, otherwise
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // find Session ID in the cookie first
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi String isForward = (String)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster request.getAttribute(Constants.FORWARD_PARAM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.message("SessionID(HttpServletRequest) : is forward = "
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi + isForward);
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((isForward != null) &&
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster isForward.equals(Constants.FORWARD_YES_VALUE)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String realReqSid = SessionEncodeURL.getSidFromURL(request);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (realReqSid != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster encryptedString = realReqSid;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieValue = CookieUtils
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster .getCookieValueFromReq(request, cookieName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cookieValue != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster encryptedString = cookieValue;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieMode = Boolean.TRUE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieValue = CookieUtils
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster .getCookieValueFromReq(request, cookieName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // if no cookie found in the request then check if
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // the URL has it.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (cookieValue == null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String realReqSid = SessionEncodeURL.getSidFromURL(request);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (realReqSid != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster encryptedString = realReqSid;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieMode = Boolean.FALSE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster cookieMode = Boolean.TRUE;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster encryptedString = cookieValue;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott /**
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott * Creates a default instance of SessionID with a null Session ID.
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott * Note: This function is needed for deserialisation.
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott */
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott public SessionID() {
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott }
71ef1e179613c2e17b9ad5f1c9db6bf533941f9dRobert Wapshott
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Constructs a <code>SessionID</code> object based on a Session ID.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param sid The session ID String in an encrypted format.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public SessionID(String sid) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster encryptedString = sid;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // toString() returns a String that is identical to 'sid'
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Checks if encrypted string is null or empty
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if encrypted string is null or empty.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean isNull() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return isNull(encryptedString);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Utility method to check if argument is null or empty string
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param s string to check
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if <code>s</code> is null or empty.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static boolean isNull(String s) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return s == null || s.length() == 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts * Returns the session server path in this object.
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts *
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts * @return The session server path in this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionServerURI() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull(sessionServerURI)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionServerURI;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts /**
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts * Returns the session server URL in this object.
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts *
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts * @return The session server URL in this object.
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts */
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts public String getSessionServerURL() {
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts parseSessionString();
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts return sessionServerProtocol + "://" + sessionServer + ":" + sessionServerPort + sessionServerURI;
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts }
73db2ddb960cafd7ffb6daf89eb697910d36c56dJames Phillpotts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method returns the boolean representing if this session id
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is a regular auth token, generated via AuthContext API
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and not a restricted one.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The boolean representing if this session id
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is that of a regular auth token, generated via AuthContext API
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean getComingFromAuth() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (debug.messageEnabled()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.message("SessionID.getComingFromAuth():"
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott + "comingFromAuth:" + comingFromAuth);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return comingFromAuth;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method sets the boolean representing if this session id
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is a regular auth token, generated via AuthContext API
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param comingFromAuth boolean representing if the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * token has been generated by AuthContext and is a regular token,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * not restricted one.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void setComingFromAuth(boolean comingFromAuth) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.comingFromAuth = comingFromAuth;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the session server name in this object.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The session server protocol in this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionServerProtocol() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull(sessionServerProtocol)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionServerProtocol;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the session server port in this object
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The session server port in this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionServerPort() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull(sessionServerPort)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionServerPort;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the session server name in this object.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The session server name in this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionServer() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull(sessionServer)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionServer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the domain where this session belongs to.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The session domain name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionDomain() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionDomain;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the session server id in this object.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return The session server id in this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getSessionServerID() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull(sessionServerID)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sessionServerID;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
1f7d36d655f5d4d021b4dd67ca200ac503f5a25ePeter Major * Returns the encrypted session string. By doing so it also makes it possible to use this string representation
1f7d36d655f5d4d021b4dd67ca200ac503f5a25ePeter Major * for serializing/deserializing SessionID objects for session failover.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return An encrypted session string.
1f7d36d655f5d4d021b4dd67ca200ac503f5a25ePeter Major * @see org.forgerock.openam.cts.utils.JSONSerialisation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String toString() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return encryptedString;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Compares this Session ID to the specified object. The result is true if
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and only if the argument is not null and the random string and server
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * name are the same in both objects.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param object the object to compare this Session ID against.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if the Session ID are equal; false otherwise.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public boolean equals(Object object) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (object == null || !(object instanceof SessionID)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SessionID another = (SessionID) object;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return encryptedString.equals(another.encryptedString);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a hash code for this object.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return a hash code value for this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public int hashCode() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Since SessionID is immutable, it's hashCode doesn't change.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return encryptedString.hashCode();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Extracts the server, protocol, port, extensions and tail from Session ID
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void parseSessionString() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // parse only once
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isParsed) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This check is done because the SessionID object is getting created
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with empty sid value. This is a temparory fix. The correct fix for
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * this is, throw a SessionException while creating the SessionID
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (isNull()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new IllegalArgumentException("sid value is null or empty");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
4709b991352c6de69ba02928ed6cbf373ca62ed5jeff.schenk String serverID = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String sidString = encryptedString;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // sidString would have * if it has been c66 encoded
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden if (isC66Encoded()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sidString = c66DecodeCookieString(encryptedString);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int outerIndex = sidString.lastIndexOf("@");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (outerIndex == -1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster isParsed = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String outer = sidString.substring(outerIndex + 1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int tailIndex = outer.indexOf("#");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster tail = outer.substring(tailIndex + 1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (tailIndex != -1) {
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott String extensionPart = outer.substring(0, tailIndex);
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott extensions = new DynamicSessionIDExtensions(new LegacySessionIDExtensions(extensionPart));
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott } else {
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott extensions = new LegacySessionIDExtensions();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott /*
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott * Assigning the SITE_ID to ServerID is counter-intuitive. See {@link SessionID#validate()}
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott * for JavaDoc detailing this arrangement.
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott */
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott serverID = extensions.getSiteID();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (serverID != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setServerID(serverID);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception e) {
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas debug.error("Invalid sessionid format:[" + encryptedString + "]", e);
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas throw new IllegalArgumentException("Invalid sessionid format:[" + encryptedString + "]" + e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster isParsed = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Sets the server info by making a naming request by passing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * its id which is in session id and parses it.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param id ServerID
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void setServerID(String id) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster URL url = new URL(WebtopNaming.getServerFromID(id));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServerID = id;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServerProtocol = url.getProtocol();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServer = url.getHost();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServerPort = String.valueOf(url.getPort());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServerURI = url.getPath();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int idx = sessionServerURI.lastIndexOf('/');
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (idx > 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sessionServerURI = sessionServerURI.substring(0, idx);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster idx = sessionServerURI.lastIndexOf('/');
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception e) {
4709b991352c6de69ba02928ed6cbf373ca62ed5jeff.schenk debug.error("Could not get server info from sessionid: "+id+"]", e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new IllegalArgumentException(
4709b991352c6de69ba02928ed6cbf373ca62ed5jeff.schenk "Invalid server id in session id:["+id+"]" + e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns tail part of session id
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return An opaque tail part of session id
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getTail() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return tail;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the if the cookies are supported.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * @return Boolean object value which is Boolean.<code>TRUE<code> if
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * supported <code>FALSE</code> otherwise
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public Boolean getCookieMode() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return cookieMode;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Retrieves extension value by name Currently used session id extensions
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * are
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>SessionService.SITE_ID</code> server id (from platform server list)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * hosting this session (in failover mode this will be server id of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * load balancer)
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>SessionService.PRIMARY_ID</code>,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>SessionService.SECONDARY_ID</code> used if internal request
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * routing mode is enabled.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return extension.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott public SessionIDExtensions getExtension() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster parseSessionString();
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott return extensions;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Generates properly encoded session id string given the encrypted ID,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * extension map and tail part
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param encryptedID encrypted part of session ID.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param extensions map of session ID extensions.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param tail tail part of session ID (currently used to carry associated
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * HTTP session ID)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return encoded session id string.
3ac8bf29f1a21ecac7307d4e1180cf167fae51c3jeff.schenk * @throws SessionException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott static String makeSessionID(String encryptedID, SessionIDExtensions extensions,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String tail) throws SessionException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster StringBuilder buf = new StringBuilder();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buf.append(encryptedID);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (extensions != null || tail != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buf.append("@");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (extensions != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ByteArrayOutputStream baOut = new ByteArrayOutputStream();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DataOutputStream dataOut = new DataOutputStream(baOut);
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott for (Map.Entry<String, String> entry : extensions.asMap().entrySet()) {
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott dataOut.writeUTF(entry.getKey());
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott dataOut.writeUTF(entry.getValue());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster dataOut.close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buf.append(Base64.encode(baOut.toByteArray()));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buf.append("#");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (tail != null) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster buf.append(tail);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String returnValue = buf.toString();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (c66EncodeCookie()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster returnValue = c66EncodeSidString(returnValue);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return returnValue;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new SessionException(e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Generates encoded session id string which uses the same extensions and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * tail part as prototype session id, but a different encrypted ID. This
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * method is used to generate session handle and restricted token id for a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * given master session id. Related session IDs must share extensions and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * tail information in order for session failover to work properly
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param encryptedID encrypted ID.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param prototype session ID to copy extensions and tail from
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return encoded session id
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws SessionException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static String makeRelatedSessionID(String encryptedID,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SessionID prototype) throws SessionException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster prototype.parseSessionString();
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott return makeSessionID(encryptedID, prototype.getExtension(), prototype.tail);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Checks whether session id needs to be c66 encoded to convert to cookie
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return <code>true</code> if session id needs to be c66 encoded to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * convert to cookie value. Otherwise returns <code>false</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * c66 encoding is opensso specific url safe char66 encoding.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see #c66EncodeSidString(String)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see #c66DecodeCookieString(String)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static boolean c66EncodeCookie() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Boolean.valueOf(
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi SystemProperties.get(Constants.C66_ENCODE_AM_COOKIE,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "false")).booleanValue();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Converts native session id string to opensso specific url safe char66
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * encoded string.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * This is not a general purpose utility.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This is meant only for internal use
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param sidString plain text string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return url safe modifed char66 encoded string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see #c66DecodeCookieString(String)
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Sample session id string:
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * AQIC5wM2LY4SfcxPEcjVKCEI7QdmYvlOZvKZpdEErxVPvx8=@AAJTSQACMDE=#
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * We would replace
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * + with -
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * / with _
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * = with .
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @ with star
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * # with star
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * while reconstucting the original cookie value first occurence of
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * star would be replaced with @ and the subsequent occurunce star would
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * be replaced with #
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String c66EncodeSidString(String sidString) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (sidString == null || sidString.length() == 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return sidString;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int length = sidString.length();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char[] chars = new char[length];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; i < length; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char c = sidString.charAt(i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (c == '+') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '-';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '/') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '_';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '=') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '.';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '@') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '*';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '#') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '*';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = c;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi return new String(chars);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Converts opensso specific url safe char66
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * encoded string to native session id string.
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi * This is not a general purpose utility.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This is meant only for internal use
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param urlEncodedString opensso specific url safe char66 encoded string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return native session id string
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see #c66EncodeSidString(String)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * We would replace
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * - with +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * _ with /
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * . with =
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * first occurence of star with @
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * subsequent occurence of star with #
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static String c66DecodeCookieString(String urlEncodedString) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (urlEncodedString == null || urlEncodedString.length() == 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return urlEncodedString;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int length = urlEncodedString.length();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char[] chars = new char[length];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean firstStar = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; i < length; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char c = urlEncodedString.charAt(i);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (c == '-') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '+';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '_') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '/';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '.') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '=';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if (c == '*') {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (firstStar) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster firstStar = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '@';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = '#';
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster chars[i] = c;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi return new String(chars);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden /**
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden * Determines whether the session ID is c66 encoded or not.
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden *
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden * @return {@code true} if the session ID is non-null and c66-encoded.
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden * @see Constants#C66_ENCODE_AM_COOKIE
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden */
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden public boolean isC66Encoded() {
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden return encryptedString != null && encryptedString.contains("*");
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden }
d6d869d072d090f6e4c1753602340ad2e3e82a52Neil Madden
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public SessionID generateRelatedSessionID(SessionServerConfig serverConfig) throws SessionException {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return new SessionID(SessionID.makeRelatedSessionID(generateEncryptedID(serverConfig), this));
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /**
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @return true if this SessionID actually represents a session handle.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public boolean isSessionHandle() {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return toString().startsWith(SHANDLE_SCHEME_PREFIX);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public String generateSessionHandle(SessionServerConfig serverConfig) throws SessionException {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return SHANDLE_SCHEME_PREFIX + SessionID.makeRelatedSessionID(generateEncryptedID(serverConfig), this);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public static String generateAmCtxID(SessionServerConfig serverConfig) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return Long.toHexString(
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott secureRandom.getInstanceForCurrentThread().nextLong()) +
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott serverConfig.getLocalServerID();
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /**
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Generates new encrypted ID string to be used as part of session id
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott *
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @return emcrypted ID string
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott private static String generateEncryptedID(SessionServerConfig serverConfig) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String r = Long.toHexString(secureRandom.getInstanceForCurrentThread().nextLong());
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott // TODO note that this encryptedID string is kept only
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott // to make this compatible with older Java SDK clients
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott // which knew too much about the structure of the session id
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott // newer clients will mostly treat session id as opaque
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott return AccessController.doPrivileged(new EncodeAction(r + "@"
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + serverConfig.getPrimaryServerID(), Crypt.getHardcodedKeyEncryptor()));
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /**
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * Generates new SessionID
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott *
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott * @param serverConfig Required server configuration
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott * @param domain session domain
aecd370b032812f9eb701ae1b97617c46a57e3d1Gabor Melkvi *
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @return newly generated session id
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @throws SessionException
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden public static SessionID generateSessionID(SessionServerConfig serverConfig, String domain) throws SessionException {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String encryptedID = generateEncryptedID(serverConfig);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott String siteID = serverConfig.getPrimaryServerID();
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden String primaryID = getPrimaryId(serverConfig);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden // AME-129, always set a Storage Key regardless of persisting or not.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden String storageKey = String.valueOf(secureRandom.getInstanceForCurrentThread().nextLong());
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden LegacySessionIDExtensions ext = new LegacySessionIDExtensions(primaryID, siteID, storageKey);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden String sessionID = SessionID.makeSessionID(encryptedID, ext, null);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden return new SessionID(sessionID, serverConfig.getLocalServerID(), domain);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden }
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden /**
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * Generates a new stateless session ID.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden *
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * @param serverConfig Required server configuration.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * @param domain session domain.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * @param jwt the stateless session JWT.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * @return the stateless session ID.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden * @throws SessionException if an error occurs encoding the session ID.
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden */
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden public static SessionID generateStatelessSessionID(SessionServerConfig serverConfig, String domain, String jwt)
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden throws SessionException {
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden Reject.ifNull(jwt);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden String siteID = serverConfig.getPrimaryServerID();
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden String primaryID = getPrimaryId(serverConfig);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden LegacySessionIDExtensions ext = new LegacySessionIDExtensions(primaryID, siteID, null);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden final String sessionId = makeSessionID("", ext, jwt);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden return new SessionID(sessionId, serverConfig.getLocalServerID(), domain);
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden }
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden private static String getPrimaryId(SessionServerConfig serverConfig) {
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott String primaryID = "";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott // AME-129 Required for Automatic Session Failover Persistence
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (serverConfig.isSiteEnabled() &&
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott serverConfig.getLocalServerID() != null &&
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott !serverConfig.getLocalServerID().isEmpty()) {
d0da70ccbba38b773e7a7cc71bc124b06206d201Robert Wapshott
aae5a841fc16f04abaab7e36461c1c7e5cf485e1sachiko primaryID = serverConfig.getLocalServerID();
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden return primaryID;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
997d6667b8c483bf582a231b1b24f84fbe6c8390Neil Madden
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott private SessionID(String sid, String serverID, String domain) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott this(sid);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott setServerID(serverID);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott sessionDomain = domain;
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott /**
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * This method validates that the received session ID points to an existing server ID, and the site ID also
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * corresponds to the server ID found in the session. Within this method two "extensions" are of interest: SITE_ID
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * and PRIMARY_ID. The PRIMARY_ID extension contains the hosting server's ID, but only if the given server belongs
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * to a site. The SITE_ID extension contains either the primary site's ID (if the hosting server belongs to a site)
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * or the hosting server's ID. This method will look at the extensions and make sure that they match up with the
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * naming table of this environment. If there is a problem with the session ID (e.g. the server ID actually points
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * to a primary or secondary site, or if the server ID doesn't actually correlate with the site ID), then a
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * SessionException is thrown in order to prevent forwarding of the received session request. A possible scenario
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * for having such an incorrect session ID would be having multiple OpenAM environments using the same cookie
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * domain and cookie name settings.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott *
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * @throws SessionException If the validation failed, possibly because the provided session ID was malformed or not
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott * created within this OpenAM deployment.
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott */
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott public void validate() throws SessionException {
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott String siteID = getExtension().getSiteID();
1d407e39b7d8f68d9a2b1e178f35fab037d9835aRobert Wapshott String primaryID = getExtension().getPrimaryID();
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String errorMessage = null;
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas if (StringUtils.isEmpty(siteID)) {
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas errorMessage = "Invalid session ID, Site ID is null or empty";
3dc19a5813890ebe9e661118e644a14b7c502225Jon Thomas } else if (primaryID == null) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //In this case by definition the server is not assigned to a site, so we want to ensure that the
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //SITE_ID points to a server
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (!WebtopNaming.isServer(siteID)) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott errorMessage = "Invalid session ID, Site ID \"" + siteID + "\" either points to a non-existent server,"
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + " or to a site";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String realSiteID = WebtopNaming.getSiteID(siteID);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (errorMessage == null && realSiteID != null && !realSiteID.equals(siteID)) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott errorMessage = "Invalid session ID, Site ID \"" + siteID + "\" points to a server, but its "
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + "corresponding site ID is not present in the session ID";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott } else {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //PRIMARY_ID is not null, hence this session belongs to a site, we need to verify that the PRIMARY_ID
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //and the SITE_ID are both correct, and they actually correspond to each other
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (!WebtopNaming.isServer(primaryID)) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott errorMessage = "Invalid session ID, Primary ID \"" + primaryID + "\" either points to a non-existent "
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + "server, or to a site";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott String realSiteID = WebtopNaming.getSiteID(primaryID);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (errorMessage == null) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (realSiteID == null || realSiteID.equals(primaryID)) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //The server from the session doesn't actually belong to a site
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott errorMessage = "Invalid session ID, Primary ID \"" + primaryID + "\" server isn't member of Site "
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + "ID \"" + siteID + "\"";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott } else if (!realSiteID.equals(siteID)) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott //The server from the session actually belongs to a different site
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott errorMessage = "Invalid session ID, Primary ID \"" + primaryID + "\" server doesn't belong"
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott + " to Site ID \"" + siteID + "\"";
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (errorMessage != null) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott if (debug.warningEnabled()) {
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott debug.warning(errorMessage);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott throw new SessionException(errorMessage);
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
35ab1c5bca11317474fe12bdd8d22c17cdaf2697Robert Wapshott }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}