Sunday, 1 June 2014

Part2: Creating a SAML 2.0 Token using WIF 4.5

In Part 1 I demonstrated how to generate a simple SAML2 token using the WIF 4.5 libraries. To finish this out I will now describe how to read a SAML2 token that was previously generated with the SamlTokenProcessor class.

Read Token

In order to read an encrypted and signed SAML2 token an instance of a SecurityTokenHandler class is required that has the correct configuration. Specifically we need an instance of an Saml2SecurityTokenHandler class. It is possible to create an instance of this class and configure it through code, an alternate approach is to use the WIF configuration classes to configure and create an instance of a Saml2SecurityTokenHandler. This is a preferred approach because it provides some level of flexibility to the SamlTokenProcessor. Below is an example of how to create the Saml2SecurityTokenHandler from the IdentityConfiguration.
IdentityConfiguration configuration = new IdentityConfiguration();

_saml2SecurityTokenHandler = configuration.SecurityTokenHandlers[typeof(Saml2SecurityToken)];

_saml2SecurityTokenHandler.Configuration.ServiceTokenResolver = 
 new X509CertificateStoreTokenResolver(StoreName.My, StoreLocation.CurrentUser);

The Saml2SecurityTokenHandler instance requires a security token resolver. This is a class that is able to resolve the signing and encrypting certificates that where originally used to create the SAML2 token. The IdentityConfiguration class expects a configuration section in the application configuration file.
<configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </configSections>

The configuration required for the example application is as follows, this configuration is a basic configuration which is used for token validation, more on this later. The configuration can be used to configure replay detection for tokens or the maximum clock skew between the token generator and the token consumer.
<system.identityModel>
 <identityConfiguration>
  <audienceUris>
   <add value="http://rp.com/" />
  </audienceUris>
  <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
   <trustedIssuers>
    <add thumbprint="‎0D274A03BDCA95015E712E2808F917C93159ED1B"/>
   </trustedIssuers>
  </issuerNameRegistry>
 </identityConfiguration>
</system.identityModel>

Note: The thumbprint element value must be set to the thumbprint of the STS identity certificate that was generated or acquired from a CA. Also be careful copy and pasting the thumbprint as it can copy with BOM data in the string.

Now that we have an instance of a Saml2SecurityTokenHandler it can be used to read a token from a stream.
public SecurityToken ReadSecurityToken(Stream stream)
{
 SecurityToken securityToken;

 using(XmlReader rdr = new XmlTextReader(stream))
 {
  securityToken = _saml2SecurityTokenHandler.ReadToken(rdr);
 }

 return securityToken;
}

Validate Token


The VerifySecurityToken method of the SamlTokenProcessor class can verify a SAML2 token against the configuration specified in the configuration file. A prerequisite to verifying the SAML2 token generated is to ensure that the signing token is present in the certificate store under TrustedPeople.

image

The VerifySecurityToken method will verify the attributes of the token against the configuration. As a test the audienceUri can be modified to cause the  verification to fail.
<audienceUris>
 <add value="http://rp2.com/" />
</audienceUris>
When the test application is run using this configuration an AudienceUriValidationFailedException exception will be thrown.
 
System.IdentityModel.Tokens.AudienceUriValidationFailedException: ID1038: The AudienceRestrictionCondition was not valid because the specified Audience is not present in AudienceUris.
Audience: 'http://rp.com/'
   at System.IdentityModel.Tokens.Saml2SecurityTokenHandler.ValidateToken(SecurityToken token)
   at CoreMemoryDump.Saml.SamlTokenProcessor.VerifySecurityToken(SecurityToken securityToken) in c:\Users\Office\Documents\Visual Studio 2012\Projects\CoreMemoryDump.Saml\CoreMemoryDump.Saml\SamlToken
Processor.cs:line 92
   at CoreMemoryDump.SamlTest.Program.Main(String[] args) in c:\Users\Office\Documents\Visual Studio 2012\Projects\CoreMemoryDump.Saml\CoreMemoryDump.SamlTest\Program.cs:line 47

Similarly modifying the TrustedIssuers list will elicit an exception indicating that the issuer is not trusted.

Summary


The intent of this example code was to show that it is possible to generate, read and verify a SAML token using the base libraries from the WIF 4.5 framework. This example provides a basic implementation that can be extended to enable greater flexibility for generating SAML tokens.  


The code is available here: GitHub DumpingCoreMemory.Saml

Thursday, 1 May 2014

