Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security

Security in WIF

4.83/5 (8 votes)
25 Aug 2015CPOL7 min read 14.8K  
In this post, we’ll focus on security.

Security WIF Future Processing

In this post, we’ll focus on security. We’ll try to prove that claims base authentication is safe. As we remember, SAML tokens are issued by “trusted” STS. But what exactly does “trusted” issuer mean? In this post, we’ll try to find the definition of “trusted issuer”, a list of attributes which decide that issuer is trusted. The fundamental “security concept” is based on four aspects:

  • Authentication
  • Authorization
  • Integrity
  • Confidentiality

WIF approach to authentication and authorization mechanisms has been described in the previous post, today we focus on Integrity and Confidentiality. The Integrity warrants that data has not been altered (intentionally or unintentionally) between "there" and "here," or between "then" and "now." The Confidentiality protects sensitive data - data can’t be read with the exception of the receiver(s) they were explicitly intended for. Windows Identity Foundation to achieve “integrity and confidentiality” requirements uses certificates and Public Key Infrastructure concept. As we remember, STS is a special type of web service (WCF service) based on WS-Trust protocol. WCF provides mechanisms which allow to protect communication on two levels: Transport and Message. When using transport security, the user credentials and claims are passed by using the transport layer (e.g. Secure Sockets Layer (SSL)). When using message security, the user credentials and claims are encapsulated in every message with the use of the WS-Security specification to secure messages. These two protection levels are the basis of communication security in web services (and WCF).

WIF Security

Additionally, WIF has its own mechanisms (and in this post, we focus on them) which protect issued tokens. The token is digitally signed by token issuer when created, so that it can be verified at the receiver’s end. The token can be also encrypted (optionally). A digital signature is basically a way to ensure that the token is authentic. It means that you know who created the token and you know that it has not been altered in any way since that person created it. (More information about digital signature can be found here).

SAML Token Signature

As we remember, token can contain information about the user, roles or permissions, and this makes for a very flexible authorization model. Those pieces of information are signed by STS Signing Certificate. In our solution, this certificate (with private key) is stored in Local Machine Personal store (STS uses certificate thumbprint to identify proper certificate).

Local Machine Personal Store - Future Processing

Figure 1. Local Machine Personal Store

The SAML token signature is based on xmldsig standard. An XML Signature consists of a Signature element in the http://www.w3.org/2000/09/xmldsig# namespace. In the picture below, the typical SAML token signature element has been presented.

the typical SAML token signature element Future Processing

The signature (except the one required by standard SignedInfo element) contains KeyInfo element (standard says that it is an optional element), which contains information about Signing Certificate (entire Signing Certificate with public key, without private key, is attached to signature). Based on this certificate, a client decides that token has been issued by trusted STS.

Trusted Issuer

The typical communication between Relying Party consists of a few basic steps:

  1. The RP initializes and sends (via application) authentication request to the STS. Request contains client's credentials required to authenticate the client.
  2. The STS validates the client's credentials, generates and sends an issued token to the client.
  3. The RP validates the received token.

Now, we try to explain what exactly “RP validates received token” means. At first, RP verifies whether token is issued by issuer from the trusted list (configuration file system.identityModel->issuerNameRegistry->trustedIssuers)

XML
<issuernameregistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, 
System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <trustedissuers>
          <!-- Issuer thumbprint. -->
          <add name="Localhost" 
          thumbprint="5DA000A8A9AE99E5269F283C72911F5D8BE2D6D1">
        </add>
 </trustedissuers>
</issuernameregistry>
Listing 1: Sample trusted issuers configuration

The trustedIssuers section contains a list of trusted issuer, one issuer is identified by thumbprint. As we remember, STS signing certificate is attached to SAML token signature, and thumbprint of this certificate must be on the trusted issuer list in the configuration file. It is the first (required) step of validation. The next steps depend on our configuration. In our example, we don’t use additional mechanism to validate the STS signing certificate. Now, we try to analyze which possible solutions offer WIF. The certificateValidation setting is one of the most imported elements, which decide how the issued token will be validated. The certificateValidation allows to define two validation aspects:

  • Certificate Validation Mode (None||ChainTrust||PeerTrust||PeerOrChainTrust||Custom)
  • Revocation Mode (NoCheck||Offline||Online)

and trusted Store Location (CurrentLocation||LocalMachine). Now, in few words (WIF security mechanisms based on PKI - more about PKI and certificates in the next series of posts), we’ll try to explain how it works. Each certificate has its own issuer (in our solution we use self-sign certificate – it means that each certificate is signed by the same entity whose identity it certifies). When certificateValidationMode doesn’t equal None, we should (to positive verification) install an issuer certificate of a signing certificate in Store Location. Each certificate can be also revoked - this operation can be done via Certificate Revocation List or Online Certificate Protocol. The Revocation Mode describes how certificate status will be validated. Let’s check sample configuration. At first, we set in our Relying Party application certificateValidationMode=’PeerOrChainTrust’ and try to login to STS. The RP application throws the following exception:

