6

I'm trying to understand what I need to develop a framework using WCF, Claims and ADFS 3.0. The internal users will authenticate against Active Directory, External User authenticate against SQL Server table and the authorization is stored in database tables implementing groups and permission. I am creating a API using WCF not Web Api or OWIN.

I'm not interested in using Identity Server or 3rd party products, I just want to know how I create a Custom Security Token Service to read from my membership table and set claims via my Groups and Permissions table.

I can find no information on any of this. There is no Identity and Access control in Visual Studio 2015 and there seems to be nothing using WCF, only using Web Api, OWIN and MVC?

3
  • Building a custom STS is not a good idea. It is very hard to get everything right and a lot of things fall over if you get it wrong. Configure a maintained product instead.
    – flup
    Commented Oct 5, 2015 at 16:41
  • Maintained product, can you suggest one. I've written tons of .net membership providers that are never a good idea and I don't have the option of using a 3rd party project. I'm up to the challenge though if someone can point me in the right direction instead of just saying its not a good idea. Can you give me more than that?
    – Fab
    Commented Oct 7, 2015 at 18:25
  • Identity Server in specific, why would that be a bad idea?
    – flup
    Commented Oct 7, 2015 at 19:08

2 Answers 2

3

When I' am developing claims aware WCF application like yours, I ran through this link that makes me understood how it works. The only thing that is not quite similar to your needs is that it is not ADFS 3.0.

And I don't think you can use both ADFS for internal user and SQL for external "like membership" at the same time/together. All I know is that you can trust other company's ADFS as other identity provider.

If you are referring to How to Build Claims Aware WCF here are some available links.

Nonetheless, the link is still active that support .Net 4.5 & 4.6 and WIF is already part of the framework unlike before that you need to install WIF.

Below is the fragment of my WCF Service configuration :

Bindings

<bindings>
    <ws2007FederationHttpBinding>
        <binding name="ws2007FederationHttpBinding">
            <security mode="TransportWithMessageCredential">
                <message establishSecurityContext="false" negotiateServiceCredential="false">
                    <issuerMetadata address="https://<adfs server>:9643/adfs/services/trust/mex"/>
                    <issuer address="https://<asfs aserver>:9643/adfs/services/trust/13/usernamemixed"/>
                </message>
            </security>
        </binding>
    </ws2007FederationHttpBinding>
</bindings>

Identity Configuration

<system.identityModel>
    <identityConfiguration name="serviceidentity">
        <audienceUris mode="Never">
            <add value="https://localhost/FedSecurity/"/>
        </audienceUris>
        <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
            <authority name="http://<asfs aserver>:9643/adfs/services/trust">
                <keys >
                    <add thumbprint="8D6BF173ERERERFDFE9CE9CD0FB57FB57A5D68403EA88" name="http://<asfs aserver>:9643/adfs/services/trust" />
                </keys>
                <validIssuers>
                    <add name="http://<asfs aserver>:9643/adfs/services/trust" />
                </validIssuers>
            </authority>
        </issuerNameRegistry>
        <!--certificationValidationMode set to "None" by the the Identity and Access Tool for Visual Studio. For development purposes.-->
        <certificateValidation certificateValidationMode="None" />
    </identityConfiguration>
</system.identityModel>

Fragment Configuration of my WCF Client

<system.serviceModel>
        <bindings>
            <ws2007FederationHttpBinding>
                <binding name="ws2007FederationHttpBinding">
                    <security mode="TransportWithMessageCredential">
                        <message establishSecurityContext="false">
                            <issuer address="https://<adfs server>:9643/adfs/services/trust/13/usernamemixed"
                                binding="ws2007HttpBinding" bindingConfiguration="https://<adfs server>:9643/adfs/services/trust/13/usernamemixed" />
                            <issuerMetadata address="https://<adfs server>:9643/adfs/services/trust/mex" />
                            <tokenRequestParameters>
                                <trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
                                    <trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</trust:KeyType>
                                    <trust:KeySize xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">256</trust:KeySize>
                                    <trust:KeyWrapAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p</trust:KeyWrapAlgorithm>
                                    <trust:EncryptWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptWith>
                                    <trust:SignWith xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2000/09/xmldsig#hmac-sha1</trust:SignWith>
                                    <trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
                                    <trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
                                </trust:SecondaryParameters>
                            </tokenRequestParameters>
                        </message>
                    </security>
                </binding>
            </ws2007FederationHttpBinding>
            <ws2007HttpBinding>
                <binding name="https://<adfs server>:9643/adfs/services/trust/13/usernamemixed">
                    <security mode="TransportWithMessageCredential">
                        <transport clientCredentialType="None" />
                        <message clientCredentialType="UserName" establishSecurityContext="false" />
                    </security>
                </binding>
            </ws2007HttpBinding>
        </bindings>
        <client>
            <endpoint address="https://localhost/FedSecurity/CloudService.svc"
                binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBinding"
                contract="CloudBeta.ICloudSevice" name="ws2007FederationHttpBinding" />
        </client>
</system.serviceModel>

Additional info :

  • I used ADFS 2.0 with UserName authentication with credential added in our active directory
  • Adding of relying Party was not discuss here but needed.
  • Certificate for token encryption/decryption is also required ( Party of AFDS )
  • Adding of claims in ADFS

I hope this information would help you!

1
  • 2
    Too bad I get "This Topic Is No Longer Available", that's what I'm saying. Everything is either outdated, tools no longer exists and no information on using ADFS to authenticate AD for domain users and against a membership database for non domain users using custom STS.
    – Fab
    Commented Sep 24, 2015 at 14:37
1

This article seems to have a good start for you, http://southworks.com/blog/2007/03/11/the-holly-grail-of-enterprise-soa-security/

and here is the code that I use in my MVC app (not WCF, but many of the things that need to be done are the same)

var claims = new List<Claim>()
            {
                new Claim(ClaimTypes.Name, result.UserName),
                new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", result.Email),
                new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
                    result.Email),
                new Claim("UserId", result.Id.ToString(CultureInfo.InvariantCulture)),
                new Claim("UserName", result.UserName),
                new Claim("FirstName", result.FirstName)
            };

        //load claims from database here
        claims.AddRange(result.Roles.Select(role => new Claim(ClaimTypes.Role, role.Name)));

        var id = new ClaimsIdentity(claims, "Forms");
        var cp = new ClaimsPrincipal(id);
        var token = new SessionSecurityToken(cp)
        {
            IsPersistent = false

        };

        Session["authToken"] = token;

        var sam = FederatedAuthentication.SessionAuthenticationModule;
        sam.WriteSessionTokenToCookie(token);

Not the answer you're looking for? Browse other questions tagged or ask your own question.