Part1: Creating a SAML 2.0 Token using WIF 4.5

To create a SAML token we will need a set of certificates for the Relying Party (RP) and Secure Token Service (STS). These certificates plus keys will be used for the signing and encryption of the SAML 2.0 token. In the  part 2 of this series the keys will be used for signature verification and decryption.
First we need a certificate for the certificate authority that will be used as the issuer for the STS and Relying Party. Note you will be prompted for a password for the CA private key file, use a simple password as you will be prompted for this password when creating the certificates for the RP.
makecert -n "CN=RootCATest" -r -sv RootCATest.pvk RootCATest.cer
To create the certificate for the STS and Relying Party the following command can be executed from a batch file.
makecert -sk %1 -iv RootCATest.pvk -n CN=%1 -ic RootCATest.cer –sr localmachine -ss my -sky exchange -pe %1.cer
For example createcert.bat RP will create the certificate for the RP. Note that all of the certificate creation commands must be executed from a VS2012/2010 command prompt that is running with administrator privileges.
Later we will place the certificates in the relevant certificate stores for use later in the process of developing the SAML token generator.

Token Generation

To generate a SAML token a SecurityTokenDescriptor must be created. This is a place holder for the attributes of an issued token.
private SecurityTokenDescriptor BuildBaseSecurityTokenDescriptor(Uri appliesToAddress, String issuer, TimeSpan validityPeriod, 
            IEnumerable<Claim> claims, X509Certificate2 encryptingCertificate, X509Certificate2 signingCertificate)
{
  DateTime utcNow = DateTime.UtcNow;
  SecurityTokenDescriptor securityTokenDescriptor = new SecurityTokenDescriptor();
  securityTokenDescriptor.AppliesToAddress = appliesToAddress.ToString();
  securityTokenDescriptor.TokenIssuerName = issuer;
  securityTokenDescriptor.Lifetime = new Lifetime(utcNow, utcNow.Add(validityPeriod));
  securityTokenDescriptor.SigningCredentials = new X509SigningCredentials(signingCertificate);
  securityTokenDescriptor.Subject = new ClaimsIdentity(claims);
  securityTokenDescriptor.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";
  securityTokenDescriptor.EncryptingCredentials = new EncryptedKeyEncryptingCredentials(encryptingCertificate);

  return securityTokenDescriptor;
}

To generate the token a SecurityTokenHandlerCollection is constructed with a collection of SecurityToken handlers. To generate a SAML token we use a Saml2SecurityTokenHandler, to generate the Saml2 token and a EncryptedSecurityTokenHandler to encrypt and sign the token when the token is serialized.
public SamlTokenProcessor()
{
  _securityTokenHandlerCollection = new SecurityTokenHandlerCollection();
  _securityTokenHandlerCollection.Add(new Saml2SecurityTokenHandler());
  _securityTokenHandlerCollection.Add(new EncryptedSecurityTokenHandler());
}

Calling the CreateSecurityToken method generates a Saml2SecurityToken instance.
SamlTokenProcessor processor = new SamlTokenProcessor();

X509Certificate2 encryptingCertificate = CertificateResolver.ResolveCertificate(StoreLocation.LocalMachine, StoreName.My, "CN=RP");
X509Certificate2 signingCertificate = CertificateResolver.ResolveCertificate(StoreLocation.LocalMachine, StoreName.My, "CN=STS");

List<Claim> claims = new List<Claim>() { new Claim("Claim", "Value") };

SecurityToken token = processor.CreateSecurityToken(new Uri("http://rp.com"), "sts", new TimeSpan(0, 0, 10), claims, 
 encryptingCertificate, signingCertificate);

using(Stream stream = new FileStream("token.xml", FileMode.OpenOrCreate))
{
 processor.SerializeSecurityToken(token, stream);
}

The SerializeSecurityToken method serializes the token to a stream. This applies the signing and encryption to the resultant tokens XML representation. Below is an example token shortenedshortend for brevity.
<?xml version="1.0" encoding="utf-8"?>
<EncryptedAssertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
  <xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
      <e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
          <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        </e:EncryptionMethod>
        <KeyInfo>
          <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <X509Data>
              <X509IssuerSerial>
                <X509IssuerName>CN=RootCATest</X509IssuerName>
                <X509SerialNumber>78425684050690387325969986111748521388</X509SerialNumber>
              </X509IssuerSerial>
            </X509Data>
          </o:SecurityTokenReference>
        </KeyInfo>
        <e:CipherData>
          <e:CipherValue>NSmOOCR6CzGCj+lY2PF....</e:CipherValue>
        </e:CipherData>
      </e:EncryptedKey>
    </KeyInfo>
    <xenc:CipherData>
      <xenc:CipherValue>e5kGcfcel/YN+Qjz....</xenc:CipherValue>
    </xenc:CipherData>
  </xenc:EncryptedData>