Certification validation exception Future Processing

Figure 2. Certification validation exception

To solve this problem, we should add STS certificate to Trusted People Certificates in Current User Store.

SAML Token Encryption

WIF also allows to enable token encryption mechanism. When encryption is enabled, each token sent to Relying Party is encrypted by encryption certificate. To decrypt token, RP should have proper private key (which corresponds with public key from encryption certificate). If we have multiple RPs for the STS, we should select the certificate that is specific to the RP request (STSService class GetScope method). We can enable encryption via choose encryption certificate in STS configuration file.

XML
<add key="EncryptingCertificateName" value="??5DA000A8A9AE99E5269F283C72911F5D8BE2D6D1">
</add>
Listing 2: Sample STS encryption configuration

In our example, we use signing certificate (via set certificate thumbprint) - we should remember that we don’t need private key for encryption. Now, when we try to login to STS by our Relying Party application, RP throws the following error:

Token decryption error Future Processing

Figure 3. Token decryption error

This kind of error means that RP can’t decrypt the received token, because it can’t find a proper certificate with private key. The received token is encrypted via XML Encryption Syntax – it means that the received token should contain information about certificate required to decrypt it (KeyInfo element).

Encrypted token Future Processing

Figure 4. Encrypted token

Information on how to encrypt your claims is available, however, the information is a bit scattered. Some pieces of information may be found here:

The decrypting operation is a little bit complicated, unfortunately, I didn’t find a simple, elegant solution (we can use the approach that was presented in Decrypting a Security Token post. In our solution, we try to find a workaround for this kind of problem. If we remove tags SecurityTokenReference, we can use EncryptedXml class to decrypt token. This solution may be not elegant, but it works.

C#
private ClaimsPrincipal CreateUserIdentityFromSecurityToken(SecurityToken token)
{
    var genericToken = token as GenericXmlSecurityToken;
    var handlers =
        FederatedAuthentication.FederationConfiguration.IdentityConfiguration
            .SecurityTokenHandlerCollectionManager.SecurityTokenHandlerCollections.First();
    var decryptedToken = DecryptToken(genericToken.TokenXml.OuterXml);
    var cToken = handlers.ReadToken(new XmlTextReader(new StringReader(decryptedToken)));
    var identity = handlers.ValidateToken(cToken).First();
    var userIdenity = new ClaimsPrincipal(identity);
    return userIdenity;
}

private static string DecryptToken(string encryptedToken)
{
    var content =
        encryptedToken.Replace(
            "<o:securitytokenreference xmlns:o="\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"">",
            string.Empty);
    content = content.Replace("</o:securitytokenreference>", string.Empty);
    var xmlData = new XmlDocument();
    xmlData.LoadXml(content);
    var exml = new EncryptedXml(xmlData);
    exml.DecryptDocument();
    return xmlData.InnerXml;
}
Listing 3: Security Token Decryption

We should remember that certificate described by X509Data should be added to Relying Party application “Personal Certificate Store”. In our example, the application uses My User Account Store Location.

SAML Token Expiry Time

Each token issued by STS has set NotBefore and NotOnOrAfter properties, which define time when token is valid. The Request Security Token contains special field Lifetime, which allows to define SAML token lifetime (in our example, STS sets token lifetime to 30 minutes, by default).

JavaScript
var rst = new RequestSecurityToken(RequestTypes.Issue);
  rst.AppliesTo = new EndpointReference("https://RelyingParty/*");
  rst.Lifetime = new Lifetime(DateTime.UtcNow, DateTime.Now.AddMinutes(10));
Listing 4: Request Security Token Lifetime

If LifeTime is set, STS returns token with requested token expiry. A Relying Party application should validate token lifetime and “renew” it when required.

C#
private static void ValidateTokenExpiry(SecurityToken token)
      {
          if (token.ValidFrom > DateTime.UtcNow)
          {
              throw new SecurityTokenNotYetValidException();
          }

          if (token.ValidTo < DateTime.UtcNow)
          {
              throw new SecurityTokenExpiredException();
          }
      }
Listing 5: Security Token LifeTime validation

Summary

In this article, aspects of WIF security approach have been presented. We have implemented working example solution, which demonstrates how integrity and confidentiality mechanisms work. Now, we can define requirements for “Trusted Issuer” and we know which basic WIF settings define “security”. The next article will focus on Public Key Infrastructure. We’ll try to explain what exactly PKI means and how to prepare certificates for STS.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)