Archive for March, 2011

Some tips on Active Federation with ADFS 2.0

Introduction

At work I have been working on helping my company adopt ADFS 2.0 for a Single Sign-On initiative. I have been working on handling a WPF application’s federation with ADFS and needed to use active federation (by definition). I had been following along with Dominick Baier’s blog post at http://www.leastprivilege.com/WIFADFS2AndWCFndashPart5ServiceClientMoreFlexibilityWithWSTrustChannelFactory.aspx. Dominick’s sample seemed simple enough but there were quite a few ADFS things I had to figure out in order to make things work.

BTW, learning how WIF relates to ADFS has been quite challenging but I have found the following article to be very helpful: http://technet.microsoft.com/en-us/library/adfs2-federation-wif-application-step-by-step-guide(WS.10).aspx.

Issues

    1. So I downloaded the code for the post and tried running the ManualClient. This uses WSTrustChannelFactory to connect to ADFS. The base sample uses the following ADFS endpoint:
      static string stsEndpoint = "https://<machine.domain>/adfs/services/trust/13/windowstransport";
      

      The windowstransport ADFS endpoints are not enabled by default so you must enable them. When I first tried to enable the WS Trust 1.3 version it would enable but it would not allow me to enable the proxy for this. I am not sure why. Eventually I was able to get the WS Trust 1.3 endpoint enabled. So at first I switched over to using the WS Trust 2005 endpoint. I also had to change the trust version to TrustVersion.WSTrustFeb2005 in the code as well. Here is the updated code at this point:

      static string stsEndpoint = "https://<machine.domain>/adfs/services/trust/2005/windowstransport";
      static string svcEndpoint = "https://<machine.domain>/soapadfs/service.svc";
      
      static void Main(string[] args)
      {
         var token = GetToken();
         CallService(token);
      }
      
      private static SecurityToken GetToken()
      {
         var factory = new WSTrustChannelFactory(
            new WindowsWSTrustBinding(SecurityMode.Transport),
            stsEndpoint);
      
         factory.TrustVersion = TrustVersion.WSTrustFeb2005;
      
         var rst = new RequestSecurityToken
         {
            RequestType = RequestTypes.Issue,
            AppliesTo = new EndpointAddress(svcEndpoint),
            KeyType = KeyTypes.Symmetric
         };
      
         var channel = factory.CreateChannel();
      
         return channel.Issue(rst);
      }
      
    2. So then I ran the code and it got all the way to the last line of the method GetToken() and it gives me the following nearly meaningless message back (wrapped in a FaultException):

      ID3082: The request scope is not valid or is unsupported.

      I was not able to find very good information on this error but I eventually found out that one of the reasons that this can occur is if you have not setup a relying party trust in ADFS for your application.

    3. Like with much of active federation, there is a lot less documentation out there for active federation than for passive federation. Here are the steps I went through to create an ADFS relying party for an application that does not have a federation metadata document:

      a. In the ADFS 2.0 MMC, click to create a Relying Party trust.
      b. On the next page of the wizard, choose to “Enter data about the relying party manually”. Click Next
      c. Enter a display name, click Next
      d. Choose ADFS 2.0, click Next
      e. For now, do not specify an encryption certificate, click Next,
      f. Do not click to enable WS-Federation passive or Web-SSO. Both of these are browser-based options that do not apply to active federation. Click Next.
      g. For the relying party trust identifier, enter the endpoint reference you are using to call over WS-Trust, so I entered: <a href=”https:///soapadfs/service.svc”>https://<machine.domain>/soapadfs/service.svc
      h. Click to allow all to access the relying party, click Next.
      i. Click Next to move on to the Claims Authorization Wizard.
      j. I just specify a Windows username pass through at this point (see the link in my introduction for how to set this up).

    4. So then I try to run the application again and I get another annoying error message:

ID3037: The specified request failed.

Unfortunately, this is a very general one. The solution I found was to go into the relying party trust and specify the encryption certificate.

  1. Then I can successfully get the GetToken method to work properly. I did also notice one other variation in the ADFS configuration that can lead to a weird error. If you disable a relying party trust and try to run the application again you get the following error:

MSIS3127: The specified request failed.

To resolve this, simply enable the relying party trust.

Conclusion

I have found that much of the work with ADFS goes by the principle, “no guts, no glory,” and I wish it were easier. There seem to be a large number of errors that you can receive without a lot of helpful information for helping you resolve them. Hopefully these error resolutions will help you and I will be sure to post any other workarounds I find as I get further down the road of implementing ADFS.

Thanks,

Advertisements

, ,

10 Comments