Microsoft Azure : Azure AppFabric - Access Control (part 2) - Configuring Access Control for Jupiter Motors

10/25/2012 1:40:04 AM

Configuring Access Control for Jupiter Motors

It's now time to configure Access Control for the Jupiter Motors client application. The first thing we need to do is plan who we want to access our web service, and what actions can be performed. For this web service offered by Jupiter Motors, it's pretty simple only our client application should have access, and it can call any of the three functions in the service. Just as a reminder, the functions are:

  • LoadStartupData: The function returns two datasets, one containing the possible statuses for an order and the other containing the orders waiting completion

  • GetStatusForOrder: This function returns the status of a selected order

  • AddOrderStatusUpdateToQueue: This function puts the status update into a queue to be processed by our worker role

We need to create a ruleset allowing access to these functions, as well as the token policies and scopes. As we're providing access to internally developed applications, we can use the simple symmetric key functionality, similar to a user ID and password. Additionally, we need to enable an SSL on our portal to secure the data being transferred.

Configuring Azure AppFabric Portal

Before any requests can be made of Azure AppFabric, we need to obtain the Management Key. This key is included in the corresponding request to prove we are able to make the request by having secret information. This key should be protected carefully. To find the Management Key, we need to log in to the Azure AppFabric portal at http://appfabric.azure.com/. After we've logged in, we can see details of our project and the Service Namespaces, if there are any, as shown in the following screenshot:

As we have an existing Service Namespace, we can click on its name to be taken to the Service Namespace details page. The top section, named Manage, contains both the Current Management Key and Previous Management Key. Both keys are supported in case any key is changed before all existing applications are updated.

If there is no Service Namespace listed, or if we need to create a new Service Namespace, there is a link on the project summary page (shown in the screenshot prior to the preceding one) that we use to create a new Service Namespace. To create a Service Namespace, we follow these steps:

  1. 1. The first step in creating a new Service Namespace is to choose the name we want to use to refer to the namespace. As the name we choose must be unique across all of Azure, it's important to validate it.

  1. 2. The next step is to choose the region in which our Service Namespace is to be run. At the time of writing, there were only four regions to choose from. These regions do not refer to a particular data center, but to a geographic region in which one or more data centers are located.

  1. 3. Finally, if we're planning to use the Service Bus, we can choose the number of connections. We'll discuss more about this in the further sections, but we will configure the connections at the same time.

Configuration tools

