Tuesday, 15 May 2012

ACS Rule Groups and Service Identities

In my previous post I walked you through configuring ACS to issue SWT tokens to a client using Service Identities and when it came to configuring the Rule Groups we just left everything as default. I just wanted to expand on this area a little bit as the Rule Group can be very useful when it comes to securing a Relying Party with a Service Identity.

Restricting access

By accepting the defaults when creating the rule group we are essentially telling ACS that we accept ANY Service Identity credentials as valid for the relying party and to just pass on the claims that ACS produces. But what if we want to restrict which Service Identities can authenticate with ACS? Well it's actually very simple, we modify the rule!


By selecting an Input claim type of nameidentifier we are able to instruct ACS to only run this rule when a matching claim and value is found. When authenticating with a Service Identity, ACS will create a nameidentifier claim with the value set to the Service Identity name. We can specify this as our claim value in this rule.

The rule then tells ACS to output the same nameidentifier claim with the same value, effectively passing it through. Of course we could set this up to output a completely different claim and value but for now this is all we need to do. The output claim will then be wrapped up into the SWT token and sent back to the client.

This rule effectively restricts access to the relying party by only accepting the Service Identity matching the claim value.

I can test this by trying to authenticate with the 'RESTClient' service identity which should succeed based on my rule and then using the 'two10na' Service Identity which should fail.

First using 'RESTClient'



This results in a successful response:


Now let's try it using 'two10na':



Access denied! We get a 403 (forbidden) back from ACS because it is unable to successfully run the Rule Group associated with the Relying Party.

Handling SWT Tokens from ACS (Part One)

The full code from this blog is now available on GitHub as a reference implementation.

If you are developing an application that requires claims-based authentication then Windows Azure ACS (Access Control Service) could be the answer to your prayers. ACS can be used as an out-of-the-box STS in this scenario, although this is actually just one small part of its full offering.

If you are committed to using WCF with WS-Federation then your obvious choice will be to setup ACS to provide SAML tokens over it's WS-Federation binding. This is a well documented subject so will not be covered here. But what if your application can't use WCF or you choose not to use WCF? Is ACS still useful to you? Well the answer is yes it is as it comes with an array of other integration options such as OAuth2 and OAuth WRAP. Using these protocols we can request SWT tokens to provide our claims and the aim of this post is to show you how you can do this without using WCF at all.

Configuring ACS

So here's the scenario. You're building a RESTful API and you want to authorise calls to it using claims. ACS can help accelerate the process here as it can be our trusted token provider.

For this demo we'll be using a Service Identity to authenticate with ACS. Service Identities are useful for authenticating applications rather than users as they simply provide a method for an application to pass credentials to the ACS without needing to prompt the user and receive a token back for presentation to the relying party (in this case our REST service).

You can configure Service Identities in ACS on this screen:
ACS Service Identities management

Add the Service Identity

First we need to Add the Service Identity:

Add Service Identity
Give the Service Identity a name, description and select Password for Credential Type. You can also give the credential an Effective date, if we want it activate at a specific time and also an Expiration date at which point the credential will no longer be active. It's very important to remember that credentials expire so make sure you reset this value if you want to continue using it! Alternatively add a new credential to the Service Identity.

So we now have a Service Identity and a Password credential associated with it.

Add a Relying Party

We now need to create a Relying Party in ACS that will establish a trust relationship between the REST API and ACS. To do this navigate to 'Relying party applications' in the ACS control panel. You should see this screen:
Relying Party Applications management

From here we can add a new relying party:
Add Relying party
Give the relying party a name and select 'Enter settings manually' under 'Mode'. Now we must ensure that we enter a value for 'Realm' that matches the URL of the REST API. This is vital as the SWT tokens will be validated against this when we come to make API calls.

For our simple scenario we can leave 'Return URL' and 'Error URL' blank.

Select 'SWT' under Token format and leave the lifetime as default.

Add Relying Party (continued)
We don't need to use any Identity providers so uncheck all boxes. Check 'Create new rule group' under 'Rule Groups'.

Under 'Token signing key' click the 'Generate' button to generate a new Symmetric Key for this relying party. This key will be used to sign the tokens issued from ACS, copy and paste this key to notepad for later. You can add/delete/edit these keys within the 'Certificates and keys' section in the portal. 

Note: There is a default Signing Key within ACS that will be used if you do not create one for your RP but it is a security risk to use the same signing key across all RPs.

Configure the Rule Group

We now need to configure the Rule Group for the relying party. Rule groups act like a pipeline for transforming a set of claims into a new set of claims. Navigate to 'Rule groups' in the portal.

Rule groups management
Click on the 'Default Rule Group for <YOUR RELYING PARTY>' that was created for us when we added the relying party. You should now see this screen:
Edit Rule Group
We need to add a claim rule in order to have ACS process our token request successfully so click on 'Add'.

Add Claim Rule
Select 'Access Control Service' as the input claims for this rule will be generated as a result of authenticating with ACS itself via the Service Identity. We can leave all the other fields as default as we only want to pass through the claims generated by ACS back to our client. If you wanted to add some additional claims to your token you could easily do so here by adding more claim rules that take Any input claim / value and outputs the claim type and value you wish to add.

Request a Token from ACS

We have now configured ACS to receive client credentials and issue an SWT token for a given relying party. So lets test that this works by writing some client code to request a token.



We can use System.Net.WebClient to make a simple HTTP POST request to ACS using the WRAP protocol. By navigating to the 'Application integration' section in the portal we will find a list of URLs we can use to request tokens from the ACS.


In our case we are going to use OAuth WRAP so we need the URL highlighted above.

Set client.BaseAddress to your base ACS URL without the "WRAPv0.9" part, we will tell our WebClient to append that bit later.

We then need to set wrap_name to the Service Identity name we configured earlier, wrap_password to the password credential of our Service Identity and wrap_scope to match the Realm of our Relying Party. The call to client.UploadValues("WRAPv0.9", "POST", values) appends "WRAPv0.9" to our base URL, tells the WebClient object to use HTTP POST and adds our wrap parameters as the data.

The response that comes back from the ACS contains our SWT token, success!



In Part Two I will show you how we can now validate this token and use it to authenticate a RESTful API.