</EncryptedAssertion>

In the second part of this two part blog I will demonstrate how to reverse the process and extract the claims from the encrypted SAML2 token.

The code is available here: GitHub DumpingCoreMemory.Saml

Tuesday, 1 April 2014

Creating and Consuming SAML 2.0 Tokens using WIF

With the introduction of Windows Identity Foundation 4.5 Microsoft removed the Visual Studio templates that could be used to generate a custom WCF STS service. The custom STS could then be used to issue SAML 2.0 tokens based on custom credentials passed with the WS-Trust request to the custom STS.

The underlying classes are still available to use for creating a custom STS, without the templates available it is still possible to create a custom WCF STS service but it requires a bit more effort.

There is however an alternate means to generate SAML 2.0 tokens using WIF that forgoes the need to create a custom STS. This is useful in scenarios involving proprietary systems that have custom protocols and authentication, that also do not lend themselves well to integration with ADFS etc.

To explain how this can be achieved I will break the problem down into two parts:

Part 1: Creating a SAML 2.0 Token using WIF 4.5

Part2: Consuming a SAML 2.0 Token using WIF 4.5

Saturday, 22 March 2014

mfNordic library released on Codeplex

As part of the development effort for the home monitoring system I implemented a .net micro framework library for interfacing to a Nordic semiconductor NRF24L01P radio module. I have released the source code on https://mfnordic.codeplex.com/ under the MS-PL license.

Using the library

var radio = new Nrf24L01P(SPI_Devices.SPI1, Pins.GPIO_PIN_D0, Pins.GPIO_PIN_D1, Pins.GPIO_PIN_D2);

The Nrf24L01P class needs the SPI port, the chips select, chip enable and interrupt line that the physical radio device is connected too.

The radio can be left with the default settings or can be configured via properties. Below are some example properties.

 radio.Features = radio.Features | Feature.AckPayload | Feature.DynamicPayload;
 //Note the number of address bytes must match the configured/default radio.AddressWidth property
 radio.TransmitAddress = new byte[] {0,0,0,0,0};
 radio.Mode = Mode.Receiver;
 radio.Channel = 125;

The class will raise events when data is transmitted or received or errors occur. These events can be hooked, each has an event argument that contains relevant context information.

 _radio.OnDataReceived += RadioOnDataReceived;
 _radio.OnTransmitFailed += RadioOnTransmitFailed;
 _radio.OnTransmitSuccess += RadioOnTransmitSucess;
 _radio.OnDataReceiveFailure += RadioDataReceivedFailure;

 static void RadioDataReceivedFailure(object sender, DataReceiveFailureEventArgs e)
 {
  Debug.Print("OnDataReceiveFailure occured on Pipe: " + e.Pipe);
 }

 static void RadioOnDataReceived(object sender, DataReceivedEventArgs e)
 {
  Debug.Print("RadioOnDataReceived occured on Pipe: " + e.Pipe + " " + e.Payload.Length + "bytes received");
 }

The NRF24L01P supports up to 6 logical radio data pipelines, all sharing some basic settings namely:

  • CRC enabled/disabled (CRC always enabled when Enhanced ShockBurst™ is enabled)
  • CRC encoding scheme
  • RX address width
  • Frequency channel
  • Air data rate
  • LNA gain

The library exposes the data pipelines via an indexer. This allows properties and methods of individual pipes to be accessed.

 radio[Pipe.Pipe0].AutoAcknowledgment = true;
 radio[Pipe.Pipe0].DynamicPayload = true;
 radio[Pipe.Pipe0].Enabled = true;

Acknowledge packets can be queued on a given pipe line using the QueueAcknowledgePacket method.

 radio[Pipe.Pipe0].QueueAcknowledgePacket(new byte[] {0,1,2,3});

In transmitter mode packets can be transmitted using the Transmit method. The Boolean parameter indicates if the packet should be transmitted with an expected acknowledge from the receiver.

 radio.Transmit(new byte[] { 0, 1, 2, 3 }, false);

