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; }