Search code examples
wifadfs

Convert Identity Foundation Token to ClaimsPrincipal


I'm working on a console application as a proof of concept for authentication over AD FS. The code I have so far is

using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.ServiceModel;
using System.ServiceModel.Security;
using System.Xml;
using Thinktecture.IdentityModel.WSTrust;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var factory = new WSTrustChannelFactory(new WindowsWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress("https://dcadfs.security.net/adfs/services/trust/13/windowsmixed"))
            {
                TrustVersion = TrustVersion.WSTrust13
            };

            var rst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                KeyType = KeyTypes.Bearer,
                AppliesTo = new EndpointReference("https://dcadfs.security.net/adfs/services/trust/13/windowsmixed")
            };

            var channel = factory.CreateChannel();
            var genericToken= channel.Issue(rst) as GenericXmlSecurityToken;

            if (genericToken != null)
            {
                var sh = new WindowsUserNameSecurityTokenHandler();
                //Next line errors with ID4065: Cannot read security token. Exepected elemt is username
                var token = sh.ReadToken(new XmlTextReader(new StringReader(genericToken.TokenXml.OuterXml)));
                var claimsPrincipal = new ClaimsPrincipal(sh.ValidateToken(token2).First());
            }           

        }
    }
}

It fails on ReadToken with expected name element error, I think I'm probably using the wrong handler/initializing it wrong?

I also think I'm missing a couple of other points

  1. At no point am I identitying to AD FS who the relying party is.
  2. I was unsure what to set AppliesTo to as I'm not using a service so I've set it to the AD FS endpoint.

Any advice on either of those would be great.

Really struggling to find examples of this outside of WCF/Configuration based approach. I'm trying to get it all in code to give me a better understanding of how it all works.


Solution

  • 1 and 2 are related - the AppliesTo specifies the RP in ADFS.

    What comes back is a SAML token - so you need to use the SamlSecurityTokenHandler to read the token (not WindowsUserName…).