Finally to power the radio devices RF section up.

    radio.PowerUp = true;

To enable the  radio device, which will set the CE signal to the device, which will active the RX or TX mode of the radio device.

 radio.Enable = true;

Wednesday, 19 March 2014

Home Monitoring System – Version 1.0

Having worked on my home monitoring system on an off for the last number of weeks I have finally gotten to version 1 for the host board and the sensor nodes.

Temperature And Humidity Sensor Node

I completed the development and testing of the wireless temperature and humidity sensor nodes.

WP_20140319_001

This board was installed in an enclosure as shown below. The board was designed to fit snuggly into the enclosure which takes two AAA batteries to power the sensor.

WP_20140319_002WP_20140319_003

The sensor implements a simple channel scanning and handshake protocol which allows it to determine the radio frequency channel the wireless hub is listening for packets. When the channel is found by sending a NodeHello packet to which the wireless hub replies with a NodeHelloAck packet. The NodeHelloAck packet contains configuration data that the node uses to setup it logical RF channel.

Once the handshake has completed the node enters a loop where it sleeps for a period, which is provided as part of the handshake data, wakes up and transmits the latest temperature, humidity and battery voltage readings to the wireless base station.

Wireless Hub

I chose a Netduino Plus 2 as the hardware for the wireless hub. The hardware setup is pretty straight forward. An NRF24L01P radio module is connected to power and the SPI port on the Netduino.

WP_20140319_004

The Netduino implements a simple web server, based on embeddedwebserver, that hosts a set of pages that renders the sensor data from each of the sensors, allows configuration changes to be made and log file viewing. Since the Netduino has limited memory and CPU most of the processing for data rending is offloaded onto the browser. The sensor data page uses a JavaScript graphing component called Rickshaw. The pages are rendered on the client side browser as a single page application using AngularJs as the MVVM framework and Bootstrap to provide a responsive UI that scales to different device screen sizes.

Sensor Data Display

Monitoring

The sensor data is rendered on the main page of the application. The interface allows selection of a number of days of data. Multiple sensor feeds can be rendered, the graphing component supports hoover details when the mouse is over a point on the graph.

Nodes Configuration

Nodes

The nodes configuration page shows active nodes and the node types. The nodes name can be modified.

System Log

log

The logging level is set on the configuration page from 0 to 4, 0 = None 4 = Debug

Configuration

Configuration

The configuration page allows the following to be configured:

  • The radio channel
  • The radio device address
  • The log level
    • None
    • Info
    • Warn
    • Error
    • Debug
  • Update interval, the rate that the sensor will push readings

Future Additions

  • Minor web UI clean up and changes
  • The ability to export sensor data
  • The ability to have a node release its allocated id

I would also like to add some additional sensor types, maybe air quality, water,power etc. Later I would like to use the data gathered to directly control the space heating from the netduino, via a relay node that can be used to advance and retard the heating system based on evaluation of the temperature data. For example on a very cold day fire up the heat at an earlier time than the heating control system would normally.

Monday, 20 January 2014

Home Monitoring System – Sensor Node

Finally the boards that I designed for the home monitoring system arrived from OSH Park. Son now I can get down to building the the boards. The photo below shows the board in the bottom half of the enclosure that I am planning to use.
WP_20140116_003
To ensure that I don't release the blue smoke I decided to build and test the node in a number of steps. For the first step I soldered the components of the power supply and tested the output voltage.
WP_20140116_004
This first step was successful connecting a bench power supply set to 2.8 volts yielded an output of 3.3 volts.
WP_20140116_005
The next step was to solder the remaining capacitors and ICs and resistors. When designing the board I used 0603 for the resistor and capacitor footprints. This was a mistake because they are difficult to hand solder due to the size. Next time I will use the next size up.

The other SMD that was difficult to solder was the LCC8 humidity sensor. In fact I initially soldered it on upside down and had to remove it, in the process of which I destroyed the part. Below is an image of the final board with the debug and ISP header but without the radio module this will be added later.
WP_20140117_004
When I initially attached the ISP I found that it would not connect to the board. The reason for this was that the ISP clock was set to the default of 1Mhz. The ATmega48PA is shipped with internal RC oscillator at 8.0MHz and with the fuse CKDIV8 programmed, resulting in 1.0MHz system clock. Reducing the ISP clock to 1/4 of the CPU frequency resolved the issue.
AVRSettings
When I resolved the connection issue to the device I was able to flash the firmware and start testing the sensor board. The first check was to determine if the ADC voltage monitoring circuit worked. This is where I ran into another problem. I powered the board with a bench power supply @ 2.8 volts. Reading the battery voltage via the ADC resulted in a value of 2.1 volts. After examining the battery sensing circuit it initially looked like the p channel FET was not switching on fully causing a voltage drop of 0.6 volts across the Source to Gate. Checking the Drain voltage measured 2.1 volts which was wrong because it was not switched on, i.e. 0 volts applied.

