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

svcutil generating incorrect client for WSHttpBinding with SecurityMode.TransportWithMessageCredential #4828

Open
samsp-msft opened this issue May 18, 2022 · 2 comments · May be fixed by #4843
Assignees
Labels
Projects

Comments

@samsp-msft
Copy link
Member

Defining a WCF Core service using WSHttpBinding with SecurityMode.TransportWithMessageCredential. Creating a client using .NET Framework, will correctly be able to call the service.

The generated code for a .NET core client does not, and fails.

The service endpoint is defined using:

 public void Configure(IApplicationBuilder app)
        {
            var wsHttpBindingWithCredential = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
            wsHttpBindingWithCredential.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

            app.UseServiceModel(builder =>
            {
                // Add the Echo Service
                builder.AddService<EchoService>(serviceOptions =>
                {
                    // Set a base address for all bindings to the service, and WSDL discovery
                    serviceOptions.BaseAddresses.Add(new Uri($"http://localhost:{Program.HTTP_PORT}/EchoService"));
                    serviceOptions.BaseAddresses.Add(new Uri($"https://localhost:{Program.HTTPS_PORT}/EchoService"));
                })
                // Add WSHttpBinding endpoints
                .AddServiceEndpoint<EchoService, IEchoService>(new WSHttpBinding(SecurityMode.None), "/wsHttp")
                .AddServiceEndpoint<EchoService, IEchoService>(new WSHttpBinding(SecurityMode.Transport), "/wsHttp")
                .AddServiceEndpoint<EchoService, IEchoService>(wsHttpBindingWithCredential, "/wsHttpUserPassword", ep => { ep.Name = "AuthenticatedEP"; });

                builder.ConfigureServiceHostBase<EchoService>(CustomUserNamePasswordValidator.AddToHost);

                // Configure WSDL to be available over http & https
                var serviceMetadataBehavior = app.ApplicationServices.GetRequiredService<CoreWCF.Description.ServiceMetadataBehavior>();
                serviceMetadataBehavior.HttpGetEnabled = serviceMetadataBehavior.HttpsGetEnabled = true;
            });
        }

The GetBindingForEndpoint generated code for the service definition is:

         if ((endpointConfiguration == EndpointConfiguration.AuthenticatedEP))
            {
                System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
                System.ServiceModel.Channels.TransportSecurityBindingElement userNameOverTransportSecurityBindingElement = System.ServiceModel.Channels.SecurityBindingElement.CreateUserNameOverTransportBindingElement();
                userNameOverTransportSecurityBindingElement.MessageSecurityVersion = System.ServiceModel.MessageSecurityVersion.WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
                result.Elements.Add(userNameOverTransportSecurityBindingElement);
                System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
                result.Elements.Add(textBindingElement);
                System.ServiceModel.Channels.HttpsTransportBindingElement httpsBindingElement = new System.ServiceModel.Channels.HttpsTransportBindingElement();
                httpsBindingElement.AllowCookies = true;
                httpsBindingElement.MaxBufferSize = int.MaxValue;
                httpsBindingElement.MaxReceivedMessageSize = int.MaxValue;
                result.Elements.Add(httpsBindingElement);
                return result;
            }

Which is incorrectly trying to use CreateUserNameOverTransportBindingElement(); which is incorrect for this binding type.

@petarpetrovt
Copy link

I have the same problem. Instead of CreateCertificateOverTransportBindingElement the client binding is generated with CreateUserNameOverTransportBindingElement.

Binding (Server)

var binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;

Configuration (WcfTestClient)

<customBinding>
    <binding name="HttpsCertificate_ICoreService" sendTimeout="00:05:00">
        <security defaultAlgorithmSuite="Default" authenticationMode="CertificateOverTransport"
            requireDerivedKeys="true" securityHeaderLayout="Lax" includeTimestamp="true"
            messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
            <localClientSettings detectReplays="false" />
            <localServiceSettings detectReplays="false" />
        </security>
        <textMessageEncoding messageVersion="Soap11" />
        <httpsTransport requireClientCertificate="true" />
    </binding>
</customBinding>

Generated (Client)

if ((endpointConfiguration == EndpointConfiguration.HttpsCertificate_ICoreService))
{
    System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
    System.ServiceModel.Channels.TransportSecurityBindingElement userNameOverTransportSecurityBindingElement = System.ServiceModel.Channels.SecurityBindingElement.CreateUserNameOverTransportBindingElement();
    userNameOverTransportSecurityBindingElement.MessageSecurityVersion = System.ServiceModel.MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10;
    userNameOverTransportSecurityBindingElement.SecurityHeaderLayout = System.ServiceModel.Channels.SecurityHeaderLayout.Lax;
    result.Elements.Add(userNameOverTransportSecurityBindingElement);
    System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
    textBindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.Soap11;
    result.Elements.Add(textBindingElement);
    System.ServiceModel.Channels.HttpsTransportBindingElement httpsBindingElement = new System.ServiceModel.Channels.HttpsTransportBindingElement();
    httpsBindingElement.AllowCookies = true;
    httpsBindingElement.MaxBufferSize = int.MaxValue;
    httpsBindingElement.MaxReceivedMessageSize = int.MaxValue;
    result.Elements.Add(httpsBindingElement);
    return result;
}

@petarpetrovt petarpetrovt linked a pull request Jun 15, 2022 that will close this issue
5 tasks
@HongGit HongGit added this to Needs triage in Tooling via automation Jun 16, 2022
@HongGit HongGit moved this from Needs triage to 2.0.4 in Tooling Jun 24, 2022
@imcarolwang
Copy link
Contributor

  1. dotnet-svcutil now generates WSHttpBinding instead of Custombinding with these changes in: https://github.com/dotnet/wcf/pull/4774/commits
  2. custom binding hard coded generation of CreateUserNameOverTransportBindingElement , PR Fix svcutil endpoint configurations generation  #4843 addresses it

@HongGit HongGit moved this from 2.0.4 to 2.1.1 in Tooling Nov 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Tooling
2.1.1
Development

Successfully merging a pull request may close this issue.

4 participants