{"id":31212,"date":"2021-01-07T09:00:30","date_gmt":"2021-01-07T16:00:30","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=31212"},"modified":"2021-01-05T15:29:50","modified_gmt":"2021-01-05T22:29:50","slug":"wsfederationhttpbinding-in-net-standard-wcf","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/wsfederationhttpbinding-in-net-standard-wcf\/","title":{"rendered":"WSFederationHttpBinding in .NET Standard"},"content":{"rendered":"<p>As .NET Core has evolved, the WCF team has worked to expand support for WCF client scenarios on .NET Standard and .NET Core. Until recently, one of the gaps developers faced when building WCF clients for .NET Core was the lack of <code>WSFederationHttpBinding<\/code> and <code>WS2007FederationHttpBinding<\/code>. These bindings support WS-Federation authentication scenarios where users authenticate with a security token service (like Active Directory Federation Services) and use a token from that authentication provider to authenticate with a separate service (called the &#8216;relying party&#8217;). Last month, the <a href=\"https:\/\/www.nuget.org\/packages\/System.ServiceModel.Federation\">System.ServiceModel.Federation package<\/a> (targeting .NET Standard 2.0) released, enabling these client WCF scenarios!<\/p>\n<p>This post covers the basics of getting started with System.ServiceModel.Federation in your .NET Core application. It goes over how to install the package and how its use differs from previous WS-Fed WCF scenarios.<\/p>\n<h2>Using <code>WSFederationHttpBinding<\/code><\/h2>\n<p>To use the .NET Standard-compatible version of <code>WSFederationHttpBinding<\/code>, add a reference to the <a href=\"https:\/\/www.nuget.org\/packages\/System.ServiceModel.Federation\"><code>System.ServiceModel.Federation<\/code><\/a> package with version <code>4.8.0<\/code>.<\/p>\n<pre><code class=\"xml\">&lt;PackageReference Include=\"System.ServiceModel.Federation\" Version=\"4.8.0\" \/&gt;\r\n<\/code><\/pre>\n<p>This package contains the <code>WSFederationHttpBinding<\/code> type that is now used for both WSFederationHttp and WS2007FederationHttp scenarios. A key difference between .NET Framework WCF scenarios and .NET Core WCF scenarios is that .NET Core doesn&#8217;t use application config files for setting up WCF objects, so the binding will need to be configured in code rather than in <code>app.config<\/code>, as you might have previously done for .NET Framework.<\/p>\n<p>If you&#8217;re using a WCF client (derived from <code>ClientBase&lt;T&gt;<\/code>) to interact with your WCF service, you can use the client&#8217;s constructor that takes a <code>Binding<\/code> and an <code>EndpointAddress<\/code> as parameters. In many cases, existing client code generated by .NET Framework&#8217;s SvcUtil will continue to work. Just make sure you&#8217;re using client constructors that accept a binding as a parameter instead of one that expects to create the binding from configuration. Updates to <a href=\"https:\/\/docs.microsoft.com\/dotnet\/core\/additional-tools\/dotnet-svcutil-guide\">dotnet-svcutil<\/a> and Visual Studio&#8217;s <a href=\"https:\/\/docs.microsoft.com\/dotnet\/core\/additional-tools\/wcf-web-service-reference-guide\">WCF Web Service Reference Provider Tool<\/a> are planned which will enable auto-generating .NET Standard-specific clients for WCF services with WS-Federation bindings.<\/p>\n<p>The <code>WSFederationHttpBinding<\/code> constructor takes a single parameter of type <code>WSTrustTokenParameters<\/code>. This parameter is used to specify details about the token issuer (STS) the binding should get tokens from and how those tokens should be handled. The easiest way to create an instance of <code>WSTrustTokenParameters<\/code> is to use the <code>WSTrustTokenParameters.CreateWS2007FederationTokenParameters<\/code> or <code>WSTrustTokenParameters.CreateWSFederationTokenParameters<\/code> helper methods. These static methods will create <code>WSTrustTokenParameters<\/code> for WS2007Federation and WSFederation scenarios, respectively. Both methods take the issuer binding (also called the &#8216;inner binding&#8217;) and endpoint address as parameters. It&#8217;s also possible to create your own <code>WSTrustTokenParameters<\/code> via the constructor and specify exactly the behavior you need. Important properties on the <code>WSTrustTokenParameters<\/code> type include:<\/p>\n<ul>\n<li><strong><code>IssuerAddress<\/code><\/strong> This is an <code>EndpointAddress<\/code> for the STS that the federation binding should get tokens from.<\/li>\n<li><strong><code>IssuerBinding<\/code><\/strong> This property represents what is sometimes known as the inner binding &#8211; the WCF binding used for communicating with the token issuer. This is often a <code>WSHttpBinding<\/code> or <code>WS2007HttpBinding<\/code>, but will vary based on the scenario and should match the type of binding that would have been used for the issuerBinding in a .NET Framework app.config file.<\/li>\n<li><strong><code>MessageSecurityVersion<\/code><\/strong> This property specifies which versions of WSSecurity, WSTrust, WSSecureConversation, and WSSecurityPolicy should be used. If you were previously using <code>WSFederationHttpBinding<\/code>, then the correct value for this property is <code>WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10<\/code>. If you were previously using <code>WS2007FederationHttpBinding<\/code>, then the correct value is <code>WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10<\/code>. Using the <code>CreateWSFederationTokenParameters<\/code> or <code>CreateWS2007FederationTokenParameters<\/code> helper methods will initialize this properly automatically.<\/li>\n<li><strong><code>TokenType<\/code><\/strong> This optional property specifies the type of token that should be requested from the issuer.<\/li>\n<li><strong><code>CacheIssuedTokens<\/code>, <code>MaxIssuedCachingTime<\/code>, and <code>IssuedTokenRenewalThresholdPercentage<\/code><\/strong> These properties indicate whether tokens should be cached and for how long. In many cases, these properties don&#8217;t need to be set as the defaults (tokens are cached for 60% of their lifetime) are sufficient.<\/li>\n<li><strong><code>EstablishSecurityContext<\/code><\/strong> This boolean determines whether or not to use a secure conversation context. Again, this property often doesn&#8217;t need to be set because the default (true) is common.<\/li>\n<li><strong><code>RequestContext<\/code><\/strong> An optional string that will be passed along in WS-Trust requests to the token issuer that can help with correlating messages for diagnostic purposes.<\/li>\n<\/ul>\n<p>Once the <code>WSTrustTokenParameters<\/code> instance has been created and passed to a <code>WSFederationHttpBinding<\/code>, that binding can be used to create a WCF client (derived from <code>ClientBase<\/code>) or <code>ChannelFactory<\/code>.<\/p>\n<p>Here is an example of creating a typical <code>WSFederationHttpBinding<\/code>:<\/p>\n<pre><code class=\"CSharp\">\/\/ First, create the inner binding for communicating with the token issuer.\r\n\/\/ The security settings will be specific to the STS and should mirror what\r\n\/\/ would have been in an app.config in a .NET Framework scenario.\r\nvar issuerBinding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);\r\nissuerBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;\r\nissuerBinding.Security.Message.EstablishSecurityContext = false;\r\n\r\n\/\/ Next, create the token issuer's endpoint address\r\nvar endpointAddress = new EndpointAddress(\"https:\/\/&lt;IssuerAddress&gt;\/adfs\/services\/trust\/13\/usernamemixed\");\r\n\r\n\/\/ Finally, create the WSTrustTokenParameters\r\nvar tokenParameters = WSTrustTokenParameters.CreateWS2007FederationTokenParameters(issuerBinding, endpointAddress);\r\n\r\n\/\/ This workaround is necessary only until an updated System.ServiceModel.Federation ships with\r\n\/\/ https:\/\/github.com\/dotnet\/wcf\/issues\/4426 fixed.\r\n\/\/ The CreateWSFederationTokenParameters helper method does not have this bug.\r\ntokenParameters.KeyType = SecurityKeyType.SymmetricKey;\r\n\r\n\/\/ Create the WSFederationHttpBinding\r\nvar binding = new WSFederationHttpBinding(tokenParameters);\r\n<\/code><\/pre>\n<p>A sample client using <code>WSFederationHttpBinding<\/code> is available <a href=\"https:\/\/github.com\/mjrousos\/WSFedSample\">on GitHub<\/a>.<\/p>\n<h2>Wrap up<\/h2>\n<p>With the release of System.ServiceModel.Federation, it is now be possible to implement scenarios that consume WCF services with WS-Federation bindings on .NET Core. The System.ServiceModel.Federation package is built from the <a href=\"https:\/\/github.com\/dotnet\/wcf\/\">WCF repository<\/a>, so please leave feedback there if you run into anything that doesn&#8217;t work right.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The new `System.ServiceModel.Federation` package adds support for `WSFederationHttpBinding` and `WS2007FederationHttpBinding` which enable WS-Federation authentication scenarios. In this post, I&#8217;ll show you you the basics of getting started with these client-side bindings in your .NET Core applications and .NET Standard libraries.<\/p>\n","protected":false},"author":7413,"featured_media":31350,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196],"tags":[],"class_list":["post-31212","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core"],"acf":[],"blog_post_summary":"<p>The new `System.ServiceModel.Federation` package adds support for `WSFederationHttpBinding` and `WS2007FederationHttpBinding` which enable WS-Federation authentication scenarios. In this post, I&#8217;ll show you you the basics of getting started with these client-side bindings in your .NET Core applications and .NET Standard libraries.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/31212","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/7413"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=31212"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/31212\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/31350"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=31212"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=31212"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=31212"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}