On a hunch I checked the datasheet of the FET against the footprint on the board. I discovered the PMBFJ177 footprint is different the Gate and Drain are interchanged. I will need to get another J177 FET that matches the board footprint.

Once these issues where resolved I was able to debug the code that reads the humidity and temperature from the CC2D33S sensor using the AVR dragon.

The next step is to add the radio module and figure out a strategy to debug and test the radio module and its code.

Saturday, 4 January 2014

Home Monitoring System – Phase 1

Having spent a great deal of time and effort upgrading my 1970s built home to make it habitable in the winter, yes it was really that bad, and as an added benefit improve its energy efficiency. Now that the improvements have been made I would now like to monitor the effectiveness or lack thereof if that happens to be the case. Unfortunately I have will have no data to compare the data acquired from this proposed system, on the up side I will have data to hopefully make further improvements.

My initial plan is to focus on space heating as this is generally the biggest pain point in older houses.

Goals

  • Capture Temperature and Humidity
    • Temperature and Humidity are related and have an effect on the Thermal Comfort of the living space
  • Small Size Sensors
    • The sensors must be small and inconspicuous as I will be placing a number of them around the house
  • Battery powered
    • AA or AAA batteries, preferably AAA due to the size requirement
  • Efficient Power Usage
    • Aim to be operational for minimum of a year without requiring a battery change

Solution

Sensor

For phase 1 the wireless sensors will communicate with the Control Hub which will log and aggregate the data that the sensor nodes periodically send. The control hub will expose a set of web pages to manage the sensor network devices and view and export data.

Sensor Node

The sensor node is based around an Atmel ATMEGA48PA 8-bit CPU. This was chosen due to the fact that it is a picoPower device which means that it is capable minimising power down to 0.1µA in sleep mode.

The wireless link will use an nRF24L01+ module these are extremely cheap and can be picked up on eBay for 80 cent which is remarkable given the chip itself is about 2-3 euro in single unit prices. This device operates in the 2.4Ghz space and is optimised for low power applications. Consuming sub μA current in power down mode.

To measure humidity and temperature the sensor chosen was the CC2D33S sensor from GE. This sensor has a 3% accuracy and operates from –40 to 125°C. It costs about 6 ~ 8 euro in single unit quantity. It has an I2C bus interface and can operate in a sleep mode where it consumes 0.6 µA (typical) and 750 µA (typical) when operating. It also has a small footprint compared to some of the cheaper Chinese sensors available.

For power management I decided to add a boost regulator based on the 3.3 volt version of the AAT1217 chip. This was chosen due to cost and the fact that it does not need an external Schottky diode which are difficult to find with a low forward voltage drop and reasonable load current.

PowerSupply

The boost regulator will operate down to 0.5 volts ensuring that the sensor node will remain operational as the input voltage drops.

I have also added the option of not installing the boost convertor and its components by placing a shut from VBAT to VCC.

Shunt

To monitor the input voltage to the sensor node I added a simple FET switch switch to a resistor that that the microcontroller will sample when it is performing a sensor update and send the input voltage, temperature and the humidity data.

BatSense

I will use the following enclosure to house the sensor as its neat and tidy. The PCB to fit the chosen enclosure was designed with KiCad and a small batch was ordered through OSH Park. A render of the PCB is shown below.

i

Once the boards arrive I will begin the building and debugging. I will add some follow up posts recording my progress. I think the main risk to the sensor nodes is the radio module. The 2.4 Ghz band is quite congested and the range performance of the 2.4 Ghz modules can be affected by obstacles such as internal doors, floors and walls.

Control Hub

The Control Hub is the next piece of the system, I have not made much progress on the implementation of this yet. I do however have a set of requirements:

  • Expose a simple web interface
    • To view data
    • To manage the sensor nodes, update interval etc.
  • On board storage
    • Should not require external storage for storing reading
  • Expose  a programmatic interface
    • Maybe some kind of restful interface