Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SecurityBindingElement #13

Closed
iamjasonp opened this issue May 13, 2015 · 28 comments
Closed

Support SecurityBindingElement #13

iamjasonp opened this issue May 13, 2015 · 28 comments
Assignees
Milestone

Comments

@iamjasonp
Copy link
Member

SecurityBindingElement is not yet supported and throws PlatformNotSupportedException

@zhenlan
Copy link
Member

zhenlan commented Aug 4, 2015

@iamjasonp you may like to look into what takes to enable issue #81 first for this item.

@fdsprod
Copy link

fdsprod commented Aug 21, 2015

Hi @iamjasonp, would you be able to tell me if fixing this issue will also resolve #9. We are at a stand still with upgrading our WIndows 8.1 app to Windows 10 because of this.

@iamjasonp
Copy link
Member Author

Hi @jeffboulanger - it should fix #9 as well, but we are very tightly scoping the work right now to a limited set of scenarios. Not everything will be supported out of the gate, but we'll continue to enable the scenarios as we go along. We'll probably see SSL out of the gate first, followed by other modes of transport security

@zhenlan zhenlan modified the milestones: 2015.09, 2015.08 Sep 1, 2015
@iamjasonp
Copy link
Member Author

I think we managed to confuse ourselves here. SecurityBindingElement mainly does with SOAP message security and mixed mode security. TransportSecurityBindingElement (#9) is what we're focusing on right now rather than this.

@jeffboulanger, we just committed a first pass for Transport Security (We can now connect to a server successfully now with SSL security over net.tcp, but there are some issues as the client cert can't be specified yet due to us needing to enable some contracts and wait for UWP to open up some API surface).

Can you comment further on what features you might need so we can take that into consideration when prioritizing?

@fdsprod
Copy link

fdsprod commented Sep 4, 2015

@iamjasonp Rather than list everything and possibly miss something, here is how we use WCF in our application. We have about 10 different endpoints, all of which setup their bindings via the following code.

    public class NoTimestampBasicHttpBinding : BasicHttpBinding
    {
        public NoTimestampBasicHttpBinding(BasicHttpSecurityMode securityMode, MessageVersion messageVersion = null)
            : base(securityMode)
        {
            CustomMessageVersion = messageVersion;
            IsNonSecure = securityMode == BasicHttpSecurityMode.TransportCredentialOnly;

            MaxBufferSize = 10485760;
            MaxBufferPoolSize = 10485760;
            MaxReceivedMessageSize = 10485760;
            ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            AllowCookies = false;
            TextEncoding = Encoding.UTF8;
            TransferMode = TransferMode.Buffered;
        }

        public MessageVersion CustomMessageVersion
        {
            get;
            private set;
        }

        public bool IsNonSecure
        {
            get;
            private set;
        }

        public override BindingElementCollection CreateBindingElements()
        {
            var bindingElementCollection = base.CreateBindingElements();

            var securityBindingElement = bindingElementCollection.FirstOrDefault(x => x is SecurityBindingElement) as SecurityBindingElement;
            if (securityBindingElement != null)
            {
                securityBindingElement.IncludeTimestamp = false;

                var transportSecurityBindingElement = securityBindingElement as TransportSecurityBindingElement;
                if (transportSecurityBindingElement != null)
                {
                    transportSecurityBindingElement.IncludeTimestamp = false;
                }
            }

            if (CustomMessageVersion != null)
            {
                var messageEncodingBindingElement = bindingElementCollection.FirstOrDefault(x => x is MessageEncodingBindingElement) as TextMessageEncodingBindingElement;
                if (messageEncodingBindingElement != null)
                {
                    messageEncodingBindingElement.MessageVersion = CustomMessageVersion;
                }
            }

            return bindingElementCollection;
        }
    }

    public sealed class CustomBinding : BasicHttpBinding
    {
        private BindingElementCollection _bindingElements;

        public CustomBinding(BasicHttpSecurityMode securityMode, BindingElementCollection bindingElements)
            : base(securityMode)
        {
            Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
            _bindingElements = new BindingElementCollection(bindingElements.ToArray());

            MaxBufferSize = 10485760;
            MaxBufferPoolSize = 10485760;
            MaxReceivedMessageSize = 10485760;
            ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            AllowCookies = false;
            TextEncoding = Encoding.UTF8;
            TransferMode = TransferMode.Buffered;
        }

        public override BindingElementCollection CreateBindingElements()
        {
            var securityBindingElement = _bindingElements.FirstOrDefault(x => x is SecurityBindingElement) as SecurityBindingElement;
            if (securityBindingElement != null)
            {
                securityBindingElement.IncludeTimestamp = false;
            }

            return _bindingElements;
        }
    }

    public static class BindingFactory
    {
        public static readonly TimeSpan OpenTimeoutTimespan = TimeSpan.FromSeconds(10);
        public static readonly TimeSpan CloseTimeoutTimespan = TimeSpan.FromSeconds(10);

        public static Binding Create(BasicHttpSecurityMode securityMode = BasicHttpSecurityMode.None, bool resetDefaultTimeouts = true, MessageVersion messageVersion = null)
        {
            BasicHttpBinding binding = new NoTimestampBasicHttpBinding(securityMode, messageVersion);
            switch (binding.Security.Mode)
            {
                case BasicHttpSecurityMode.Transport:
                case BasicHttpSecurityMode.TransportWithMessageCredential:
                case BasicHttpSecurityMode.TransportCredentialOnly:
                    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
                    break;

                case BasicHttpSecurityMode.None:
                case BasicHttpSecurityMode.Message:
                default:
                    // Do Nothing
                    break;
            }

            if (resetDefaultTimeouts)
            {
                binding.OpenTimeout = OpenTimeoutTimespan;
                binding.CloseTimeout = CloseTimeoutTimespan;
            }

            binding.MaxBufferSize = 10485760;
            binding.MaxBufferPoolSize = 10485760;
            binding.MaxReceivedMessageSize = 10485760;
            binding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            binding.AllowCookies = false;
            binding.TextEncoding = Encoding.UTF8;
            binding.TransferMode = TransferMode.Buffered;

            return binding;
        }

        public static Binding CreateCustom(BasicHttpSecurityMode securityMode = BasicHttpSecurityMode.None, bool resetDefaultTimeouts = true, MessageVersion messageVersion = null)
        {
            BindingElementCollection bindingElements = new BindingElementCollection();
            var defaultBindings = new NoTimestampBasicHttpBinding(securityMode, messageVersion).CreateBindingElements();
            foreach(var defaultBinding in defaultBindings)
            {
                if (defaultBinding is MessageEncodingBindingElement)
               {
                    bindingElements.Add(new CustomTextMessageBindingElement(messageVersion));
                }
                else
                {
                    bindingElements.Add(defaultBinding.Clone());
                }
            }

            var binding = new CustomBinding(securityMode, bindingElements);

            if (resetDefaultTimeouts)
            {
                binding.OpenTimeout = OpenTimeoutTimespan;
                binding.CloseTimeout = CloseTimeoutTimespan;
            }

            binding.MaxBufferSize = 10485760;
            binding.MaxBufferPoolSize = 10485760;
            binding.MaxReceivedMessageSize = 10485760;
            binding.ReaderQuotas = XmlDictionaryReaderQuotas.Max;
            binding.AllowCookies = false;
            binding.TextEncoding = Encoding.UTF8;
            binding.TransferMode = TransferMode.Buffered;

            return binding;
        }
    }

    // Usage
    var binding = BindingFactory.Create(BasicHttpSecurityMode.TransportWithMessageCredential, false);
    var serviceClient = new ProfileServiceClient(binding, settings.Url);

    // ProfileServiceClient ctor
    public ProfileServiceClient(Binding binding, string remoteAddress)
        : base(binding, new System.ServiceModel.EndpointAddress(remoteAddress))
    {
        this.Endpoint.Name = EndpointConfiguration.ProfilesServicePort.ToString();
    }

Everything else for the service clients are generated with the wsdl tools, and hasn't been modified.

Hopefully this helps.

@zhenlan zhenlan modified the milestones: 2015.10, 2015.09 Oct 6, 2015
@iamjasonp
Copy link
Member Author

We haven't turned on anything with MessageCredential (Message Security) at the moment, unfortunately, due to time constraints.

We are still working on #385 to turn on some of the APIs required for setting client certs. I think everything else here should be supported after #9.

@fdsprod
Copy link

fdsprod commented Oct 14, 2015

@iamjasonp Thanks for the update, we are waiting patiently

@raydixon
Copy link

@jeffboulanger Thank you! Your code sample - #13 (comment) - got me past a blocking issue I had with BasicHttpBinding using SOAP 1.1 instead of SOAP 1.2 and WsHttpBinding not being available in the Unversal Windows library!

@fdsprod
Copy link

fdsprod commented Nov 18, 2015

@iamjasonp #385 and #9 are marked as closed, does that mean this should work now?

@iamjasonp
Copy link
Member Author

@jeffboulanger - should do. I confess i haven't given your particular binding setup above a try, but after a cursory inspection, i think what you need is available now.

The only thing is:

 securityBindingElement.IncludeTimestamp = false;

Will not compile, since we haven't included Message Security yet, but given that you're setting this to false, I don't think it makes a practical difference to your scenario.

@fdsprod
Copy link

fdsprod commented Nov 19, 2015

@iamjasonp Thanks I will give it a try. Not being able to set the IncludeTimestamp to false, will the current code send the timestamp, or is it just not being sent anyway?

@fdsprod
Copy link

fdsprod commented Nov 19, 2015

@iamjasonp I tried to reference nuget package 23516 but received errors about other reference assemblies not having x64 or x64-aot support. The most recent version I'm able to try is 23409. When I used this version I received a PlatformNotSupportedException on SetKeyDerivation. Looking at the latest code in master I see this method has not yet been implemented.

        public virtual void SetKeyDerivation(bool requireDerivedKeys)
        {
            throw ExceptionHelper.PlatformNotSupported("SecurityBindingElement.SetKeyDerivation is not supported.");
        }

The problem occurs in the code I've added in a previous comment, in NoTimestampBasicHttpBinding

        public override BindingElementCollection CreateBindingElements()
        {
            var bindingElementCollection = base.CreateBindingElements();  // Exception occurs here.

@iamjasonp
Copy link
Member Author

Got it - thanks for the catch.
SetKeyDerivation has to do with message security, so it wasn't implemented. I see the offending code here: https://github.com/dotnet/wcf/blob/master/src/System.Private.ServiceModel/src/System/ServiceModel/BasicHttpMessageSecurity.cs#L66

I think for this one we'll have to just hard-force this to false and throw PlatformNotSupported when it's set to true. Based on a reading of the code, we should be okay if we enforce this to be false for the time being.


As for:

Not being able to set the IncludeTimestamp to false, will the current code send the timestamp, or is it just not being sent anyway?

No, it's not going to be sent at all since WS-RM/WS-Security isn't turned on. This setting controls WS-Security based timestamping only - for example, used to detect replayed messages or to ensure only-once delivery

@iamjasonp
Copy link
Member Author

#540 opened to track this issue you pointed out. Thanks @jeffboulanger!

@fdsprod
Copy link

fdsprod commented Dec 7, 2015

@iamjasonp Got around to testing this today and am getting a new error

TransportSecurityBindingElement.GetProperty is not supported.

This occurs when actually calling a method defined on a service client endpoint.

Example:

        public System.Threading.Tasks.Task<GetAllProfilesResponse> GetAllProfilesAsync(GetAllProfilesRequest request)
        {
            return base.Channel.GetAllProfilesAsync(request);
        }

I'm using v4.1.0-rc2-23604. Please let me know if you need more information.

@iamjasonp
Copy link
Member Author

@jeffboulanger - yep, I saw that in my testing. #577 has the fix, and I intend to merge it in a couple of hours after fixing come comments

@iamjasonp
Copy link
Member Author

Alright, next thing to do:

System.ServiceModel.Channels.TransportSecurityBindingElement.BuildChannelFactoryCore() will need to be implemented, for SecurityMode.Message or SecurityMode TransportWithMessageCredential.

It shouldn't be needed when Message Security is not turned on.

@fdsprod
Copy link

fdsprod commented Dec 8, 2015

@iamjasonp Do i need to wait for BuildChannelFactoryCore() or can I use the nightly from that includes #577?

@iamjasonp
Copy link
Member Author

@jeffboulanger Don't think you need to wait, as you don't set BasicHttpSecurityMode to .Message or .TransportWithMessageCredential.

Verified with this case: iamjasonp@23e1c2f#diff-2f52e0ae0c609fa39a62ed9f284696deR41

@fdsprod
Copy link

fdsprod commented Dec 9, 2015

@iamjasonp We do, as shown in the code I posted above

    // Usage
    var binding = BindingFactory.Create(BasicHttpSecurityMode.TransportWithMessageCredential, false);
    var serviceClient = new ProfileServiceClient(binding, settings.Url);

@fdsprod
Copy link

fdsprod commented Dec 14, 2015

@iamjasonp Is there a issue open to be tracked for #13 (comment) so I can be informated when I sohuld be able to try again?

@iamjasonp
Copy link
Member Author

@jeffboulanger - I overlooked your use of TransportWithMessageCredential at the bottom. #8 tracks supporting message security - for now this feature work isn't scheduled for the rtm timeframe.

It's understood that message security is an important scenario. Please do chime in on #8 (or any other bug you happen to see relating to message security) so we can prioritize accordingly to what customers need.

@iamjasonp
Copy link
Member Author

Let's move all further discussion on supporting SecurityMode.TransportWithMessageCredential and SecurityMode.Message to #8.

Thanks for your input, everyone!

@MelbourneDeveloper
Copy link

So, can we actually use security now? We really need UsernamePasswordAuthentication implemented. Has it been implemented? When will it be implemented?

@himansishah
Copy link

Hello , I am not getting way to call WCF service which is third party API i need to call it from Aws Lambda Core Project and i am getting error like "TransportSecurityBindingElement.BuildChannelFactoryCore is not supported." I have attached error picture that it will make you more clear. please give me any solution or idea it ll be appreciable ..thanks in advance.
error

@89NightLight
Copy link

any updates on this? i have the exact same problem with calling WCF service, I get the same PlatformNotSupportedException: TransportSecurityBindingElement.BuildChannelFactoryCore is not supported. same as @himansishah

@siblight
Copy link

Mornng, is there any updates on this issue?

@lommez
Copy link

lommez commented Oct 17, 2019

I got the same problem.
Is there any work around?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants