protected SessionSecurityToken(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                return;

            byte[] cookie = (byte[])info.GetValue(tokenKey, typeof(byte[]));

            if (null == cookie || 0 == cookie.Length)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4272));
            }

            SessionDictionary dictionary = SessionDictionary.Instance;
            //
            // We are creating a reader over the decrypted form of the cookie that is in memory. 
            // Passing Max for the XmlDictionaryReaderQuotas is safe.
            //
            using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(cookie, 0, cookie.Length, dictionary, XmlDictionaryReaderQuotas.Max, null, null))
            {
                //
                // Layout is strict, must be in following order:
                //
                // Version
                // SecureConversationVersion
                // ID
                // ContextID
                // Key
                // Generation {optional}
                // EffectiveTime
                // ExpiryTime
                // KeyEffectiveTime
                // KeyExpiryTime
                //
                // SessionSecurityToken data may follow, in the order:
                //
                bool isSecurityContextSecurityTokenWrapper = false;
                bool isPersistent = true;
                bool isReferenceMode = false;
                string cookieContext = String.Empty;

                if (reader.IsStartElement(dictionary.SecurityContextToken, dictionary.EmptyString))
                {
                    isSecurityContextSecurityTokenWrapper = true;
                }
                else if (reader.IsStartElement(dictionary.SessionToken, dictionary.EmptyString))
                {
                    //@PersistentTrue
                    if (reader.GetAttribute(dictionary.PersistentTrue, dictionary.EmptyString) == null)
                    {
                        isPersistent = false;
                    }

                    if (reader.GetAttribute(dictionary.ReferenceModeTrue, dictionary.EmptyString) != null)
                    {
                        isReferenceMode = true;
                    }

                    reader.ReadFullStartElement();
                    reader.MoveToContent();

                    // <Context>
                    if (reader.IsStartElement(dictionary.Context, dictionary.EmptyString))
                    {
                        cookieContext = reader.ReadElementContentAsString();
                    }
                }
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.SecurityContextToken.Value, reader.Name)));
                }

                string version = reader.ReadElementString();
                if (version != SupportedVersion)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4232, version, SupportedVersion)));
                }

                //
                // SecureConversation Version
                //
                string scNamespace = reader.ReadElementString();
                Uri scVersion;

                if (scNamespace == WSSecureConversationFeb2005Constants.Namespace)
                {
                    scVersion = WSSecureConversationFeb2005Constants.NamespaceUri;
                }
                else if (scNamespace == WSSecureConversation13Constants.Namespace)
                {
                    scVersion = WSSecureConversation13Constants.NamespaceUri;
                }
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4232, version, SupportedVersion)));
                }

                string instanceIdentifier = null;
                if (reader.IsStartElement(dictionary.Id, dictionary.EmptyString))
                {
                    instanceIdentifier = reader.ReadElementString();
                }

                if (string.IsNullOrEmpty(instanceIdentifier))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4239, dictionary.Id.Value)));
                }

                if (!reader.IsStartElement(dictionary.ContextId, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.ContextId.Value, reader.Name)));
                }

                SysUniqueId contextIdentifier = reader.ReadElementContentAsUniqueId();

                if (!reader.IsStartElement(dictionary.Key, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.Key.Value, reader.Name)));
                }
                byte[] key = reader.ReadElementContentAsBase64();

                // optional
                SysUniqueId generation = null;
                if (reader.IsStartElement(dictionary.KeyGeneration, dictionary.EmptyString))
                {
                    generation = reader.ReadElementContentAsUniqueId();
                }

                if (!reader.IsStartElement(dictionary.EffectiveTime, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.EffectiveTime.Value, reader.Name)));
                }
                DateTime effectiveTime = new DateTime(XmlUtil.ReadElementContentAsInt64(reader), DateTimeKind.Utc);

                if (!reader.IsStartElement(dictionary.ExpiryTime, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.ExpiryTime.Value, reader.Name)));
                }
                DateTime expiryTime = new DateTime(XmlUtil.ReadElementContentAsInt64(reader), DateTimeKind.Utc);

                if (!reader.IsStartElement(dictionary.KeyEffectiveTime, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.KeyEffectiveTime.Value, reader.Name)));
                }
                DateTime keyEffectiveTime = new DateTime(XmlUtil.ReadElementContentAsInt64(reader), DateTimeKind.Utc);

                if (!reader.IsStartElement(dictionary.KeyExpiryTime, dictionary.EmptyString))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4230, dictionary.KeyExpiryTime.Value, reader.Name)));
                }
                DateTime keyExpiryTime = new DateTime(XmlUtil.ReadElementContentAsInt64(reader), DateTimeKind.Utc);

                ClaimsPrincipal principal = null;

                if (reader.IsStartElement(dictionary.ClaimsPrincipal, dictionary.EmptyString))
                {
                    principal = ReadPrincipal(reader, dictionary);
                }

                SctAuthorizationPolicy sctAuthorizationPolicy = null;                
                if (reader.IsStartElement(dictionary.SctAuthorizationPolicy, dictionary.EmptyString))
                {
                    reader.ReadStartElement(dictionary.SctAuthorizationPolicy, dictionary.EmptyString);
                    SysClaim sysClaim = DeserializeSysClaim(reader);
                    reader.ReadEndElement();
                    sctAuthorizationPolicy = new SctAuthorizationPolicy(sysClaim);
                }

                string endpointId = null;
                if (reader.IsStartElement(dictionary.EndpointId, dictionary.EmptyString))
                {
                    endpointId = reader.ReadElementContentAsString();
                }

                reader.ReadEndElement();

                _claimsPrincipal = principal;
                _contextId = contextIdentifier;
                _id = instanceIdentifier;
                _context = cookieContext;
                _securityKeys = new ReadOnlyCollection<SecurityKey>(new SecurityKey[] { new InMemorySymmetricSecurityKey(key) });
                _endpointId = endpointId;
                _validFrom = effectiveTime;
                _validTo = expiryTime;
                _keyGeneration = generation;
                _keyEffectiveTime = keyEffectiveTime;
                _keyExpirationTime = keyExpiryTime;
                _isSecurityContextSecurityTokenWrapper = isSecurityContextSecurityTokenWrapper;
                _secureConversationVersion = scVersion;
                _sctAuthorizationPolicy = sctAuthorizationPolicy;
                _isPersistent = isPersistent;
                _isReferenceMode = isReferenceMode;

            }
        }
        /// <summary>
        /// The the purposes of this method are:
        /// 1. To enable layers above to get to the bootstrap tokens
        /// 2. To ensure an ClaimsPrincipal is inside the SCT authorization policies.  This is needed so that
        ///    a CustomPrincipal will be created and can be set.  This is required as we set the principal permission mode to custom 
        /// 3. To set the IAuthorizationPolicy collection on the SCT to be one of IDFx's Authpolicy.        
        /// This allows SCT cookie and SCT cached to be treated the same, futher up the stack.  
        /// 
        /// This method is call AFTER the final SCT has been created and the bootstrap tokens are around.  Itis not called during the SP/TLS nego bootstrap.
        /// </summary>
        /// <param name="sct"></param>
        internal void SetPrincipalBootstrapTokensAndBindIdfxAuthPolicy( SecurityContextSecurityToken sct )
        {
            if ( sct == null )
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull( "sct" );
            }

            List<IAuthorizationPolicy> iaps = new List<IAuthorizationPolicy>();

            //
            // The SecurityContextToken is cached first before the OnTokenIssued is called. So in the Session SCT
            // case the AuthorizationPolicies will have already been updated. So check the sct.AuthorizationPolicies
            // policy to see if the first is a AuthorizationPolicy. 
            //
            if ( ( sct.AuthorizationPolicies != null ) &&
                ( sct.AuthorizationPolicies.Count > 0 ) &&
                ( ContainsEndpointAuthPolicy(sct.AuthorizationPolicies) ) )
            {
                // We have already seen this sct and have fixed up the AuthorizationPolicy
                // collection. Just return.
                return;
            }

            //
            // Nego SCT just has a cookie, there are no IAuthorizationPolicy. In this case,
            // we want to add the EndpointAuthorizationPolicy alone to the SCT.
            //
            if ( ( sct.AuthorizationPolicies != null ) &&
                ( sct.AuthorizationPolicies.Count > 0 ) )
            {
                //
                // Create a principal with known policies.
                //
                AuthorizationPolicy sctAp = IdentityModelServiceAuthorizationManager.TransformAuthorizationPolicies( sct.AuthorizationPolicies,
                                                                                                                     _securityTokenHandlerCollection,
                                                                                                                     false );
                // Replace the WCF authorization policies with our IDFx policies.  
                // The principal is needed later on to set the custom principal by WCF runtime.
                iaps.Add( sctAp );

                //
                // Convert the claim from WCF unconditional policy to an SctAuthorizationPolicy. The SctAuthorizationPolicy simply
                // captures the primary identity claim from the WCF unconditional policy which IdFX will eventually throw away. 
                // If we don't capture that claim, then in a token renewal scenario WCF will fail due to identities being different 
                // for the issuedToken and the renewedToken.
                //
                SysClaim claim = GetPrimaryIdentityClaim( SystemAuthorizationContext.CreateDefaultAuthorizationContext( sct.AuthorizationPolicies ) );

                SctAuthorizationPolicy sctAuthPolicy = new SctAuthorizationPolicy( claim );
                iaps.Add( sctAuthPolicy );
            }

            iaps.Add( new EndpointAuthorizationPolicy( _endpointId ) );
            sct.AuthorizationPolicies = iaps.AsReadOnly();
        }
        /// <summary>
        /// Core ctor with all parameters in their most primitive form.  This constructor is used in deserialization and
        /// when generating a wrapper SessionSecurityToken from a SecurityContextSecurityToken.
        /// </summary>
        /// <param name="contextId">Context identifier</param>
        /// <param name="id">Token identifier</param>
        /// <param name="context">Session context data</param>
        /// <param name="endpointId">The endpoint to which this token is bound. String.Empty would create a unscoped token.</param>
        /// <param name="key">Key material</param>
        /// <param name="validFrom">Start time</param>
        /// <param name="validTo">End time</param>
        /// <param name="keyGeneration">Key Generation identifier</param>
        /// <param name="keyEffectiveTime">Key start time</param>
        /// <param name="keyExpirationTime">Key end time</param>
        /// <param name="authorizationPolicies">Authorization policies</param>
        /// <param name="securityContextSecurityTokenWrapperSecureConversationVersion">The version of
        /// WS-SecureConversation used to generate this SCT.  This should be null if the token is not an SCT wrapper.</param>
        internal SessionSecurityToken(ClaimsPrincipal claimsPrincipal,
                                       SysUniqueId contextId,
                                       string id,
                                       string context,
                                       byte[] key,
                                       string endpointId,
                                       DateTime? validFrom,
                                       DateTime? validTo,
                                       SysUniqueId keyGeneration,
                                       DateTime? keyEffectiveTime,
                                       DateTime? keyExpirationTime,
                                       SctAuthorizationPolicy sctAuthorizationPolicy,
                                       Uri securityContextSecurityTokenWrapperSecureConversationVersion)
            : base()
        {
            if (claimsPrincipal == null || claimsPrincipal.Identities == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("claimsPrincipal");
            }

            if (contextId == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId");
            }

            //
            // validFrom and validTo may not have values.
            // need to set them to reasonable defaults before moving forward.
            // SecurityContextSecurityToken will check the values, but I choose to check
            // here to keep the exception in our stack.
            //

            DateTime validFromEffective;
            DateTime validToEffective;

            if (validFrom.HasValue)
            {
                validFromEffective = DateTimeUtil.ToUniversalTime(validFrom.Value);
            }
            else
            {
                validFromEffective = DateTime.UtcNow;
            }

            if (validTo.HasValue)
            {
                validToEffective = DateTimeUtil.ToUniversalTime(validTo.Value);
            }
            else
            {
                validToEffective = DateTimeUtil.Add(validFromEffective, SessionSecurityTokenHandler.DefaultTokenLifetime);
            }

            if (validFromEffective >= validToEffective)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("validFrom"));
            }

            if (validToEffective < DateTime.UtcNow)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("validTo"));
            }

            if (endpointId == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointId");
            }

            if (!keyEffectiveTime.HasValue)
            {
                keyEffectiveTime = (DateTime?)validFromEffective;
            }

            if (!keyExpirationTime.HasValue)
            {
                keyExpirationTime = (DateTime?)validToEffective;
            }

            if (keyEffectiveTime.Value > keyExpirationTime.Value || keyEffectiveTime.Value < validFromEffective)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("keyEffectiveTime"));
            }

            if (keyExpirationTime.Value > validToEffective)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("keyExpirationTime"));
            }

            if (securityContextSecurityTokenWrapperSecureConversationVersion == null)
            {
                // Not an SCT wrapper: use the default namespace.
                _secureConversationVersion = WSSecureConversation13Constants.NamespaceUri;
            }
            else
            {
                // SCT wrapper: use the provided namespace.
                _isSecurityContextSecurityTokenWrapper = true;
                _secureConversationVersion = securityContextSecurityTokenWrapperSecureConversationVersion;
            }

            if (key == null)
            {
                // We have to create a dummy key here. We are not in WCF and we will
                // never use this key. But this is created only to satisfy WCF's
                // SecurityContextSecurityToken constructor.
                key = CryptoHelper.KeyGenerator.GenerateSymmetricKey(128);
            }

            if (endpointId == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointId");
            }

            _claimsPrincipal = claimsPrincipal;
            _contextId = contextId;
            _id = id;
            _context = context;
            _securityKeys = new ReadOnlyCollection<SecurityKey>(new SecurityKey[] { new InMemorySymmetricSecurityKey(key) });
            _endpointId = endpointId;
            _validFrom = validFrom.Value;
            _validTo = validTo.Value;
            _keyGeneration = keyGeneration;
            _keyEffectiveTime = keyEffectiveTime.Value;
            _keyExpirationTime = keyExpirationTime.Value;
            _sctAuthorizationPolicy = sctAuthorizationPolicy;
        }