SelfIssuedSamlTokenFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / SelfIssuedSamlTokenFactory.cs / 2 / SelfIssuedSamlTokenFactory.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.IO;
    using System.Security.Cryptography; 
    using System.Security.Cryptography.X509Certificates;
    using System.IdentityModel.Tokens;
    using System.IdentityModel.Selectors;
    using System.ServiceModel; 
    using System.ServiceModel.Security;
    using System.ServiceModel.Security.Tokens; 
    using System.Text; 
    using System.Xml;
    using System.Globalization; 

    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace;

 
    //
    // Summary: 
    //  Produces SamlTokens from the locally store claims. 
    //
    internal class SelfIssuedSamlTokenFactory :TokenFactoryBase 
    {


        public static readonly TimeSpan TokenLifetime = new TimeSpan( 1, 0, 0 );//1 hour 
        static readonly SamlSerializer samlSerializer = new SamlSerializer();
 
        // 
        // Assertion ID must start with a letter or "_".
        // It cannot start with a digit. Neither should it contain a ":" 
        // WCF uses "SamlSecurityToken-" as the prefix, doing the same here.
        //
        const string SamlAssertionIdPrefix = "SamlSecurityToken-";
 
        //
        // DigestAlgorithm - for the basic algorithm suites, it is SHA1 
        // 
        const string DefaultDigestAlgorithm = SecurityAlgorithms.Sha1Digest;
 
        //
        // SignatureAlgorithm - SHA1 unless speicified in RST template in recipient policy
        //
        string m_signatureAlgorithm = SecurityAlgorithms.RsaSha1Signature; 

        // 
        // EncryptionAlgorithm - AES 256 CBC unless speicified in RST template in recipient policy 
        //
        string m_encryptionAlgorithm = SecurityAlgorithmSuite.Default.DefaultEncryptionAlgorithm; 


        string m_encryptWithAlgorithm;
 

        string m_keyWrapAlgorithm; 
 

        // 
        // Summary:
        //  Creates an instance of a SelfIssuedTokenFactory
        // Arguments:
        //  connection:     The store connection that the objects 
        //                  are used from.
        // 
        public SelfIssuedSamlTokenFactory() 
        {
        } 

        //
        // Summary:
        //  Generates all token information. 
        //
        // Arguments: 
        //  card:           The infocard whos claims will be used. 
        //  creationParam:  Creation parameters are not supported.  This value must be null.
        //  credential:     This may contain a pin information, if the claims are pin protected. 
        //  policy:         The policy of the recipient
        //
        // Return:
        //  A new TokenDescriptor object containing the generated token information. 
        //
        protected override TokenDescriptor ProduceToken( 
                                            InfoCard card, 
                                            TokenCreationParameter creationParam,
                                            TokenFactoryCredential credential, 
                                            InfoCardPolicy policy,
                                            bool discloseOptional )
        {
            List claims; 
            XmlElement protectedToken;
            DisplayToken displayToken; 
            SamlSecurityToken rawToken; 
            RSACryptoServiceProvider proofKeyOnlyPublic = null;
            SymmetricAlgorithm sessionKey = null; 
            SecurityKeyIdentifier identityKeyIdentifier;
            SecurityKeyIdentifier proofKeyIdentifier;
            SecurityKey proofCryptoInsideSamlToken;
            TokenDescriptor token; 

            if( !String.IsNullOrEmpty( policy.OptionalRstParams.SignatureAlgorithm ) ) 
            { 
                //
                // If this is not supported, Indigo will throw 
                //
                m_signatureAlgorithm = policy.OptionalRstParams.SignatureAlgorithm;
            }
 
            if( !String.IsNullOrEmpty( policy.OptionalRstParams.EncryptionAlgorithm ) )
            { 
                // 
                // EncryptionUtility will throw if this is not supported.
                // 
                m_encryptionAlgorithm = policy.OptionalRstParams.EncryptionAlgorithm;
            }

 

 
            // 
            // We'll check signWith and encryptWith after setting the proof key
            // as it depends on the proof key type. 
            //

            try
            { 
                claims = GetClaimSet( card, policy, discloseOptional );
                List disclosedClaims = new List( claims.Count ); 
                for( int i = 0; i < claims.Count; i++ ) 
                {
                    disclosedClaims.Add( claims[ i ].Id ); 
                }

                //
                // Retrive the asymmetric public keys 
                //
                using( RSACryptoServiceProvider identityKeyOnlyPublic = card.GetPublicCryptography( policy.Recipient.GetIdentifier() ) ) 
                { 

                    identityKeyIdentifier = new SecurityKeyIdentifier( new RsaKeyIdentifierClause( identityKeyOnlyPublic ) ); 

                    //
                    // Generate the proof key and identifier for the SAML subject.
                    // This may be no key (browser case), symmetric, or asymmetric. 
                    //
                    if( SecurityKeyTypeInternal.SymmetricKey == policy.KeyType ) 
                    { 
                        IDT.Assert( policy.ImmediateTokenRecipient is X509RecipientIdentity, "Symmetric key type is not allowed when no certifcate is provided for the token recipeint" );
 
                        m_keyWrapAlgorithm = SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm;
                        IDT.Assert( "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" == m_keyWrapAlgorithm, "What we have chosen" );

                        if( !String.IsNullOrEmpty( policy.OptionalRstParams.EncryptWith ) ) 
                        {
                            m_encryptWithAlgorithm = policy.OptionalRstParams.EncryptWith; 
                        } 
                        else
                        { 
                            m_encryptWithAlgorithm = SecurityAlgorithmSuite.Default.DefaultEncryptionAlgorithm;
                        }

 
                        //
                        // Encrypt the symmetric proof key using key wrap algorithm to the recipient's public key. 
                        // 
                        sessionKey = new RijndaelManaged();
 
                        //
                        // Initialize the suite based on encrypt with so that we can get the
                        // correct symmetric key size.
                        // 
                        SecurityAlgorithmSuite suite;
                        switch( m_encryptWithAlgorithm ) 
                        { 
                            case SecurityAlgorithms.Aes128Encryption:
                                suite = SecurityAlgorithmSuite.Basic128; 
                                break;
                            case SecurityAlgorithms.Aes192Encryption:
                                suite = SecurityAlgorithmSuite.Basic192;
                                break; 
                            case SecurityAlgorithms.Aes256Encryption:
                                suite = SecurityAlgorithmSuite.Basic256; 
                                break; 
                            case SecurityAlgorithms.TripleDesEncryption:
                                suite = SecurityAlgorithmSuite.TripleDes; 
                                break;
                            default:
                                throw IDT.ThrowHelperError( new TokenCreationException(
                                    SR.GetString( SR.UnsupportedEncryptWithAlgorithm, m_encryptWithAlgorithm ) ) ); 
                        }
 
                        // 
                        // Now set the key size
                        // 
                        sessionKey.KeySize = suite.DefaultSymmetricKeyLength;
                        X509SecurityToken wrappingKey = new X509SecurityToken( ( ( X509RecipientIdentity ) policy.ImmediateTokenRecipient).LeafCertificate, Guid.NewGuid().ToString() );
                        SecurityKeyIdentifier wrappingKeyIdentifier = new SecurityKeyIdentifier(
                            wrappingKey.CreateKeyIdentifierClause() ); 

 
                        byte[ ] wrappedKey = wrappingKey.SecurityKeys[ 0 ].EncryptKey( 
                                                m_keyWrapAlgorithm,
                                                sessionKey.Key ); 

                        proofKeyIdentifier = new SecurityKeyIdentifier(
                            new EncryptedKeyIdentifierClause(
                                wrappedKey, 
                                m_keyWrapAlgorithm,
                                wrappingKeyIdentifier ) ); 
 
                        //
                        // Can't use proofKeyIdentifier.CreateKey() - otherwise we get InvalidOperationException 
                        // "This SecurityKeyIdentifier does not have any clause that can create a key.
                        //
                        proofCryptoInsideSamlToken = new InMemorySymmetricSecurityKey( sessionKey.Key );
 
                        ThrowIfProofKeyOperationsNotSupported( policy, proofCryptoInsideSamlToken );
                    } 
                    else if( SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType ) 
                    {
 
                        if( !String.IsNullOrEmpty( policy.OptionalRstParams.EncryptWith ) )
                        {
                            m_encryptWithAlgorithm = policy.OptionalRstParams.EncryptWith;
                        } 
                        else
                        { 
                            m_encryptWithAlgorithm = SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm; 
                        }
 

                        //
                        // This is because RP will probably expect the same
                        // key wrap for decrypting T and for decrypting the Message 
                        //
                        m_keyWrapAlgorithm = m_encryptWithAlgorithm; 
 

                        sessionKey = null; 
                        //
                        // Proof key, per infocard guide:
                        // The subject confirmation key (proof key) specified in the self-issued token should be
                        // treated as a short-term key that can be exercised by the service requester during the 
                        // token validity interval to demonstrate that it is the subject of the token.
                        // So ideally, this should be proofKeyOnlyPublic = new RSACryptoServiceProvider( 1024 ); 
                        // In that case, also dispose that in the finally. 

                        // 
                        // However to prevent overhead of creating a temp RSA key pair, we are using the same public/private
                        // key pair which is the identity key. So proofKeyOnlyPublic is just a dummy variable to illustrate
                        // us passing in the proof key
                        // 
                        proofKeyOnlyPublic = identityKeyOnlyPublic;
 
                        proofKeyIdentifier = new SecurityKeyIdentifier( new RsaKeyIdentifierClause( proofKeyOnlyPublic ) ); 

                        proofCryptoInsideSamlToken = proofKeyIdentifier.CreateKey(); 

                        ThrowIfProofKeyOperationsNotSupported( policy, proofCryptoInsideSamlToken );
                    }
                    else 
                    {
                        m_keyWrapAlgorithm = SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm; 
                        IDT.Assert( "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" == m_keyWrapAlgorithm, "What we have chosen" ); 

                        IDT.Assert( SecurityKeyTypeInternal.NoKey == policy.KeyType, "Bad enum member for SecurityKeyTypeInternal." ); 
                        proofKeyIdentifier = null;
                        proofCryptoInsideSamlToken = null;

                    } 

 
 
                    using( SelfIssuedAuthAsymmetricKey issuerSigningKey = new SelfIssuedAuthAsymmetricKey( card.GetPrivateCryptography( policy.Recipient.GetIdentifier() ) ) )
                    { 
                        Uri recipient = policy.ImmediateTokenRecipient.Address.Uri;

                        if( null != policy.PolicyAppliesTo )
                        { 
                            recipient = policy.PolicyAppliesTo.Uri;
                        } 
 

                        // 
                        // Create the raw SAML token
                        //
                        rawToken = CreateSamlToken( claims, identityKeyIdentifier, proofKeyIdentifier, proofCryptoInsideSamlToken, issuerSigningKey, recipient );
 
                        displayToken = CreateDisplayToken( claims );
 
                        // 
                        // If the immediate token recipient specifies a certificate
                        // then encrypt the token 
                        //
                        X509RecipientIdentity x509Id = policy.ImmediateTokenRecipient as X509RecipientIdentity;
                        if( null != x509Id )
                        { 
                            protectedToken = EncryptionUtility.EncryptSecurityToken(
                                rawToken, 
                                x509Id.LeafCertificate, 
                                m_encryptionAlgorithm,
                                m_keyWrapAlgorithm, 
                                policy.ProtocolVersionProfile );
                        }
                        else
                        { 
                            MemoryStream ms = new MemoryStream();
                            XmlDictionaryWriter xmlwriter = XmlDictionaryWriter.CreateDictionaryWriter( new XmlTextWriter( new StreamWriter( ms ) ) ); 
                            policy.ProtocolVersionProfile.TokenSerializer.WriteToken( xmlwriter, rawToken ); 
                            xmlwriter.Flush();
                            ms.Seek( 0, SeekOrigin.Begin ); 
                            XmlDocument doc = new XmlDocument();
                            protectedToken = (XmlElement)doc.ReadNode( Utility.CreateReaderWithQuotas( ms ) );
                            Array.Clear( ms.GetBuffer(), 0, Convert.ToInt32( ms.Length ) );
                            ms.Close(); 
                        }
 
                    } 
                }
 
                StringWriter writer = new StringWriter( CultureInfo.InvariantCulture );
                policy.ProtocolVersionProfile.TokenSerializer.WriteKeyIdentifierClause( XmlDictionaryWriter.CreateDictionaryWriter(
                                                    new XmlTextWriter( writer ) ),
                                                    new SamlAssertionKeyIdentifierClause( rawToken.Id ) ); 
                writer.Flush();
                string tokenReference = writer.GetStringBuilder().ToString(); 
 
                token = new TokenDescriptor(
                    rawToken.Id, 
                    rawToken.ValidFrom,
                    rawToken.ValidTo,
                    protectedToken,
                    displayToken, 
                    sessionKey,
                    tokenReference, 
                    tokenReference, 
                    disclosedClaims );
 
                //
                // Clear out references whose ownership has been transferred to the TokenDescriptor.
                //
                sessionKey = null; 
                rawToken = null;
            } 
            catch( InfoCardBaseException ) 
            {
                // 
                // Don't need to wrap this again
                //
                throw;
            } 
            catch( Exception e )
            { 
                if( IDT.IsFatal( e ) ) 
                {
                    throw; 
                }

                //
                // In case an asymmetric algorithm or some such is not supported and 
                // SelfIssuedAuthRsaCryptoProvider throw a NotSuppotedException, which gets
                // wrapped by Indigo as InvalidOperationException 
                // This could happen if the recipient specified a supported encryption algorithm 
                // as a SIGNATURE algorithm -- This would pass the IsSupportedAlgorithm check but fail
                // when actually trying to generate the signature. 
                //
                throw IDT.ThrowHelperError(
                           new TokenCreationException( null, e ) );
            } 
            finally
            { 
 

                // 
                // Have to make certain that we dispose of the identity key before leaving if ownership wasn't
                // transferred to the TokenDescriptor.  If we don't dispose of this then the finalizer will run and
                // throw since it will attempt to dispose as the wrong identity.
                // 

                if( null != proofKeyOnlyPublic ) 
                { 
                    //
                    // This should already have been disposed since we are using the 
                    // same key for issuer and proof currently; just doing it for clarity
                    //
                    ( (IDisposable)proofKeyOnlyPublic ).Dispose();
                    proofKeyOnlyPublic = null; 
                }
 
                if( null != sessionKey ) 
                {
                    ( (IDisposable)sessionKey ).Dispose(); 
                    sessionKey = null;
                }
            }
 
            return token;
 
 
        }
 

        void ThrowIfProofKeyOperationsNotSupported( InfoCardPolicy policy, SecurityKey proofCryptoInsideSamlToken )
        {
            // 
            // Check if the proof supports the SignWith algorithm URI.
            // 
            if( !String.IsNullOrEmpty( policy.OptionalRstParams.SignWith ) && 
                 !proofCryptoInsideSamlToken.IsSupportedAlgorithm( policy.OptionalRstParams.SignWith ) )
            { 
                throw IDT.ThrowHelperError(
                    new TokenCreationException(
                        SR.GetString( SR.UnsupportedSignWithAlgorithm, policy.OptionalRstParams.SignWith ) ) );
            } 

            // 
            // Check if the proof supports the EncryptWith algorithm URI. 
            //
            if( !proofCryptoInsideSamlToken.IsSupportedAlgorithm( m_encryptWithAlgorithm ) ) 
            {
                throw IDT.ThrowHelperError(
                    new TokenCreationException(
                        SR.GetString( SR.UnsupportedEncryptWithAlgorithm, m_encryptWithAlgorithm ) ) ); 

            } 
        } 

        // 
        // Summary:
        //  Creates a new SamlSecurityToken object from the list of claims and the subject key.
        //
        // Arguments: 
        //  claims:         The list of Claims to be converted to SamlAssertions.
        //  identityKey:    The derived key that will be used to identify the user. 
        // 
        // Returns:
        //  A new validated SamlSecurityToken object that will expire in TokenLifetime. 
        //
        SamlSecurityToken CreateSamlToken(
                            List claims,
                            SecurityKeyIdentifier issuerKeyIdentifier, 
                            SecurityKeyIdentifier proofKeyIdentifier,
                            SecurityKey proofCryptoInsideSamlToken, 
                            SecurityKey issuerSigningKey, 
                            Uri immediateTokenRecipientUri )
        { 
            SamlConditions conditions;
            SamlSubject subject;
            SamlAttributeStatement subjectStatement;
            List allStatements; 
            List attributes;
            SamlSecurityToken token; 
            DateTime created = DateTime.UtcNow; 

            // 
            // Add audience restriction
            //
            Collection audiences = new Collection();
            audiences.Add( immediateTokenRecipientUri ); 
            SamlAudienceRestrictionCondition samlAudienceRestrictionCondition = new SamlAudienceRestrictionCondition( audiences );
            Collection restrictionCond = new Collection(); 
            restrictionCond.Add( samlAudienceRestrictionCondition ); 
            conditions = new SamlConditions( created,
                                        created.Add( TokenLifetime ), 
                                        restrictionCond );

            string[ ] confirmationMethods = new string[ ] {
                null != proofKeyIdentifier 
                ? SamlConstants.HolderOfKey
                : XmlNames.Saml10.Bearer 
            }; 

            subject = new SamlSubject(  null, 
                                        null,
                                        null,
                                        confirmationMethods,
                                        null, 
                                        proofKeyIdentifier );
 
            if( null != proofCryptoInsideSamlToken ) 
            {
                subject.Crypto = proofCryptoInsideSamlToken; 
            }

            attributes = new List( claims.Count );
            char[ ] delimter = { '/' }; 

 
            for( int i = 0; i < claims.Count; i++ ) 
            {
 

                string[ ] segments = claims[ i ].Id.Split( delimter );
                IDT.ThrowInvalidArgumentConditional( 0 == segments.Length, "claimUri" );
                string attrName = segments[ segments.Length - 1 ]; 

                // 
                // Add specific checks for gender and date of birth claims 
                //
                if( claims[ i ].Id == InfoCardConstants.Gender ) 
                {
                    IDT.Assert( claims[ i ].Value == "0"
                               || claims[ i ].Value == "1"
                               || claims[ i ].Value == "2", "Wrong value type for gender claim, only values '0' (Unspecified), '1' (Male) and '2' (Female) are allowed " ); 
                }
                if( claims[ i ].Id == InfoCardConstants.DateOfBirth ) 
                { 
                    DateTime dob = DateTime.Parse( claims[ i ].Value, CultureInfo.InvariantCulture ).ToUniversalTime();
                    IDT.Assert( null != dob, "Invalid value for date of birth " ); 
                    attributes.Add(
                            new SamlAttribute(
                                XmlNames.WSIdentity.DictionaryUri,
                                attrName, 
                                new string[ ] { XmlConvert.ToString( dob, XmlDateTimeSerializationMode.Utc ) } ) );
                } 
                else 
                {
                    attributes.Add( 
                            new SamlAttribute(
                                XmlNames.WSIdentity.DictionaryUri,
                                attrName,
                                new string[ ] { claims[ i ].ToString() } ) ); 
                }
            } 
 

            subjectStatement = new SamlAttributeStatement( subject, attributes ); 

            allStatements = new List( 1 );
            allStatements.Add( subjectStatement );
 
            SamlAssertion assertion = new SamlAssertion(
                                             SamlAssertionIdPrefix + Guid.NewGuid().ToString(), 
                                             XmlNames.WSIdentity.SelfIssuerUri, 
                                             created,
                                             conditions, 
                                             null,
                                             allStatements
                                             );
 
            if( !issuerSigningKey.IsSupportedAlgorithm( m_signatureAlgorithm ) )
            { 
                throw IDT.ThrowHelperError( 
                    new TokenCreationException(
                        SR.GetString( SR.UnsupportedSignatureAlgorithm, m_signatureAlgorithm ) ) ); 
            }


            // 
            // Set up the signing credentials.
            // Use the RSA key pair from the ledger for signing the token 
            // 
            assertion.SigningCredentials = new SigningCredentials(
                issuerSigningKey, 
                m_signatureAlgorithm,
                DefaultDigestAlgorithm,
                issuerKeyIdentifier );
 
            token = new SamlSecurityToken( assertion );
            return token; 
        } 

 
        //
        // Summary:
        //  Creates a display token from the list of claims that were included in the token.
        // 
        // Arguments:
        //  claims:     This list of claims to add to the display token 
        // 
        // Returns:
        //  A new DisplayToken object with the specified claim values. 
        DisplayToken CreateDisplayToken( List claims )
        {

            List displayClaims = new List(); 

            for( int i = 0; i < claims.Count; i++ ) 
            { 
                List values = new List();
                values.Add( claims[ i ].Value ); 

                DisplayClaim clm = new DisplayClaim(
                    InfoCardConstants.ClaimDisplayTag( claims[ i ].Id.ToString() ),
                    values, 
                    InfoCardConstants.ClaimsDescription( claims[ i ].Id.ToString() ),
                    claims[ i ].Id.ToString() ); 
                displayClaims.Add( clm ); 
            }
            DisplayToken token = new DisplayToken( displayClaims ); 
            return token;
        }

 
        //
        // Summary: 
        //  Gets the intersecting set of claims from the specified InfoCard 
        //
        // Arguments: 
        //  card:             The infocard to extract the claims from.
        //  policy:           Specifies the policy of the relying party or identity provider.
        //  discloseOptional: Specifies whether optional claims are to be disclosed.
        // 
        // Returns:
        //  returns a new collection of InfoCardClaim that were matched from the requiredClaims. 
        // 
        List GetClaimSet( InfoCard card, InfoCardPolicy policy, bool discloseOptional )
        { 
            StoreConnection connection = StoreConnection.GetConnection();
            try
            {
                List intersectedClaims = null; 

                if( null != policy.RequiredClaims ) 
                { 
                    intersectedClaims = new List( policy.RequiredClaims.Length );
 
                    AddClaimsThatIntersect( policy.RequiredClaims, false, card.GetClaims(),
                        policy.ImmediateTokenRecipient.GetOrganizationPPIDIdentifier(), card.Id, intersectedClaims );
                }
 
                if( discloseOptional && null != policy.OptionalClaims )
                { 
                    // 
                    // Check to see if only optional claims were requested.
                    // 
                    if( null == intersectedClaims )
                    {
                        intersectedClaims = new List( policy.OptionalClaims.Length );
                    } 

                    AddClaimsThatIntersect( policy.OptionalClaims, true, card.GetClaims(), 
                        policy.ImmediateTokenRecipient.GetOrganizationPPIDIdentifier(), card.Id, intersectedClaims ); 
                }
 
                return intersectedClaims;
            }
            finally
            { 
                connection.Close();
            } 
        } 

 
        //
        // Summary:
        // Add infocardclaims that intersect with policy to intersectedClaims
        // 
        // Args:
        //    processingOptionalClaims - Whether we are intersecting optional claims or not 
        //    claims - claims we have in the card 
        //    recipientPublicKey - public key of the recipient
        //    cardId - card id 
        //    intersectedClaims - collection to which claims that intersect are added
        //
        // Return value:
        //     Nil (Added claims are passed to intersectedClaims). 
        //
        void AddClaimsThatIntersect( string[ ] policyClaims, 
            bool processingOptionalClaims, 
            InfoCardClaimCollection claims,
            string recipientidentifier, 
            Uri cardId,
            List intersectedClaims )
        {
            foreach( string policyClaim in policyClaims ) 
            {
                string policyClaimUri = policyClaim; 
 
                if( policyClaimUri == InfoCardConstants.PPIDClaimsUri )
                { 
                    String ppidStr = Utility.CreatePpid(
                                         Convert.FromBase64String( recipientidentifier ),
                                         cardId );
 
                    intersectedClaims.Add( new InfoCardClaim(
                                                InfoCardConstants.PPIDClaimsUri, 
                                                ppidStr ) ); 
                }
                else 
                {

                    if( !processingOptionalClaims )
                    { 
                        //
                        // Required claims must have value, asserted by UI code 
                        // 
                        IDT.ThrowInvalidArgumentConditional(
                            !claims.ContainsKey( policyClaimUri ) || 
                            null == claims[ policyClaimUri ] ||
                            String.IsNullOrEmpty( claims[ policyClaimUri ].Value ), "policyClaimUri" );

                        intersectedClaims.Add( claims[ policyClaimUri ] ); 
                    }
                    else 
                    { 

                        InfoCardClaim claim = null; 

                        //
                        // If the policyClaimUri exists in the collection.
                        // 
                        if( claims.ContainsKey( policyClaimUri ) )
                        { 
                            claim = claims[ policyClaimUri ]; 
                        }
 
                        //
                        // Optional claims only sent if there is a value
                        //
                        if( null != claim &&        //InfoCardClaim pointed to by policyClaimUri is not null 
                            !String.IsNullOrEmpty( claim.Value ) )  //The value of the InfoCardClaim
                        //is not null or empty 
                        { 
                            intersectedClaims.Add( claim );
                        } 
                        else
                        {
                            //
                            // do nothing.  Its an optional claim we don't support. 
                            //
                        } 
 
                    }
 

                }
            }
 
        }
 
 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK