Patrice Cote
Patrice Cote

Reputation: 3716

WIF SAML RequestSecurityToken STS Internal server error

I try to reach my STS to request a token. The code is based on a blog post by @leastprivilege : WCF and Identity in .NET 4.5: External Authentication with WS-Trust. I use the explicit approach (by code).

    private static SecurityToken RequestSecurityToken()
{
            // set up the ws-trust channel factory
            var factory = new WSTrustChannelFactory(
                new UserNameWSTrustBinding(
                  SecurityMode.TransportWithMessageCredential),
                  "https://federation.mydomain/adfs/services/trust/mex") { TrustVersion = TrustVersion.WSTrust13 };

            //factory.Credentials.SupportInteractive = false;
            factory.Credentials.UserName.UserName = "user-pcote";
            factory.Credentials.UserName.Password = "123456";

            // create token request
            var rst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                KeyType = KeyTypes.Symmetric,
                AppliesTo = new EndpointReference("https://myRP/")
            };

            var channel = factory.CreateChannel();
            return channel.Issue(rst);
        }

I can see the XML when copying the STS endpoint adress in my browser, therefore the federation server is reachable. But I always get an internal server error (500) as soon as I issue the token request. Does anybody have an idea what could be my problem here.

Upvotes: 1

Views: 1335

Answers (2)

Patrice Cote
Patrice Cote

Reputation: 3716

Finally managed to get it working by changing the KeyType to KeyTypes.Bearer (since there's no certificate applied to the RP in AD FS). I based myseflf on this website that gives a good explanations on how it all relates :

http://blog.skadefro.dk/2011/09/claimsbased-authentication-and-wcf.html

if we look in Microsoft.IdentityModel.SecurityTokenService.KeyTypes we see we can use Asymmetric, Symmetric or Bearer. Tons of post out there about this.

If you use Asymmetric you as requestor need to supply a key to encrypt the claims with. ( set "UseKey” )

If you use Symmetric the identity provider have all ready been told what certificate to use, to encrypt the claims with.

If you choose Bearer. The token get signed, but claims will not be encrypted. If a token signing certificate have been assigned on the Relying Party, claims will simply not be included at all.

When you request a token, the token gets signed (not encrypted) with a certificate installed on the Identity Provider ( ADFS ). If you add a certificate on a Relying Party Trust (RP) on the ADFS server, the claims inside the token gets encrypted with with that certificate. Only host/applications that have access to the private key of that certificate can now decrypt the token and read the claims. You don’t need to read the claims in order to authenticate your self. For instance if you have a WCF Service you want to call from within an application. You can from within that application still request a token from the ADFS server and then access the WCF service with that Token. As long as the WCF service have access to the private key and can read the claims, your application don’t need it.

private static SecurityToken RequestSecurityToken()
        {

            var binding = new UserNameWSTrustBinding(
                  SecurityMode.TransportWithMessageCredential);

            var factory = new WSTrustChannelFactory(
                binding,
                new EndpointAddress(new Uri("<your_adfs_uri>/adfs/services/trust/13/usernamemixed"), EndpointIdentity.CreateSpnIdentity("host/your.spn.com"))) { TrustVersion = TrustVersion.WSTrust13 };

            factory.Credentials.UserName.UserName = "username";
            factory.Credentials.UserName.Password = "password";

            // create token request
            var rst = new RequestSecurityToken
            {
                RequestType = RequestTypes.Issue,
                KeyType = KeyTypes.Bearer,
                AppliesTo = new EndpointReference(<uri_of_your_relying_party>)
            };

            var channel = factory.CreateChannel();
            try
            {
                var response = channel.Issue(rst);
                return response ;
            }
            catch (Exception e)
            {
                var message = e.Message;
                return null;
            }

        }

Upvotes: 3

Patrice Cote
Patrice Cote

Reputation: 3716

I managed to find the right endpoint (which was /adfs/services/trust/13/usernamemixed) but now I get the following error :

ID4007: The symmetric key inside the requested security token must be encrypted

Upvotes: 0

Related Questions