At the time of writing, there is no way to configure Access Control via the portal. All configuration steps must be performed using REST calls to the configuration service from client tools. Fortunately, the Windows Azure AppFabric SDK (download from http://go.microsoft.com/fwlink/?LinkID=129448) includes a tool called ACM.exe that is used to configure Access Control. A full reference for ACM.EXE can be found at http://msdn.microsoft.com/en-us/library/ee706706.aspx. The C# source code is also included in case we need a reference, or we want to develop our own configuration tool.

An additional tool called AcmBrowser is provided in the AppFabric samples. The samples can be downloaded from http://go.microsoft.com/fwlink/?LinkID=129448 and installed separately from the SDK. AcmBrowser is a GUI tool that can be used to configure Access Control, and display the configuration in a more user-friendly manner than Acm.exe. The AcmBrowser project is located at<installfolder>\AccessControl\ExploringFeatures\Management\AcmBrowser\ManagementBrowser. In order to use AcmBrowser, we have to open the project and compile the tool. At the time of writing, Acm.exe is the recommended tool to use, and it provides useful output, so we'll use it ourselves.

The acm.exe syntax is standard verb-noun:

acm.exe <command> <resource< [-option:<option value>]

If the only option is "-?", help for that command/resource will be returned. For example, Tools>acm.exe -? returns the following help information:

More detailed help is also available for individual commands:

For a complete overview of the commands, resources, and options, the MSDN documentation is available at http://msdn.microsoft.com/en-us/library/ee706706.aspx. Some of the options we need to include with every operation toward Access Control are the Host, the Service Namespace, and the Management Key. Looking once again at the management key shown above, we surely don't want to have to type that too many times! Fortunately, we can add these three values to the config files and omit them from the command line.

The Acm.exe and acm.exe.config files are installed by default at C:\Program Files\Windows Azure platform AppFabric SDK\V1.0\Tools. We can edit the config file to provide the three options. The host is defaulted to the management web service address, accesscontrol.windows.net, and should not be changed. We can copy and paste the values for the Service Namespace and Management Key from the Azure AppFabric portal, creating the file shown here:

<?xml version="1.0" encoding="utf-8" ?>
<add key="host" value="accesscontrol.windows.net"/>
<add key="service" value="jupiter"/>
<add key="mgmtkey" value="xr5BwkhSynQ+RwGbxGEkDUepB+zrF9p8qimhfqmCPZ0="/>

At this point in the configuration process, we have a Service Namespace that does not yet have a Service Policy.

Referring to the diagram under the Basics of Access Control configuration section, we can see that we have Rule Sets, Token Policies, and Scopes to configure to create a Service Policy.

Two of the most useful commands in Acm.exe are get and getall. We use get to retrieve information on a particular Scope/Token Policy/Rule/Issuer, and we use the getall command to retrieve a list of all the Scopes/Token Policies/Rules/Issuers. The ID of the object is needed for the get command. So, as we add objects to Access Control, it's a good idea to record the details.

To confirm we don't have a scope in our Service Policy, we can use the getall command:

Tools>acm.exe getall scope

The count of the scopes in our Service Policy will be shown in the output:

Count: 0

The count of 0 confirms we do not have any scopes. We can repeat the process for Rules, Token Policies, and Issuers.

Creating a Token Policy

A Token Policy dictates the lifetime of a token (to help prevent it from being reused) and whether to autogenerate a signing key or use a static key. The command to create a Token Policy is:

acm.exe create tokenpolicy

By adding the "-?" option, we can list all options available for this command, as shown here:

Recall that the Service, Host, and Management Key are already set in the configuration file. All we need to do to create a Token Policy is to set the name and key value:

Tools>acm.exe create tokenpolicy -name:Delivery –autogeneratekey

If our Token Policy is created successfully, the ID of the policy will be returned.

Object created successfully (ID:' tp_4ef493f23daf444ca50410a7d1852125')

When using the autogeneratekey option, the timeout is defaulted to 8 hours. If we were using a static key, we'd specify the key value in the command (type carefully!). For applications used in public environments, we would probably want to set the timeout to a shorter value. Note that the ID begins with tp_. This differentiates the Token Policy IDs from other Access Control IDs.

It's a good idea to store the information for each object we create in a password keeper or database for future reference. We'll need the IDs for the next configuration steps and in some of our applications.

If we need to retrieve the details of our Token Policy, we can again use the getall command to retrieve the details of all Token Policies:

Tools>acm.exe getall tokenpolicy

We can see the ID of our Token Policy, as well as the friendly name, the timeout, and the signing key issued to our request:

Count: 1
id: tp_4ef493f23daf444ca50410a7d1852125
name: Delivery
timeout: 28800
key: l4K+qOU9OTo1dG3DWxluH+eTvsX/CBHhFbxLfxZcjC4=

Let's see how the get command works, specifying the ID as part of the options:

Tools>acm.exe get tokenpolicy

The following information is returned:

id: tp_4ef493f23daf444ca50410a7d1852125
name: Delivery
timeout: 28800
key: l4K+qOU9OTo1dG3DWxluH+eTvsX/CBHhFbxLfxZcjC4=

The information returned is the same as with the getall command. So far, so good now we need to create a scope, an issuer, and a rule.

Configuring a Scope

A scope groups the rules and token policies as they relate to a specific URI. In order to create a scope, we need to include the Token Policy ID we want associated with it.

Tools>acm.exe create scope -name:DeliveryScope

If our scope creation is successful, the ID of the scope is returned.

Object created successfully (ID:'scp_334a7c77845e7ac20764300da9119c434ffc

The IDs for scopes begin with scp_, just as the IDs for token policies began with tp_. We now have a scope, tied to a URI and with a token policy. We need this ID to create a rule, so it's a good idea to copy and paste this ID. It's now time to create an issuer and a rule.

Configuring an Issuer

An Issuer is another name for an Identity Provider. Users create accounts with Identity Providers, and Identity Providers issue claims to consuming services. In the current scenario, Access Control is the identity consumer. We establish a trust between Access Control and the Issuer with a secret key provided by the Issuer. The ultimate claims consumer our local application isn't concerned with anything other than a trust relationship with Access Control.

Tools>acm.exe create issuer -name:jupiter -issuername:jupiter -autogeneratekey

If our issuer is created successfully, the ID is returned. As with all the other IDs we've created, Issuer IDs begin with a distinct prefix. We'll use this ID to create a rule allowing access to applications presenting the correct key, so be sure to copy and paste it, too.

Configuring a Rule

Rules are where the magic happens. We'll use Rules to map claims, and we use rules to configure trusts with Issuers. The mapping is done with the inclaimtype, inclaimvalue, outclaimtype, and outclaimvalue options.

When we create a Rule, we need to include a Scope ID and an Issuer ID. Because the IDs are long, it might be easiest to build the command in a text editor first, and then copy the command to the command window.

Tools>acm.exe create rule -name:jupiterrule1 -scopeid:scp_334a7c77845e7ac2076430
0da9119c434ffcc65d -inclaimissuerid:iss_a2f7fcb5afeb7983ffbb6ce3d1a7e91edf321350


On success, the rule ID is returned, which begins with rul_.

Object created successfully (ID:'rul_42db52d7749770ca2f585ddc1b992adecb8b76bf93f

We have now created a rule that says anyone who presents a valid key from the "jupiter" issuer is placed in the user role. As we add additional identity providers to our service policy, we need to perform only these four configuration steps to map visitors into the "users" role.
Configuring a client application for Access Control

When a service is secured by Access Control, a client does not make its first request directly to the service. Instead, we need to perform the following steps:

  1. 1. Request a token from Access Control.

  2. 2. Split the token out of the response from Access Control.

  3. 3. Build the service request, including the necessary parameters and the token.

  4. 4. Issue the service request.

  1. 5. Receive and process the response from the service.

A client can cache the token and use it until the token expires. Once a token expires, the client application must request a new token before it can make any additional requests from the service.

In order to request a token from Access Control, we need to know the Service Namespace, the scope, and the issuer key. Because these values may change (especially the issuer key), it's advisable to place them in the application settings or our client application:

Requesting the Token

The first modification to our code is we need to add two Imports statements:

Imports System.Net
Imports System.Collections.Specialized

We now create a POST request to Access Control, and pass the IssuerKey and Scope settings we defined earlier. The response is returned as a byte array, which we then convert to a UTF8 encoded string:

Dim _client As New WebClient()
_client.BaseAddress = String.Format("https://{0}.accesscontrol.windows.net/", My.Settings.ServiceNamespace)
Dim _values As New NameValueCollection()
_values.Add("wrap_name", "wcfauthmanager")
_values.Add("wrap_password", My.Settings.IssuerKey)
_values.Add("wrap_scope", My.Settings.Scope)
Dim _responseBytes() As Byte = _client.UploadValues("WRAPv0.9/", "POST", _values)
Dim _response As String = System.Text.Encoding.UTF8.GetString(_responseBytes)


At this point, we now have our token, but it's part of a much larger string. We have to unpack the token by splitting apart the name/value pairs with the name wrap_access_token=, and taking the value:

Dim _pairs() As String = _response.Split("&"c)
Dim _tokenPair As String = From p In _pairs Select p Where p.Contains("wrap_access_token=")
Dim _token As String = _tokenPair.Split("="c)(1)


Now we're ready to make requests from our web service. This will require some changes to previously written and tested code. If our client project doesn't have references for System.ServiceModel and System.ServiceModel.Web, these need to be added. We also need to add an Imports System.ServiceModel to our form.

As we need to modify the request headers to include the token, we'll need to create a request proxy, add the token (remember we need to UrlDecode the token) as the "authorization" header, and then call the service.

Private Function LoadFormStartupData(ByVal _token As String) As DataSet
Dim _startup As DataSet
Dim _binding As New WebHttpBinding(WebHttpSecurityMode.None)
Dim _address As New Uri(My.Settings.Scope)
Dim _channelFactory As New WebChannelFactory(Of ERPServiceReference.IERPServiceChannel)(_binding, _address)
Dim _proxy As ERPServiceReference.IERPServiceChannel = _channelFactory.CreateChannel()
Using TempOperationContextScope As OperationContextScope = New OperationContextScope(TryCast(_proxy, IContextChannel))
Dim authHeaderValue As String = String.Format("WRAP access_token=""{0}""", System.Web.HttpUtility.UrlDecode(_token))
WebOperationContext.Current.OutgoingRequest.Headers.Add("authorization", authHeaderValue)
_startup = _proxy.LoadStartupData
End Using
CType(_proxy, IClientChannel).Close()
Return _startup
End Function


Using Access Control in a web service

We're now set to add Access Control to our web service. We have a couple of configuration values we need, and a config file is the ideal place, in case we need to edit these values later. The usual place is in a web.config file, but recall that the web.config files are deployed as part of the compiled binary on Azure. Instead, we need to use the csconfig file. The two settings we need to add are the Token Policy ID and the Service Namespace. We use these as our known values when we compare the tokens presented by the client application.

To add our settings to the WCF Role's csconfig file, right-click the JupiterMotorsWCFRole, listed under the Roles folder, and select Properties.

On the Settings tab, add our two settings.

Before we accept any tokens presented to us, we need to validate them. We can write our own token validation, but the AppFabric SDK includes a couple of classes we can use as a starting point. The WCFAuthorizationManager project (found in<%install_path%>\Access Control\Exploring Features) contains an ACSAuthorizationManager class and a TokenValidator class we can use. ACSAuthorizationManager is an implementation of ServiceAuthorizationManager, and performs the following verifications of a request:

  • It checks whether there is an authorization entry in the request headers. If not, the request is rejected.

  • If there is an authorization token in the request headers, call the TokenValidator.Validate method. If the token is not valid, the request is rejected.

  • Claims are extracted from the token, including a claim of type "action". We then determine what action the user is attempting to perform (or what method is being called). If there is no action, the request is rejected.

  • If all checks out, the action is allowed.

The TokenValidator class performs the following verifications of the token:

  • Confirms the HMAC signature is valid

  • Confirms the token has not expired

  • Confirms the issuer is trusted

  • Confirms the audience is trusted

We should add these two files to the JupiterMotorsWCFRole project. We may need to add a missing reference to System.ServiceModel.Web in order for the project to compile.

  •  SharePoint 2010: Architecture Fundamentals - Physical Deployment Options
  •  SharePoint 2010: Architecture Fundamentals - Understanding SharePoint Administration
  •  SharePoint 2010: Architecture Fundamentals - SharePoint Lists, Libraries, and Items, Pages, Navigation
  •  Installing the HP-UX 11i Operating Environment (part 3) - HP 9000 Early Boot and Beginning the Load of HP-UX
  •  Installing the HP-UX 11i Operating Environment (part 2) - Loading HP-UX
  •  Installing the HP-UX 11i Operating Environment (part 1) - Integrity Early Boot and Begin Loading HP-UX from an Ignite-UX Server, Integrity Early Boot and Begin Loading HP-UX from Media
  •  Synology DS213 + Desktop NAS
  •  Simulating SOA : Interpreting the Results of a Simulation
  •  Simulating SOA : BPEL Simulation Examples
  •  Buying Guide – Router (Part 3) - Buffalo AirStation 1750, Western Digital My Net N900 Central, Fractal Design Define R4
    Most View
    Personalizing Windows 8 : Adding Badges
    Samsung Galaxy S III - The World's Best-Selling Smartphone Model
    Apple Macbook Air 2012
    Fujifilm X-Pro1 - One Of The Very Best CSC On The Market
    Microsoft Enterprise Library : Banishing Validation Complication - How Do I Use The Validation Block?
    HTC One X+ Review - Highlighting Almost All Power Of HTC One X (Part 5)
    LINQ to Objects : How to Group Elements (part 2) - Specifying a Key to Group By
    Tips To Speed Up Your Device (Part 2)
    DDMF DirectionalEQ Effect Plugin
    CyberPower Zues M2 - The More-Affordable Ultraportable
    Top 10
    Labs Briefs Review March 2014 - Lenovo Yoga Tablet 8, Asrock Fatality Z87 Killer
    Lenovo ThinkCentre E93z All-in-one PC
    Logitech G550 PowerShell Dedicated Gaming Controls for iPhone
    Logitech UltraThin Keyboard Cover For iPad Air
    Looks Can Be Deceiving CM Storm Pulse R
    Micro ATX Motherboard Gigabyte F2A88XM DS2
    Mighty Impressive Canon Legria HF G30
    Mini-ITX Motherboard ASRock FM2A88X-ITX+
    Mini-ITX Motherboard Gigabyte F2A88XN-WIFI
    Netgear ReadyNAS 314 Enterprise Network Storage