How to: Authenticate to a REST WCF Service Deployed to Azure Using ACS

Applies To

  • Microsoft Azure Active Directory Access Control (also known as Access Control Service or ACS)

  • Microsoft Azure

  • WCF

  • REST

Summary

This How-To describes how to use ACS with Simple Web Token (SWT) to secure REST WCF service that is hosted in Microsoft Azure. It also describes in detail how to build a client application that obtains a SWT token from ACS and uses it to connect to the web service based on a username and password pair.

Contents

  • Objectives

  • Overview

  • Summary of Steps

  • Step 1 - Create a REST WCF Service

  • Step 2 - Configure ACS to Issue a SWT Token

  • Step 3 - Implement Code That Validates the SWT Token at the REST WCF Service

  • Step 4 – Implement a Client That Requests The SWT Token From ACS and Forwards It To The REST WCF Service

  • Step 5 - Considerations When Deploying to Microsoft Azure

  • Related Items

Objectives

  • Create a REST WCF Service that requires a SWT token for authentication.

  • Implement SWT token validation and separate it from business logic code.

  • Configure ACS to issue a SWT token based on a username and password pair.

  • Create a client that obtains a SWT token from ACS and passes it to the REST WCF Service.

Overview

ACS provides supports for issuing both SAML tokens and Simple Web Tokens (SWTs). For more information about which token formats are supported by ACS see Token Formats Supported in ACS (https://go.microsoft.com/fwlink/?LinkId=220927). The SWT token format is specifically designed for use with REST web services, where the token needs to fit within an HTTP header. This How-To provides details on how to write the necessary code to request SWT tokens from a web service client, as well as validate the SWT token at a REST WCF service hosted in Windows Azure.

Summary of Steps

  1. Step 1 – Create a REST WCF Service

  2. Step 2 – Configure ACS to Issue a SWT Token

  3. Step 3 – Implement Code That Validates the SWT Token at the REST WCF Service

  4. Step 4 – Implement a Client That Requests a SWT Token From ACS and Forwards It To The REST WCF Service

  5. Step 5 – Considerations When Deploying to Microsoft Azure

Step 1 – Create a REST WCF Service

This step shows you how to create a REST WCF service that can be hosted in Internet Information Services (IIS). This REST WCF service will contain a SVC file that will be hosted by IIS, a WCF library with a REST interface, and the REST service that implements the interface. This sample will show you how to implement basic methods for manipulating a user as a REST resource.

To create a REST WCF service to be deployed in IIS

  1. To run Visual Studio 2010, click Start, click Run, type the following text, and then press Enter: devenv.exe

  2. In Visual Studio, click File, and then click New Project.

  3. In the New Project window, expand the Other Project Types node and click Visual Studio Solutions. Confirm that Blank Solution is selected.

  4. Give the solution a name, for example, RESTfulWCAzureACS. We will be using this name throughout this How-To. If you gave your own name, change the code snippets accordingly.

  5. In the Solution Explorer, right-click the solution node, click Add, and then click New Project.

  6. In the Add New Project dialog box, click the WCF node, and select WCF Service Library. Give it a name, for example, RESTfulWCFLibrary, and click OK.

  7. Delete the IService1.cs, Service1.cs, and App.config files that were created by default.

  8. In the Solution Explorer, right-click the References folder and select Add Reference. In the .NET tab, select the reference to the System.ServiceModel.Web assembly and click OK.

  9. In the Solution Explorer, right-click RESTfulWCFLibrary, click Add, and then click Class.

  10. In the Add New Item dialog box, type a name for the new class, for example, User.cs

  11. Paste the following code as an implementation of the User class:

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.ServiceModel; 
    using System.Runtime.Serialization; 
    
    namespace RESTfulWCFLibrary 
    { 
        [CollectionDataContract(Name="users",Namespace="")] 
        public class Users: List<User> 
        { }
        [DataContract(Name = "user", Namespace = "")] 
        public class User 
        { 
            [DataMember(Name = "id", Order = 1)] 
            public string UserId; 
            [DataMember(Name = "firstname", Order = 2)] 
            public string FirstName; 
            [DataMember(Name = "lastname", Order = 3)] 
            public string LastName; 
            [DataMember(Name = "email", Order = 4)] 
            public string Email; 
        } 
    }
    
  12. In the Solution Explorer, right-click RESTfulWCFLibrary, click Add, and then click New Item.

  13. Select Interface from the list and give it a name, for example, IUserService.cs.

  14. Paste the following code as an implementation of the Interface:

    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.ServiceModel; 
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Web; 
    
    namespace RESTfulWCFLibrary 
    { 
        [ServiceContract] 
        interface IUserService 
        { 
            [WebGet(UriTemplate = "/users", 
                    ResponseFormat = WebMessageFormat.Xml)] 
            [OperationContract] 
            Users GetAllUsers(); 
            [WebInvoke(UriTemplate = "/users", 
                       Method = "POST", 
                       RequestFormat = WebMessageFormat.Xml, 
                       ResponseFormat = WebMessageFormat.Xml)] 
            [OperationContract] 
            User AddNewUser(User u); 
    
            [WebGet(UriTemplate = "/users/{user_id}", 
                    ResponseFormat = WebMessageFormat.Xml)] 
            [OperationContract] 
            User GetUser(string user_id); 
        } 
    } 
    
  15. Right-click RESTfulWCFLibrary in the Solution Explorer, add a new Class, and then give it a name, for example, UserService.

  16. Paste the following code as an implementation of the class:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Web;
    
    namespace RESTfulWCFLibrary
    {
        public class UserService : IUserService
        {
            static Users _users = new Users();
            public Users GetAllUsers()
            {
                //IN YOUR CASE YOU'D PROBABLY ACCESS A DB
                //OR A WEB SERVICE TO RETRIEVE ACTUAL DATA
                GenerateFakeUsers();
                return _users;
            }
            public User AddNewUser(User u)
            {
                u.UserId = Guid.NewGuid().ToString();
                //IN YOUR CASE YOU'D PROBABLY ACCESS A DB
                //OR A WEB SERVICE TO SAVE ACTUAL DATA
                _users.Add(u);
                return u;
            }
            public User GetUser(string user_id)
            {
                var u = FindUser(user_id);
                return u;
            }
            private User FindUser(string user_id)
            {
                //IN YOUR CASE YOU'D PROBABLY ACCESS A DB
                //OR A WEB SERVICE TO RETRIEVE ACTUAL DATA
                return new User()
                {
                    FirstName = "FirstName1",
                    LastName = "LastName1",
                    Email = "email1@demoDomain.com",
                    UserId = "1"
                };
            }
            private void GenerateFakeUsers()
            {
                _users.Add(new User()
                {
                    FirstName = "FirstName1",
                    LastName = "LastName1",
                    Email = "email1@demoDomain.com",
                    UserId = "1"
                });
                _users.Add(new User()
                {
                    FirstName = "FirstName2",
                    LastName = "LastName2",
                    Email = "email2@demoDomain.com",
                    UserId = "2"
                });
            }
        }
    }
    
  17. In the menu, click Build and then click Build Solution. Confirm that there are no compilation errors.

  18. To add an empty web application, right-click the RESTfulWCAzureACS solution, click Add, and then click New Project.

  19. In the Add New Project dialog box, click the Web node and select the ASP.NET Empty Web Application option from the list. Give it a name, for example, RESTfulWCFEndPointsHostedIIS, and click OK.

  20. To add a new WCF service SVC file, right-click the RESTfulWCFEndPointsHostedIIS project, click Add, and then click New Item. Click the Web node and select WCF Service from the list. Give it a name, for example, RESTfulWCFUsersServiceEndPoint.svc, and click OK.

  21. Delete the IRESTfulWCFUsersServiceEndPoint.cs and RESTfulWCFUsersServiceEndPoint.svc.cs files that were created by default. Leave the RESTfulWCFUsersServiceEndPoint.svc file intact.

  22. Double-click the RESTfulWCFUsersServiceEndPoint.svc file and paste the following markup instead of the existing one.

    <%@ ServiceHost Service="RESTfulWCFLibrary.UserService"  
                    Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>
    
  23. To build the solution, right-click it in the Solution Explorer and select Build Solution. Confirm that you do not receive any compilation errors.

  24. Copy the resulting RESTfulWCFLibrary.dll to the RESTfulWCFEndPointsHostedIIS project’s bin folder.

  25. Navigate to https://localhost:<yourDevIISPort>/RESTfulWCFUsersServiceEndPoint.svc/users.

  26. You browser should look similar to the following:

    <?xml version="1.0"?>
    <users ns:i="https://www.w3.org/2001/XMLSchema-instance">
      <user>
        <id>1</id>
        <firstname>FirstName1</firstname>
        <lastname>LastName1</lastname>
        <email>email1@demoDomain.com</email>
      </user>-<user>
        <id>2</id>
        <firstname>FirstName2</firstname>
        <lastname>LastName2</lastname>
        <email>email2@demoDomain.com</email>
      </user>
    </users>
    

Step 2 – Configure ACS to Issue a SWT Token

This step shows you how to configure your REST web service as a relying party, generate rules, and configure a service identity. These configurations are performed in the ACS Management Portal. They can also be performed programmatically using the ACS Management Service. For more information about using the ACS Management Service, see Automation (https://go.microsoft.com/fwlink/?LinkId=220931).

To configure the REST web service as a relying party

  1. Go to the Microsoft Azure Management Portal (https://manage.WindowsAzure.com), sign in, and then click Active Directory. (Troubleshooting tip: "Active Directory" item is missing or not available)

  2. To manage an Access Control namespace, select the namespace, and then click Manage. (Or, click Access Control Namespaces, select the namespace, and then click Manage.)

  3. In the Trust Relationships section, click Relying Party Applications.

  4. On the Relying Party Applications page, click Add link. The Add Relying Party Application page opens.

  5. In the Relying Party Application Settings section, make the following selections:

    • Name—Specify a display name for this relying party, for example, Username Binding Sample RP.

    • Mode—Select the Enter settings manually option.

    • Realm—Specify the realm of your WCF service, for example, https://localhost:7000/ RESTfulWCFUsersServiceEndPoint.svc/

    • Return URL—Leave blank.

    • Error URL—Leave blank.

    • Token format—Select the SWT option.

    • Token lifetime (secs)—Leave the default of 600 seconds.

  6. In the Authentication Settings section, make the following selections:

    • Identity providers—Leave all unchecked.

    • Rule groups—Select the Create New Rule Group option.

  7. In the Token Signing Settings section, make the following selections:

    • Token signing—Select the Use a dedicated certificate option.

    • Token signing key— To generate 256–bit symmetric key, click Generate.

    • Effective date—specify the key’s effective date.

    • Expiration date—specify the key’s expiration date.

  8. Click Save.

Saving your project will also trigger the creation of a rule group. Now you need to add rules in the rule group.

To add rules in the rule group

  1. On the Access Control Service page, click the Rule Groups link.

  2. On the Rule Groups page, click the group you created earlier named Default Rule Group for Username Binding Sample RP.

  3. On the Edit Rule Group page, click the Add link, which is located at the bottom of the page.

  4. On the Add Claim Rule page, in the If section, select the Access Control Service option. Leave the default values for the other options.

  5. Click Save.

To configure a service identity for the REST web service

  1. On the Access Control Service /Management Portal, click Service Identities.

  2. Click Add Service Identity.

  3. In the Name field, enter a name for the service identity. This will be the username value used in the token request.

  4. In the Type field, select Password. In case you choose to select Symmetric Key you will need to use a different code in Step 4 when sending a signed token from the WCF client.

  5. In the Password field, enter a password of your choice.

  6. In the Effective date field, set the date at which this credential will take effect.

  7. In the Expiration date field set the date at which this credential will expire.

  8. Click Save.

Step 3 – Implement Code That Validates the SWT Token at the REST WCF Service

This step shows you how to implement SWT token validation at the REST WCF service. It is a good design practice to separate the security concerns from business logic code. To accomplish this separation, you will implement an HttpModule that intercepts HTTP requests before invoking the REST WCF service’s methods.

To implement SWT token validation

  1. To add a new class library project, right-click the RESTfulWCAzureACS solution, click Add, and then click New Project.

  2. In the Add New Project dialog box, click the Windows node and select the Class Library option from the list. Enter a name of your choice, for example, SecurityModule, and click OK.

  3. While in the SecurityModule project, right-click the References folder in Solution Explorer and select the Add Reference option.

  4. In the Add Reference dialog box, click the .NET tab and select the System.Web assembly from the list. Click OK.

  5. To add a new class file, right-click the SecurityModule project in the Solution Explorer, click Add, and then click Class.

  6. In the Add New item dialog box, specify the name of the new class, for example, SWTModule.cs, and click OK.

  7. To implement the class, paste the code below, changing the configuration according to your namespace. This class implements IHttpModule interface, which will intercept incoming requests and will validate the SWT tokens.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using Microsoft.AccessControl2.SDK;
    
    namespace SecurityModule
    {
        class SWTModule : IHttpModule
        {
            //USE CONFIGURATION FILE, WEB.CONFIG, TO MANAGE THIS DATA
            string serviceNamespace = "change to your namespace";
            string acsHostName = "accesscontrol.windows.net";
            string trustedTokenPolicyKey = "change to your signing key";
            string trustedAudience = "change to your realm";
    
    
            void IHttpModule.Dispose()
            {
    
            }
    
            void IHttpModule.Init(HttpApplication context)
            {
                context.BeginRequest += new EventHandler(context_BeginRequest);
            }
    
            void context_BeginRequest(object sender, EventArgs e)
            {
                //HANDLE SWT TOKEN VALIDATION
                // get the authorization header
                string headerValue = HttpContext.Current.Request.Headers.Get("Authorization");
    
                // check that a value is there
                if (string.IsNullOrEmpty(headerValue))
                {
                    throw new ApplicationException("unauthorized");
                }
    
                // check that it starts with 'WRAP'
                if (!headerValue.StartsWith("WRAP "))
                {
                    throw new ApplicationException("unauthorized");
                }
    
                string[] nameValuePair = headerValue.Substring("WRAP ".Length).Split(new char[] { '=' }, 2);
    
                if (nameValuePair.Length != 2 ||
                    nameValuePair[0] != "access_token" ||
                    !nameValuePair[1].StartsWith("\"") ||
                    !nameValuePair[1].EndsWith("\""))
                {
                    throw new ApplicationException("unauthorized");
                }
    
                // trim off the leading and trailing double-quotes
                string token = nameValuePair[1].Substring(1, nameValuePair[1].Length - 2);
    
                // create a token validator
                TokenValidator validator = new TokenValidator(
                    this.acsHostName,
                    this.serviceNamespace,
                    this.trustedAudience,
                    this.trustedTokenPolicyKey);
    
                // validate the token
                if (!validator.Validate(token))
                {
                    throw new ApplicationException("unauthorized");
                }
    
            }
        }
    }
    
  8. To add a new class to the SecurityModule project, right-click the project in the Solution Explorer, click Add, and then click Class. Enter a name of your choice, for example, TokenValidator. This class is available as part of the Code Sample: ASP.NET Web Service (https://go.microsoft.com/fwlink/?LinkId=220996). Paste the following code as the implementation of the class:

    // Copyright 2010 Microsoft Corporation
    // Licensed under the Apache License, Version 2.0 (the "License"); 
    // You may not use this file except in compliance with the License. 
    // You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 
    
    // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR 
    // CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
    // INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR 
    // CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
    // MERCHANTABLITY OR NON-INFRINGEMENT. 
    
    // See the Apache 2 License for the specific language governing 
    // permissions and limitations under the License.
    
    namespace Microsoft.AccessControl2.SDK
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Security.Cryptography;
        using System.Text;
        using System.Web;
    
        public class TokenValidator
        {
            private string issuerLabel = "Issuer";
            private string expiresLabel = "ExpiresOn";
            private string audienceLabel = "Audience";
            private string hmacSHA256Label = "HMACSHA256";
    
            private string acsHostName;
    
            private string trustedSigningKey;
            private string trustedTokenIssuer;
            private string trustedAudienceValue;
    
            public TokenValidator(string acsHostName, string serviceNamespace, string trustedAudienceValue, string trustedSigningKey)
            {
                this.trustedSigningKey = trustedSigningKey;
                this.trustedTokenIssuer = String.Format("https://{0}.{1}/",
                    serviceNamespace.ToLowerInvariant(),
                    acsHostName.ToLowerInvariant());
    
                this.trustedAudienceValue = trustedAudienceValue;
            }
    
            public bool Validate(string token)
            {
                if (!this.IsHMACValid(token, Convert.FromBase64String(this.trustedSigningKey)))
                {
                    return false;
                }
    
                if (this.IsExpired(token))
                {
                    return false;
                }
    
                if (!this.IsIssuerTrusted(token))
                {
                    return false;
                }
    
                if (!this.IsAudienceTrusted(token))
                {
                    return false;
                }
    
                return true;
            }
    
            public Dictionary<string, string> GetNameValues(string token)
            {
                if (string.IsNullOrEmpty(token))
                {
                    throw new ArgumentException();
                }
    
                return
                    token
                    .Split('&')
                    .Aggregate(
                    new Dictionary<string, string>(),
                    (dict, rawNameValue) =>
                    {
                        if (rawNameValue == string.Empty)
                        {
                            return dict;
                        }
    
                        string[] nameValue = rawNameValue.Split('=');
    
                        if (nameValue.Length != 2)
                        {
                            throw new ArgumentException("Invalid formEncodedstring - contains a name/value pair missing an = character");
                        }
    
                        if (dict.ContainsKey(nameValue[0]) == true)
                        {
                            throw new ArgumentException("Repeated name/value pair in form");
                        }
    
                        dict.Add(HttpUtility.UrlDecode(nameValue[0]), HttpUtility.UrlDecode(nameValue[1]));
                        return dict;
                    });
            }
    
            private static ulong GenerateTimeStamp()
            {
                // Default implementation of epoch time
                TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                return Convert.ToUInt64(ts.TotalSeconds);
            }
    
            private bool IsAudienceTrusted(string token)
            {
                Dictionary<string, string> tokenValues = this.GetNameValues(token);
    
                string audienceValue;
    
                tokenValues.TryGetValue(this.audienceLabel, out audienceValue);
    
                if (!string.IsNullOrEmpty(audienceValue))
                {
                    if (audienceValue.Equals(this.trustedAudienceValue, StringComparison.Ordinal))
                    {
                        return true;
                    }
                }
    
                return false;
            }
    
            private bool IsIssuerTrusted(string token)
            {
                Dictionary<string, string> tokenValues = this.GetNameValues(token);
    
                string issuerName;
    
                tokenValues.TryGetValue(this.issuerLabel, out issuerName);
    
                if (!string.IsNullOrEmpty(issuerName))
                {
                    if (issuerName.Equals(this.trustedTokenIssuer))
                    {
                        return true;
                    }
                }
    
                return false;
            }
    
            private bool IsHMACValid(string swt, byte[] sha256HMACKey)
            {
                string[] swtWithSignature = swt.Split(new string[] { "&" + this.hmacSHA256Label + "=" }, StringSplitOptions.None);
    
                if ((swtWithSignature == null) || (swtWithSignature.Length != 2))
                {
                    return false;
                }
    
                HMACSHA256 hmac = new HMACSHA256(sha256HMACKey);
    
                byte[] locallyGeneratedSignatureInBytes = hmac.ComputeHash(Encoding.ASCII.GetBytes(swtWithSignature[0]));
    
                string locallyGeneratedSignature = HttpUtility.UrlEncode(Convert.ToBase64String(locallyGeneratedSignatureInBytes));
    
                return locallyGeneratedSignature == swtWithSignature[1];
            }
    
            private bool IsExpired(string swt)
            {
                try
                {
                    Dictionary<string, string> nameValues = this.GetNameValues(swt);
                    string expiresOnValue = nameValues[this.expiresLabel];
                    ulong expiresOn = Convert.ToUInt64(expiresOnValue);
                    ulong currentTime = Convert.ToUInt64(GenerateTimeStamp());
    
                    if (currentTime > expiresOn)
                    {
                        return true;
                    }
    
                    return false;
                }
                catch (KeyNotFoundException)
                {
                    throw new ArgumentException();
                }
            }
        }
    }
    
  9. To build the project, right-click the SecurityModule project in the Solution Explorer, and select the Build option.

  10. Copy the resulting SecurityModule.dll, which you can find in the project’s bin folder, to the RESTfulWCFEndPointsHostedIIS bin folder.

  11. In the RESTfulWCFEndPointsHostedIIS project, double-click the web.config file and paste the below configuration in system/webServer. This is required for actual Microsoft Azure deployment and debugging.

    <system.webServer>
    <modules>
    <add name="SWTModule" type="SecurityModule.SWTModule, SecurityModule" />
    </modules>
    </system.webServer>
    
  12. Attempt to navigate to https://localhost:yourDevIISPort/RESTfulWCFUsersServiceEndPoint.svc. You should receive an Unauthorized exception.

Step 4 – Implement a Client That Requests a SWT Token From ACS and Forwards It To The REST WCF Service

This step shows you how to request a SWT token from ACS and send it to the REST WCF service from client code. Note, if you configured your service identity credential for Symmetric Key in Step 2 you will need to follow the steps outlined in Signed Token Requests section in the Requesting a Token from AC topic.

To request a SWT token and send it to the REST WCF Service

  1. To add a new console application project to the solution, right-click the RESTfulWCAzureACS solution in the Solution Explorer, click Add, and click New Project.

  2. In the Solution Explorer, right-click the References folder and select Add Reference.

  3. In the .NET tab, select the System.Web assembly and click OK.

  4. In the Add New Project window, click the Windows node and select the Console Application option from the list. Give it a name, for example, Client.

  5. Double-click the Program class and paste the following code:

    using System;
    using System.IO;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Web;
    namespace RESTfulWCFClient
    {
        class Program
        {
            static string serviceNamespace = "your namespace";
            static string acsHostUrl = "accesscontrol.windows.net";
            static string realm = "your realm";
            static string uid = "your service identity name";
            static string pwd = "your service identity password";
    
            static void Main(string[] args)
            {
                string token = GetTokenFromACS(realm);
    
                WebClient client = new WebClient();
    
                string headerValue = string.Format("WRAP access_token=\"{0}\"", token);
    
                client.Headers.Add("Authorization", headerValue);
    
    
                Stream stream = client.OpenRead(@"https://localhost:yourDevIISPort/RESTfulWCFUsersServiceEndPoint.svc/users");
    
                StreamReader reader = new StreamReader(stream);
                String response = reader.ReadToEnd();
                Console.Write(response);
                Console.ReadLine();
    
            }
    
            private static string GetTokenFromACS(string scope)
            {
                string wrapPassword = pwd;
                string wrapUsername = uid;
    
                // request a token from ACS
                WebClient client = new WebClient();
                client.BaseAddress = string.Format("https://{0}.{1}", serviceNamespace, acsHostUrl);
    
                NameValueCollection values = new NameValueCollection();
                values.Add("wrap_name", wrapUsername);
                values.Add("wrap_password", wrapPassword);
                values.Add("wrap_scope", scope);
    
                byte[] responseBytes = client.UploadValues("WRAPv0.9/", "POST", values);
    
                string response = Encoding.UTF8.GetString(responseBytes);
    
                Console.WriteLine("\nreceived token from ACS: {0}\n", response);
    
                return HttpUtility.UrlDecode(
                    response
                    .Split('&')
                    .Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
                    .Split('=')[1]);
            }
    
        }
    }
    
  6. In the Solution Explorer, right-click the Client project and select Set As StartUp Project.

  7. Press the F5 key to run the solution.

Step 5 – Considerations When Deploying to Microsoft Azure

This step outlines Microsoft Azure deployment considerations.

To associate the solution with a Microsoft Azure cloud project

  1. To add a new cloud project in the Solution Explorer, right-click the RESTfulWCAzureACS project, click Add, and then click New Project.

  2. In the Add New Project dialog box, click the Cloud node and select Windows Azure Project. Give the project a name, for example, RESTWCFRole, and click OK.

  3. In the New Windows Azure Project dialog box, select the ASP.NET Web Role option in the left pane and click the > button. Click OK.

  4. In the Solution Explorer, expand the RESTWCFRole project, and expand the Roles folder.

  5. In the Roles folder, right-click the WebRole1 node and select the Associate with Web Role Project in solution option.

  6. In the Associate with Role Project dialog box, select the RESTfulWCFEndPointsHostedIIS project and click OK.

  7. To publish to Microsoft Azure, follow the steps outlined either in Publishing the Windows Azure Application from Visual Studioor in How to Deploy a Service

There are two assemblies that must be deployed with the RESTfulWCAzureACS project: RESTfulWCFLibrary.dll and SecurityModule.dll. To make sure they are deployed to Microsoft Azure follow these steps for each of them:

  1. In the Solution Explorer, locate the bin folder for the RESTfulWCFEndPointsHostedIIS project.

  2. Locate the two assemblies in the bin folder.

  3. Right-click the library dll and select Include In Project.

  4. Right-click the same library dll and select Properties.

  5. In the Properties window, select Copy if newer for the Copy to Output Directory property.

See Also

Other Resources

Code Sample: OAuth 2.0 Certificate Authentication
Code Sample: ASP.NET Web Service