/// <summary> /// Decrpyts a security token from an XML EncryptedData /// </summary> /// <param name="reader">The encrypted token XML reader.</param> /// <returns>A byte array of the contents of the encrypted token</returns> internal byte[] DecryptToken(XmlReader reader) { Requires.NotNull(reader, "reader"); Contract.Ensures(Contract.Result <byte[]>() != null); byte[] securityTokenData; string encryptionAlgorithm; SecurityKeyIdentifier keyIdentifier; bool isEmptyElement; ErrorUtilities.VerifyInternal(reader.IsStartElement(XmlEncryptionStrings.EncryptedData, XmlEncryptionStrings.Namespace), "Expected encrypted token starting XML element was not found."); reader.Read(); // get started // if it's not an encryption method, something is dreadfully wrong. InfoCardErrorUtilities.VerifyInfoCard(reader.IsStartElement(XmlEncryptionStrings.EncryptionMethod, XmlEncryptionStrings.Namespace), InfoCardStrings.EncryptionAlgorithmNotFound); // Looks good, let's grab the alg. isEmptyElement = reader.IsEmptyElement; encryptionAlgorithm = reader.GetAttribute(XmlEncryptionStrings.Algorithm); reader.Read(); if (!isEmptyElement) { while (reader.IsStartElement()) { reader.Skip(); } reader.ReadEndElement(); } // get the key identifier keyIdentifier = WSSecurityTokenSerializer.DefaultInstance.ReadKeyIdentifier(reader); // resolve the symmetric key SymmetricSecurityKey decryptingKey = (SymmetricSecurityKey)SecurityTokenResolver.CreateDefaultSecurityTokenResolver(this.tokens.AsReadOnly(), false).ResolveSecurityKey(keyIdentifier[0]); SymmetricAlgorithm algorithm = decryptingKey.GetSymmetricAlgorithm(encryptionAlgorithm); // dig for the security token data itself. reader.ReadStartElement(XmlEncryptionStrings.CipherData, XmlEncryptionStrings.Namespace); reader.ReadStartElement(XmlEncryptionStrings.CipherValue, XmlEncryptionStrings.Namespace); securityTokenData = Convert.FromBase64String(reader.ReadString()); reader.ReadEndElement(); // CipherValue reader.ReadEndElement(); // CipherData reader.ReadEndElement(); // EncryptedData // decrypto-magic! int blockSizeBytes = algorithm.BlockSize / 8; byte[] iv = new byte[blockSizeBytes]; Buffer.BlockCopy(securityTokenData, 0, iv, 0, iv.Length); algorithm.Padding = PaddingMode.ISO10126; algorithm.Mode = CipherMode.CBC; ICryptoTransform decrTransform = algorithm.CreateDecryptor(algorithm.Key, iv); byte[] plainText = decrTransform.TransformFinalBlock(securityTokenData, iv.Length, securityTokenData.Length - iv.Length); decrTransform.Dispose(); return(plainText); }
/// <summary> /// Token Authentication. Translates the decrypted data into a AuthContext. /// </summary> /// <param name="reader">The token XML reader.</param> /// <param name="audience">The audience that the token must be scoped for. /// Use <c>null</c> to indicate any audience is acceptable.</param> /// <returns> /// The authorization context carried by the token. /// </returns> internal static AuthorizationContext AuthenticateToken(XmlReader reader, Uri audience) { Contract.Ensures(Contract.Result <AuthorizationContext>() != null); // Extensibility Point: // in order to accept different token types, you would need to add additional // code to create an authenticationcontext from the security token. // This code only supports SamlSecurityToken objects. SamlSecurityToken token = WSSecurityTokenSerializer.DefaultInstance.ReadToken(reader, null) as SamlSecurityToken; if (null == token) { throw new InformationCardException("Unable to read security token"); } if (null != token.SecurityKeys && token.SecurityKeys.Count > 0) { throw new InformationCardException("Token Security Keys Exist"); } if (audience == null) { Logger.InfoCard.Warn("SAML token Audience checking will be skipped."); } else { if (token.Assertion.Conditions != null && token.Assertion.Conditions.Conditions != null) { foreach (SamlCondition condition in token.Assertion.Conditions.Conditions) { SamlAudienceRestrictionCondition audienceCondition = condition as SamlAudienceRestrictionCondition; if (audienceCondition != null) { Logger.InfoCard.DebugFormat("SAML token audience(s): {0}", audienceCondition.Audiences.ToStringDeferred()); bool match = audienceCondition.Audiences.Contains(audience); if (!match && Logger.InfoCard.IsErrorEnabled) { Logger.InfoCard.ErrorFormat("Expected SAML token audience of {0} but found {1}.", audience.AbsoluteUri, audienceCondition.Audiences.Select(aud => aud.AbsoluteUri).ToStringDeferred()); } // The token is invalid if any condition is not valid. // An audience restriction condition is valid if any audience // matches the Relying Party. InfoCardErrorUtilities.VerifyInfoCard(match, InfoCardStrings.AudienceMismatch); } } } } var samlAuthenticator = new SamlSecurityTokenAuthenticator( new List <SecurityTokenAuthenticator>( new SecurityTokenAuthenticator[] { new RsaSecurityTokenAuthenticator(), new X509SecurityTokenAuthenticator(), }), MaximumClockSkew); if (audience != null) { samlAuthenticator.AllowedAudienceUris.Add(audience.AbsoluteUri); } return(AuthorizationContext.CreateDefaultAuthorizationContext(samlAuthenticator.ValidateToken(token))); }