none
The security protocol cannot verify the incoming message with Saml Assertion token. RRS feed

  • Question

  • The security protocol cannot verify the incoming message with Saml Assertion token.

    I am trying to receive HTTPS SOAP reqest secured with Saml Assertion 1.1 Binary Security Token issued by my own custom STS. The following exception occurred in System.ServiceModel.Security.ReceiveSecurityHeader.VerifySupportingToken(TokenTracker tracker):

    <Exception><ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The supporting token provided for parameters 'System.ServiceModel.Security.Tokens.IssuedSecurityTokenParameters:
    InclusionMode: AlwaysToRecipient
    ReferenceStyle: Internal
    RequireDerivedKeys: False
    TokenType: http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1
    KeyType: AsymmetricKey
    KeySize: 0
    IssuerAddress: null
    IssuerMetadataAddress: null
    DefaultMessgeSecurityVersion: null
    UseStrTransform: False
    IssuerBinding: null
    ClaimTypeRequirements:
      http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier, optional=False' did not endorse the primary signature.</Message><StackTrace>   at System.ServiceModel.Security.ReceiveSecurityHeader.VerifySupportingToken(TokenTracker tracker)

    At service WCF endpoint I am using bindings:
               var binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
                binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
                binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
                binding.Security.Message.EstablishSecurityContext = false;
                binding.Security.Message.NegotiateServiceCredential = false;
                binding.Security.Message.ClientCredentialType = MessageCredentialType.IssuedToken;
                binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;

    To perform a custom authorization I am extending WCF security classes for:
     SecurityTokenAuthenticator
     WSSecurityTokenSerializer
     ServiceCredentialsSecurityTokenManager
     ServiceCredentials
     and SecurityToken
    using following code:
                var host = new ServiceHost(typeof(MyService), new Uri(address));
                var cert = host.Credentials.ServiceCertificate.Certificate;
                var myServiceCredentials = new MyServiceCredentials();
                myServiceCredentials.ServiceCertificate.Certificate = cert;
                host.Description.Behaviors.Remove(typeof(ServiceCredentials));
                host.Description.Behaviors.Add(myServiceCredentials);

    MyServiceCredentials defined as:
        public class MyServiceCredentials : ServiceCredentials
        {
            public override SecurityTokenManager CreateSecurityTokenManager()
            {
                return new MyServiceCredentialsSecurityTokenManager(this);
            }

            protected override ServiceCredentials CloneCore()
            {
                return new MyServiceCredentials();
            }
        }

    MyServiceCredentialsSecurityTokenManager defined as:
        public class MyServiceCredentialsSecurityTokenManager : ServiceCredentialsSecurityTokenManager
        {
            public MyServiceCredentialsSecurityTokenManager(ServiceCredentials credentials) : base(credentials) {}

            public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(
                SecurityTokenRequirement tokenRequirement,
                out SecurityTokenResolver outOfBandTokenResolver)
            {
             outOfBandTokenResolver = null;
      return new MyTokenAuthenticator();
            }

            public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
            {
                return new MyTokenSerializer(version);
            }
        }

    MyTokenSerializer defined as:
        public class MyTokenSerializer : WSSecurityTokenSerializer
        {
            protected override bool CanReadTokenCore(XmlReader reader)
            {
                return /*custom check here - always true*/;
            }

            protected override SecurityToken ReadTokenCore(XmlReader reader, SecurityTokenResolver tokenResolver)
            {
                //custom deserialization code here
                return new MySecurityToken();
            }

            protected override bool CanWriteTokenCore(SecurityToken token)
            {
                return token is MySecurityToken ? true : base.CanWriteTokenCore(token);
            }

            protected override void WriteTokenCore(XmlWriter writer, SecurityToken token)
            {
                    base.WriteTokenCore(writer, token);
            }
        }
    MyTokenAuthenticator defined as:
        internal class MyTokenAuthenticator : SecurityTokenAuthenticator
        {
            protected override bool CanValidateTokenCore(SecurityToken token)
            {
                return token is MySecurityToken; /*always true*/
            }

            protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateTokenCore(SecurityToken token)
            {
                var token = token as MySecurityToken;
                if (token == null) throw new SecurityTokenValidationException("Security token type not supported");

                var claimSet = new DefaultClaimSet( ClaimSet.System, new Claim(ClaimTypes.Name, token, Rights.PossessProperty));
                var policies = new List<IAuthorizationPolicy>(1) { new MyAuthorizationPolicy(claimSet) };
                return policies.AsReadOnly();
            }
        }
    MyAuthorizationPolicy defined as:
        public class MyAuthorizationPolicy : IAuthorizationPolicy
        {
            private readonly string _id;
            private readonly ClaimSet _tokenClaims;
            private readonly ClaimSet _issuer;

            public MyAuthorizationPolicy(ClaimSet tokenClaims)
            {
                if (tokenClaims == null) throw new ArgumentNullException("tokenClaims");
                _issuer = tokenClaims.Issuer;
                _tokenClaims = tokenClaims;
                _id = Guid.NewGuid().ToString();
            }

            public ClaimSet Issuer { get { return _issuer; } }

            public string Id { get { return _id; } }

            public bool Evaluate(EvaluationContext evaluationContext, ref object state)
            {
                if (evaluationContext == null) throw new ArgumentNullException("evaluationContext");
                evaluationContext.AddClaimSet(this, _tokenClaims);
                return true;
            }
        }
    All extension objects instantiated during service host end point creation and opening with success. When requst received by WCF then:
    1. MyTokenSerializer.ReadTokenCore() called, token deserialized and MySecurityToken object returned
    2. MyTokenAuthenticator.CanValidateTokenCore() called and returns true
    3. MyTokenAuthenticator.ValidateTokenCore() called and returns IAuthorizationPolicy collection with one claim set
    then exception occurs in System.ServiceModel.Security.ReceiveSecurityHeader.VerifySupportingToken


    What I am doing wrong and what needs to be done to complete security token validation and receive the Message?

    Thanks,
    Alexander garin


    Alex

    Monday, November 18, 2013 6:29 PM

All replies

  • Hi,

    I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay. Appreciate your patience.

    Best Regards,
    Amy Peng


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, November 19, 2013 6:47 AM
    Moderator