dotnet / wcf

This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
MIT License
1.71k stars 559 forks source link

Missing properties in IssuedSecurityTokenParameters in version 6.0.0 preview1 #5029

Open martintro opened 1 year ago

martintro commented 1 year ago

Describe the bug We have a custom issued token ws-trust binding which is using the class IssuedSecurityTokenParameters and ClaimTypeRequirement, which I cannot see is made publicly available in the nuget package.

  1. ClaimTypeRequirement class is missing.
  2. AdditionalRequestParameters property in IssuedSecurityTokenParameters is missing.
  3. ClaimTypeRequirements property in IssuedSecurityTokenParameters is missing.
  4. IssuerMetadataAddress property in IssuedSecurityTokenParameters is missing.
  5. KeySize property in IssuedSecurityTokenParameters is missing.

Would it be possible to make these public?

To Reproduce Steps to reproduce the behavior:

  1. Create a .NET 6 class library project
  2. Reference System.ServiceModel.Primitives 6.0.0-preview1.23060.3
  3. Create an instance of IssuedSecurityTokenParameters and set properties KeySize and IssuerMetadataAddress
  4. Add object to collections ClaimTypeRequirements and AdditionalRequestParameters

Expected behavior Be able to set the "missing" properties in class IssuedSecurityTokenParameters and create instance of class ClaimTypeRequirement.

mconnew commented 1 year ago

Looking at your collection of issues, I think there might be an easier path forward for you. What are you doing in your custom binding which the WSFederationHttpBinding doesn't do? We have a new System.ServiceModel.Federation package which has a good chance of having everything you need. There were a couple of bugs which included AdditionalRequestParameters not being copied, but they've been fixed in the main branch and will be in the next version. I suspect we have everything you need available there.

martintro commented 1 year ago

Thanks for taking your time @mconnew! It looks like that could work, yes. I'll try it out and get back with the result.

Another thing I found which seems unsupported is the .NET Framework binding below. What seems unsupported to me is the following code: https://github.com/dotnet/wcf/blob/main/src/System.ServiceModel.NetTcp/src/System/ServiceModel/MessageSecurityOverTcp.cs#L82 Am I missing something or is there another class I can use to get this to work? If not, is there any plans to support issued token authentication via nettcp binding in the future?

<customBinding>
  <binding name="ExampleClientCustomBinding">
    <security authenticationMode="SecureConversation" requireSecurityContextCancellation="true">
      <secureConversationBootstrap authenticationMode="IssuedToken">
        <issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" />
      </secureConversationBootstrap>
    </security>
    <binaryMessageEncoding />
    <sslStreamSecurity requireClientCertificate="false" />
    <tcpTransport>
      <connectionPoolSettings groupName="exampleClient" idleTimeout="00:01:00" leaseTimeout="00:01:00" maxOutboundConnectionsPerEndpoint="20" />
    </tcpTransport>
  </binding>
</customBinding>
mconnew commented 1 year ago

I would expect that to work. It's possible app.config support might not do the right thing (no reason to believe it wouldn't, just a possibility as I don't think that combo is tested), but I believe we have the api's to do what you want. We support ws-federation which depends on issued token support.

See next comment for correct answer.

mconnew commented 1 year ago

I just realized I replied to a WCF question and not CoreWCF, so ignore my previous comment about config.
The way you would do the above is to mimic some of what WSFederationHttpBinding does. There are a couple of key things you need to do.

First, you need to create your security binding element using something similar to the code here, with any changes for your specific scenario. The bootstrap binding element is what gets set passed to the constructor of SecureConversationSecurityTokenParameters when EstablishSecurityContext is true.

The second thing is to include WSFederationBindingElement in your custom binding, passing the SecurityBindingElement you created above as a constructor, along with WSTrustTokenParameters. What this does is replace the ClientCredentials instance with an instance of WSTrustChannelClientCredentials. This class knows how to do the WSTrust protocol to go get the token from a thrid party. If you are fetching the token via some other mechanism not involving WCF, let me know and I'll help you piece together the bits you need to plumb your issued token in.

martintro commented 1 year ago

I finally got it working with http transport, SecureConversation and IssuedTokenOverTransport as authentication mode for the secure conversation bootstrap part, by writing a custom binding class and with some inspiration from this https://github.com/dotnet/wcf/issues/4837 since we are using CreateChannelWithIssuedToken.

What I cannot find out how to solve though is the IssuedToken authentication mode for secure conversation bootstrap together with tcp transport. I found the following method https://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Channels/SecurityBindingElement.cs,1195 in .NET Framework which is currently missing for .NET 6. I guess it is missing because of the SymmetricSecurityBindingElement? I cannot find that class in this repo. Am I missing something?

I didn't get IssuedTokenOverTransport together with nettcp working neither. According to this docs (https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.configuration.authenticationmode?view=netframework-4.8.1) it sounds like it has to be http transport to be able to use IssuedTokenOverTransport?

mconnew commented 1 year ago

The link to SecurityBindingElement that you provided is for full Message security where the SOAP message is encrypted and signed. When using TransportWithMessageCredentials with TCP, it uses SslStreamSecurityBindingElement to use TLS to encrypt the communication, but it disables RequireClientCertificate as you use Message Credentials (via TransportSecurityBindingElement) to authenticate the client.

What might help you is on .NET Framework, use a debugger to step over this code:

// Load binding from config
var customBinding = new CustomBinding("ExampleClientCustomBinding");
foreach(var be in customBinding.Elements)
{
    // Add breakpoint here and look at the properties of the BindingElement
    Console.WriteLine("BindingElement type is " + be.GetType().FullName);
}

That way you can see first hand what the equivalent turns out to be.

martintro commented 1 year ago

Good idea, thanks for the tip. Alright, so TCP transport with SecureConversation and IssuedTokenOverTransport should be possible in .NET 6, right? I will try to get it working in my app again.

How about the original binding I posted? That is what we are using today and would like to continue using, if possible, in .NET 6. From what I understand IssuedToken is full message security and therefore uses SymmetricSecurityBindingElement? That's what your code also tells me (see below). What's the status of getting SymmetricSecurityBindingElement ported over to .NET 6, or have you already discarded the idea of supporting full message security in .NET 6?

<binding name="NettcpSecureConversationIssuedToken">
  <security authenticationMode="SecureConversation" requireSecurityContextCancellation="true">
    <secureConversationBootstrap authenticationMode="IssuedToken">
      <issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" />
    </secureConversationBootstrap>
  </security>
  <binaryMessageEncoding />
  <sslStreamSecurity requireClientCertificate="false" />
  <tcpTransport>
    <connectionPoolSettings groupName="nettcpSecureConversationIssuedTokenClient" idleTimeout="00:01:00" leaseTimeout="00:01:00" maxOutboundConnectionsPerEndpoint="20" />
  </tcpTransport>
</binding>
Configuration name is NettcpSecureConversationIssuedToken
BindingElement type is System.ServiceModel.Channels.SymmetricSecurityBindingElement
BindingElement type is System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
BindingElement type is System.ServiceModel.Channels.SslStreamSecurityBindingElement
BindingElement type is System.ServiceModel.Channels.TcpTransportBindingElement
martintro commented 1 year ago

@mconnew Now it works with TCP transport with SecureConversation and IssuedTokenOverTransport for me, thanks so far! My question regarding IssuedToken authentication mode/SymmetricSecurityBindingElement remains though.