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
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.
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…).