Web API Creation
Updated: April 9, 2014
Applies To: Windows Server 2012 R2
In this section, you will create a ToDo list service that maintains ToDo items for Contoso employees. The service will consist of an ASP.NET Web API and will use UseActiveDirectoryFederationServicesBearerAuthentication to ensure only authorized users and clients can access the service.
ToDoListService Web API Creation
Creating the ToDoListService Web API can be broken down into the following
Create the Relying Party Trust for the ToDoListService
Create the ToDoListService Project in Visual Studio 2013
Modify the existing code for the ToDoListService
Create the ToDoItem Object Model
Create the ToDoListController
Verify the ToDoListService runs
Create the Relying Party Trust for the ToDoListService
A relying party (RP) is any software that has a need to authenticate and authorize users. A relying party trust object consists of a variety of identifiers, names, and rules that identify a resource or RP, to the local Federation Service. In order to validate tokens that are sent to the ToDoListService, AD FS must be made aware of the ToDoListService. This is done by creating a relying party trust for our Web API.
Important
The steps below show how to manually create a relying party trust. To use PowerShell to create the relying party trust, skip to the bottom of this section.
To create a relying party trust
On DC1, from Server Manager, at the top, click tools and from the drop-down select AD FS Management. This will bring up AD FS Management.
On the left, expand Trust Relationships, right-click Relying Party Trusts and select Add Relying Party Trust. This will begin the Add Relying Party Trust Wizard.
On the Welcome screen, click Start.
On the Select Data Source screen, select Enter data about the relying party manually and click Next.
On the Specify Display Name screen, enter ToDoListService in the Display Name box and click Next.
On the Choose Profile screen, click Next.
On the Configure Certificate screen, click Next.
On the Configure URL screen, click Next.
On the Configure Identifiers screen, in the Relying Party trust identifier box, enter http://corp.contoso.com/ToDoListService and click Add. Click Next.
On the Configure Multi-factor Authentication Now screen, click Next.
On the Choose Issuance Authorization Rules screen, click Next.
On the Ready to Add Trust screen, click Next.
On the Finish screen, click Close. This will open the Edit Claim Rules for Test dialog box.
On the Issuance Transform Rules screen, click Add Rule. This will open the Add Transform Claim Rule Wizard.
On the Choose Rule Type screen, click Next.
On the Configure Claim Rule screen, in the box next to Claim Rule name: enter Email.
On the Configure Claim Rule screen, from the drop-down under Attribute Store select Active Directory.
On the Configure Claim Rule screen, under Mapping of LDAP attributes to outgoing claim types, from the drop-down next to LDAP Attribute (Select of type to add more) select E-Mail-Addresses.
On the Configure Claim Rule screen, under Mapping of LDAP attributes to outgoing claim types, from the drop-down next to Outgoing Claim Type (Select or type to add more) select E-Mail Address.
Click Finish.
On the Edit Claim Rules for Test screen, click Apply. Click OK.
The following PowerShell cmdlet can be used to accomplish the same task as above
Add-AdfsRelyingPartyTrust -Identifier https://corp.contoso.com/ToDoListService -Name ToDoListService -IssuanceAuthorizationRules '@RuleTemplate = "AllowAllAuthzRule" => issue(Type = "https://schemas.microsoft.com/authorization/claims/permit", Value = "true");' -IssuanceTransformRules '@RuleTemplate = "LdapClaims" @RuleName = "email" c:[Type == "https://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]=> issue(store = "Active Directory", types = ("https://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"),query= ";mail;{0}", param=c.value);'
Create the ToDoListService Project in Visual Studio 2013
In this section we will create the initial project for the ToDoListService in Visual Studio 2013. You will need to have Update 2 CTP2 or greater installed prior to this step because this is the first version of Visual Studio 2013 to include an on-premises authentication template for the Web API for use directly with AD FS. Use the following steps to create the initial project.
To create the ToDoListService project in Visual Studio 2013
Open Visual Studio 2013 and select New Project.
Scroll down under Visual C#, select Web and then rename the project ToDoListService. Click Ok. This will bring up a list of templates.
From the templates, select Web API.
Click Change Authentication
On the Change Authentication screen, select Organizational Accounts
On the right, from the drop-down, change Cloud – Single Organization to On-premises.
On the Change Authentication screen, in the box under On-Premises Authority (ADFS in Windows Server 2012 R2 or later is required), enter https://adfs.corp.contoso.com/federationmetadata/2007-06/federationmetadata.xml
On the Change Authentication screen, in the box under App ID URL, enter http://corp.contoso.com/ToDoListService
Click Ok.
On the New ASP.NET Project page, under Windows Azure, remove the check from the Create remote resources box and click OK. This will take a moment as the project is created.
Create the ToDoItem Object Model
Once the project is created the first thing we want to do is create the ToDoItem object which is a small class. An instance of this class will be used to contain the ToDoItem data. Use the following steps to create the ToDoItem class.
To create the ToDoItem
In Solution Explorer, right-click on the Models folder, click Add, and then click Class.
In the Add New Item dialog, enter the name ToDoItem and click Add.
The new class will be added to the project. Under public class ToDoItem, add the line: public string Title {get; set;} so that the code looks similar to below:
namespace ToDoListService.Models { public class ToDoItem { public string Title { get; set; } } }
Create the ToDoListController
In a Web API, a controller is an object that handles HTTP requests. Now we will add a controller that can return either a list of our things to do or it will allow us to add items to the list so that we don’t forget them later. Use the following steps to create the ToDoListController.
In Solution Explorer, right-click the Controllers folder, click Add and then click Controller
From the list of controllers, select Web API 2 Controller – Empty and click Add. This will bring up an Add Controller dialog box.
In the Controller name dialog box, enter the name ToDoListController. Click OK.
Open ToDoListController.cs and replace the existing code with the following:
using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Web.Http; using ToDoListService.Models; namespace ToDoListService.Controllers { [Authorize] public class ToDoListController : ApiController { // ToDo items list for all users static ConcurrentBag<ToDoItem> todoBag = new ConcurrentBag<ToDoItem>(); // GET api/todolist returns public IEnumerable<ToDoItem> Get() { return todoBag; } // POST api/todolist public void Post(ToDoItem todo) { if (null != todo && !string.IsNullOrWhiteSpace(todo.Title)) { todoBag.Add(new ToDoItem { Title = todo.Title}); } } } }
Now we will discuss the code you’ve added. The ConcurrentBag object is a thread-safe object to save ToDo items for all users. In a real service these items would be saved in a database, but for simplicity we will just store the data in memory.
// Todo items list for all users static ConcurrentBag<ToDoItem> todoBag = new ConcurrentBag<ToDoItem>();
Now that we have a place to store ToDo items, the Post() method is updated to include the functionality to add items to the ConcurrentBag.
// POST api/todolist public void Post(ToDoItem todo) { if (null != todo && !string.IsNullOrWhiteSpace(todo.Title)) { todoBag.Add(new ToDoItem { Title = todo.Title}); } }
Note the method signature has been updated to accept a ToDoItem object, which will serialize a form POST from a caller to the object. Additionally the method ensures that a ToDoItem won’t be added if it has an empty title.
Next, we will discuss the Get() method:
// GET api/todolist returns public IEnumerable<ToDoItem> Get() { return todoBag; }
The signature is updated to return IEnumerable<ToDoItem>, which will be set to the ToDo items.
Verify the ToDoListService runs
In this section we will verify that the ToDoListService runs and we will also install the iisexpress certificate so that we do not receive certificate errors when running our projects. Use the following steps to verify that the ToDoListService is running and to resolve the certificate errors.
To verify the ToDoListService
In our ToListService project in Visual Studio, press F5 to verify that the service runs.
This will bring up a pop-up that says that the project is configured to use SSL. To avoid SSL warnings in the browser you can choose to trust the self-signed certificate that IIS Express has generated. Would you like to trust the IIS Express SSL certificate? Click Yes.
This will bring up a security warning stating that you are about to install a certificate from a certificate authority claiming to represent: localhost. Click Yes.
At this point, the ASP.NET logo screen should open in Internet Explorer.
Warning
Make sure to note the port that the web API is running on. For example, if https://localhost:44300/ is displayed in the browser, then my port is 44300.
If you receive "An exception of type System.AggregateException occurred in mscorlib.dll but was not handled in user code." Go ahead and click continue. In Internet explorer you will probably see the following error: The remote certificate is invalid according to the validation procedure.
To resolve this, you will need to install the DC1 AD FS certificate in the local machines certificate store on CLIENT1. You can use the procedures outlined in Import and Export Certificates Be sure that you are importing it to the Local Machine store and that it is added to the Trusted Root Certificate Authorities container.