Showing posts with label WebAPI. Show all posts
Showing posts with label WebAPI. Show all posts

Friday, 18 March 2016

asynchronous WebAPI

Introduction

In this article I want to show, how you can improve server performance dramatically by using Microsoft asynchronous WebAPI. The text shows, how a Microsoft WebAPI service backend can be improved to handle request asynchronously and so to increase the number of concurrent clients the server can handle. You can boost the user experience of client applications with asynchronous WebAPI services by being more reactive and fluent in the user interface. This document will not describe the client side in deep, focus is on the performance of the server side. In the following section, I write a very simple web service using Microsoft WebAPI, measure the performance of concurrent requests to that service and compare the results to a second scenario, where we will make the service asynchronous.

Environment

My test machine was a Windows 8.1 PC running on Intel Core™ i7 CPU with 6 cores at 3.24 GHz and with 12 GB RAM. The WebAPI is hosted within the local IIS 8. The simulated clients also run on this machine. One can say that this is not really a realistic scenario for simulating concurrent users and measure server performance. But it will be enough to show some problems and how they can be solved with asynchronous WebAPI services.

The Server

Service Implementation

The server code is minimalistic. The code snipped below shows the implementation we need. There is only a WebAPI service that supports the GET HTTP method in a WebAPI controller named LongOperationController. This service simulates a long running operation by calling Thread.Sleep(). The service waits for 2 seconds until it returns and a response message is generated. So a client waits at least for 2 seconds when calling the service.
Notice: the service response time is a little bit longer than 2 seconds. Serialization/deserialization and transport of HTTP messages over the wire takes time. So the service response time depends on network latency.
public class LongOperationController : ApiController
{
    // GET api/<controller>
    [HttpGet]
    publicvoid DoLongRunningOperation()
    {
        Thread.Sleep(2000);
    }
}

Thread Pool Configuration

There is another variable in the scenario that has to be considered: the thread pool size. As an Asp.Net WebAPI service hosted in an IIS, the application has an own thread pool with a limited number of available threads. The default numbers of threads in the pool are calculated based in the number of cores in the CPU to find an optimum value. But they can be changed! There are two types of threads in a thread pool:
Worker Threads are used for active work e.g. when pushing a work item into the thread pool. Client requests are handled in this way. Each request is handled by an own thread from the thread pool (as far as there are enough worker threads available in the pool).
Completion Port Threads are used to wait for asynchronous I/O operations to finish (e.g. when accessing storage/disc, receive data from network, at least when using the awaitkeyword in the WebAPI service implementation). Completion port threads are not doing a lot. They simply wait and block until they receive a signal.
The number of available worker threads in the thread pool affects the performance of our WebAPI services. If there are too many concurrent client request, all worker threads are busy. New client requests must be queued. As soon as a worker thread is available again, the request is taken from the queue and processed. Using the queue is time expensive, so performance problems can occur.
The maximum number of threads in the thread pool can be increased in order to avoid those performance issues. The problem with this solution is that each thread takes about 1 MB of RAM. So maybe you have to scale the machines memory. 1000 extra threads means 1 GB extra memory! That is not the way to go here.
For our test scenario, we set the maximum number of threads in the pool to a small value: 200. So we can simulate massive concurrent client requests and provoke performance problems at the server (due to the small number of worker threads, not all client request can be handled). While simulating, we can observe what happens with the server performance/response times.
To query or set the numbers of threads the code below can be used. The ThreadPool class provides some static services to query and set the minimum, maximum and available number of worker and completion port threads.
// Variables used to store the available completion port thread counts. 
int workerThreads, completionPortThreads;  
// Variables used to store the min. and max. worker thread counts. 
int minWorkerThreads, maxWorkerThreads;  
// Variables used to store the min. and max. completion port thread counts. 
int minCompletionPortThreads, maxCompletionPortThreads;    

// Query the number of available threads in the app pool. 
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);  
// Query the minimum number of threads in the app pool. 
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);  
// Query the maximum number of threads that can be in the app pool. 
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);    

// Set the maximum number of threads available in the app pool. 
ThreadPool.SetMaxThreads(workerThreads, completionPortThreads); 
With the first service implementation and the thread pool configuration on board, we are ready with the server side and can implement the client code.

The Client

The code below shows the implementation of the client. The method creates a bunch of threads. The number of threads is given by the parameter requests in order to simulate different numbers of concurrent client requests. Each thread calls the WebAPI service shown in the previous chapter and waits for the response. After initializing all threads in the for-loop, all threads are started to the same time (more or less) and the method waits until all threads are completed. That is, when all threads called the WebAPI service and got a response (successful or not).
private static void RunConcurrentRequest(int requests) 
{ 
    var tasks = new List<Task>(); 

    for (var index = 0; index < requests; index++) 
    { 
        tasks.Add(Task.Factory.StartNew(() => 
        { 
            var url = "http://localhost:8080/AsyncWebApi/api/LongOperation"; 
            WebClient client = new WebClient(); 
            client.DownloadString(url); 
        })); 
    } 

    Task.WaitAll(tasks.ToArray()); 
} 
The first scenario should show the problems with synchronous services. Therefore, the method above is called with different parameters: 1, 10, 20, 30, 40, 50, 100, 200, 300, 400, 500, 1000, 2000 and 3000. That means, e.g. for value 1000, that 1000 requests are send to the DoLongRunningOperation WebAPI service to the same time.
While running this test scenario, performance of the ASP.NET WebAPI service was measured with the Performance Monitor (perfmon.exe). Please read my previous blog post on how to measure performance with the Microsoft Performance Monitor (http://robinsedlaczek.wordpress.com/2014/04/07/measure-performance-of-asp-net-web-applications-with-microsoft-performance-monitor-2/). The results will be explained in the next chapter.

Performance

To measure the number of requests per second, number of failed requests per second and the total number of failed requests that were handled by the WebAPI service, the appropriate performance counters have been configured in the performance monitor tool. The image below shows the results of measurements while the client code was running. The red box marks the timeframe when the client code from above was executed. The green line shows how many requests are handled per second. The server handles the request in a nearly constant way for 1 – 500 concurrent requests.
Problems occur with 1000, 2000 and 3000 concurrent requests. The blue line shows the number of failed requests per second. 1000 and more requests cannot be handled by the server in this scenario. As described above, there are only 200 worker threads at the server and the DoLongRunningOperation service takes 2 seconds for execution. So, if there are 200 and more request operations running to the same time at the server, the number of worker threads exceeds and requests are queued. If requests cannot be queued, they fail. The blue line shows that a lot of requests failed in the 1000 and more concurrent requests scenarios. The total number of not handled requests increases shown by the red line.
The next chapter shows how this situation can be improved by using asynchronous WebAPI services.

Figure 1: Performance of synchronous WebAPI services
Figure 1: Performance of synchronous WebAPI services

The asynchronous Service Implementation

To improve the performance of the server in this test scenario, the WebAPI service DoLongRunningOperation will be made asynchronous. The code below shows how to change the service implementation. First, “Async” is appended to the method name following the naming conventions in the .Net framework.
The operation is simply marked with the async keyword and the return type is changed to Task. That is all to make the service asynchronous. But there is a little bit more in this case. Since there is no asynchronous stuff done in this method, the code won’t compile. A task has to be returned or an awaitable operation has to be called. So the Thread.Sleep() method cannot be used here anymore. Instead, the awaitable Task.Delay() method is used.
Awaiting the Task.Delay() method means that DoLongRunningOperationAsync immediately returns when Task.Delay() is called. And so the thread that handles the current requests will be available in the thread pool again and can handle other requests. The Task.Delay() operation runs in a separate thread. When it finishes, the response is created and returned to the client.
An asynchronous WebAPI service does not act asynchronous from a client point of view (e.g. using a callback). The client has to wait until the operation has been finished. That is, in this scenario, when the delay of 2 seconds is over and the response is returned. The client thread is blocked until this operation completes. Asynchronous WebAPI services means, that those services do not block the worker threads in the server thread pool. So the server can handle more requests.
// GET api/<controller> 
[HttpGet]  
public async Task DoLongRunningOperationAsync()  
{   
    await Task.Delay(2000);  
} 
Changing the server code as described results in better performance of the server. The next chapter explains those results for the same test scenario (sequence of concurrent requests) from above.

Performance

The image below shows the performance measurement results when sending 1, 10, 20, 30, 40, 50, 100, 200, 300, 400, 500, 1000, 2000 and 3000 concurrent requests to the WebAPI service. Comparing to the graph of the first measurements above, the plot below looks a lot smoother. There are several points that have been improved with the asynchronous WebAPI service:
  1. There are no failed requests. As mentioned above, asynchronous calls in the WebAPI service are done in other background threads. So worker threads can be released earlier and they are available in the thread pool again to handle other requests. 200 worker threads in the thread pool seem to be enough to handle all requests in the test sequence from 1 to 3000 concurrent requests. In the first scenario the limit has been reached with 500 concurrent requests.
  2. More requests per second can be handled by the WebAPI service. The image below shows that 50 requests per second (more or less) are handled during the test period. The results of the first test scenario shows, that only 4-5 requests per second can be handled (until 1000 concurrent requests are send, where requests begin to fail).
  3. The test sequence is handled faster. In the scenario above it takes about 40 minutes to run the test sequence from 1 to 500 concurrent requests. The graph below shows that the sequence from 1 to 400 concurrent requests are handled within 4 minutes. After 8 minutes the server handled the sequence from 1 to 1000.

Figure 2: Performance of asynchronous WebAPI services
Figure 2: Performance of asynchronous WebAPI services

Conclusion

The test scenarios show that server performance can be improved dramatically by making WebAPI services asynchronous using async and await. Requests are handled faster, more requests can be handled and so there are less requests that fail. Making WebAPI services asynchronous is as easy as possible when using the async and await language features of C#.
If you have any questions or if you need assistance with your code, do not hesitate to contact me! I would be happy if you have comments, critics or opinions to this post. Please let me know!

Sunday, 22 February 2015

ASP.NET Web API vs. Windows Communication Foundation (WCF)

As described by Microsoft:

"ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework."
"Windows Communication Foundation (WCF) is Microsoft’s unified programming model for building service-oriented applications. It enables developers to build secure, reliable, transacted solutions that integrate across platforms and interoperate with existing investments."
Although these descriptions are brief, side-by-side it is easy enough to determine how Microsoft tries to distinguish the two frameworks: Web API is for RESTful services and WCF is for "existing investments."  Let's dive into the details about why Microsoft has two service frameworks and when each should be used...

The Basics: SOAP and REST (and OData)

SOAP

Without getting too deep into its history, Simple Object Access Protocol (SOAP) is a Microsoft invented protocol that was meant to create a structured way of sending and receiving data over the wire.  This protocol is one of the main foundations of WCF and utilizes XML to create services with typed data and methods.  In the typical scenario, a Web Services Description Language (WSDL) file is created from service code and is provided, usually through a static URL, to the client.  The client uses this WSDL file to understand what methods are available on the service, how to call them, and what the classes of the returned objects will be.  This is a very action-driven model that focuses on what actions a service is a capable of performing.
Example Service Endpoint: http://www.yourcompany.com/SOAPService.Svc

REST

REpresentational State Transfer (REST) is not a protocol, but an architecture and design pattern for building and calling web services.  This is the pattern that Web API was designed to utilize to build web services.  It is a very resource-drivenarchitecture that exposes endpoints based on objects and not functions.  RESTful services also make use of the standard HTTP methods and constructs to exchange data; using GET, POST, PUT, DELETE, and sometimes PATCH a caller can denote which action to perform on the object being accessed at the requested endpoint.  Query parameters and content in the body of the request can also provide ways to pass parameters to the service.

OData

Open Data Protocol (OData) is another Microsoft defined protocol (now an open web standard).  This protocol extends AtomPub and is a resource-driven model.  It allows querying resources on the web service using different endpoints to denote the resource type and query parameters to specify how to filter the results.  OData services can also be built using Web API and are usually considered a type of REST service.
Example Query: http://www.yourcompany.com/api/OData.svc/Resources()?$filter=ResourceType eq Images&$top=20

The Decision: Web API or WCF?

Client Interoperability

RESTful services, and therefore Web API by extension, are focused on simplicity and being lightweight.  Any application that is able to access a website can access a RESTful service by using the same HTTP calls.  This differs from SOAP where the client must understand the web service by utilizing the WSDL file.  The WSDL configuration adds some complication and requires additional logic that might not be readily available on many devices (phones, smart TVs, etc.) and programming languages and frameworks.

Coding Overhead

On the client side it is simple to call a RESTful service using HTTP, but hardcoding resource endpoints, serializing and deserializing objects, and recreating custom classes that are returned can be difficult; all of that low level interaction with the web service is abstracted in SOAP services and is "magically" done for you.  On the service side, WCF tends to be more configuration heavy and typically requires extensive XML work to get it configured just right. Web API, conversely, has a more standard "out-of-the-box" setup that works for most services, and provides the capability to provide customizable services that extend the base services, such as media type formatters that handle serialization, when needed.

Speed/Bandwidth

Since RESTful services only use basic HTTP, the request and response packets are generally smaller than SOAP request and response packets which package parameters, objects, metadata, etc. in a thick, usually XML, payload.  Sometimes this is an important consideration when dealing with mobile or low bandwidth devices.  The simple HTTP request/responses also tend to be more human readable than SOAP requests/responses*, although that is not as significant since these services are usually consumed programmatically.
*The caveat to this statement is that WCF services can be customized to use a simpler format, although this isn't the standard implementation.  WCF can also utilize HTTP and other protocols, although, again, that is not the standard implementation.

Functionality/Purpose

As described above, SOAP services should be very action-driven and REST/OData services should be very resource-driven.  Although any action-driven service can be converted into a resource-driven service, there are some cases where one SOAP call could translate into multiple REST calls; this creates additional overhead in calling the service, increases the complexity of the client's code, and can potentially cause data issues in poorly designed systems.  Well designed REST services should be able to mitigate this with indirect actions.  As an example, a SOAP call that purchases an item for a customer could do the following:
  1. Create an order
  2. Reduce the quantity of an item in stock
  3. Create a new shipping task
  4. Update the customer's information and order history
That single SOAP call could translate to four different REST calls updating each of those resources, or, in a properly designed system, one create (POST) PurchaseOrder call that then triggers actions to update the other resources as necessary.  Ultimately, RESTful services should be simple and atomic, but SOAP services, for better or for worse, have the flexibility to be bulky and complex.
REST services are more "discoverable" than SOAP services since they can be freely accessed in URLs.  Good REST services are also intuitive enough to figure out, both in regard to endpoints and idempotency.  As an example, ifwww.yourcompany.com/api/Employees/1 provides the employee with an ID of 1, then it is easy enough to determine that www.yourcompany.com/api/Employee/2 provides the employee with an ID of 2.  Assuming you know the service also contains customers, it is again easy enough to determine thatwww.yourcompany.com/api/Customer/1 provides the customer with and ID of 1.  Similarly intuitive, using the HTTP actions can reflect the idempotency of a call in REST services.  A PUT operation, for example, should be idempotent since you are updating fields with specific values.  A similar call in a SOAP service may not be as easy to determine whether it is idempotent or not.

Security

WCF and Web API both have security standards that are accepted.  In WCF, highly typed security frameworks and helpers are available to provide enterprise-level security, including security that meets the Web Services Interoperability Organization (WS-I) standards.  In Web API, typical web standards are used for security such as Basic and Token authentication, as well as more complex web standards such as OAuth.  If properly implemented, security in either framework will be just as good as the other, although some companys prefer and often require specific security implementations.  RESTful services, however, do provide a little more flexibility than SOAP that can be useful when authenticating with an external service such as Windows Live IDs, Google, Facebook, or Twitter.

Conclusion

Unfortunately, I cannot say that one is better than the other.  Fortunately, there is a fairly straightforward way of determining which framework to use when building a new web service.  Go through the paragraphs above and determine who is using the service, how they are using it, and how the service will be built and scaled.  My general rule of thumb is: If it's an internal/intranet web service, use WCF; if it's an external/internet web service, use Web API.

Sunday, 23 November 2014

Building your own API and Securing it with oAuth 2.0 in ASP.NET WebAPI 2

Objectives:

  1. Make a true RESTful Web API (enable CRUD functions by HTTP POST, GET, PUT, and DELETE).
  2. Enable Cross-Origin Resource Sharing, i.e., CORS (the accessibility of the API by JavaScript can be controlled).
  3. Enable Secure Authorization for API calls (use the OAuth 2.0 authorization framework).
  4. Enable Transport Layer Security, i.e., SSL (reject every non-HTTPS request).
Required Tools:
  1. A Windows Computer.
  2. Microsoft Visual Studio Express 2013 for Web (free download).
Recommended Knowledge:
  1. Securing (ASP.NET) Web API based architectures (video).
AND/OR
  1. ASP.NET Web API 2 (tutorials).
  2. OAuth 2.0 Authorization Framework (specification).
  3. Open Web Interface for .NET (OWIN).
  4. Writing an OWIN Middleware in the IIS integrated pipeline (tutorial).
  5. Enabling Cross-Origin Requests in ASP.NET Web API (tutorial).

An Skeleton Project by ASP.NET Web API 2 (oAuth 2.0 and CORS support)

1. Creating the Project
Create an ASP.NET Web Application (Visual C#) in Microsoft Visual Studio Express 2013 for Web. Let’s name it Skeleton.WebAPI. Select the Web API template and Change Authentication from ‘No Authentication’ to ‘Individual User Accounts’, [screenshot].
The ‘Controllers/ValuesController.cs’ holds our sample API endpoints. Run the project and in the browser go to ‘http://localhost:port/api/values‘ and you should get a 401 Unauthorized.
2. Writing the Sample API Endpoints
In ‘Controllers/ValuesController.cs’, comment out [Authorize] to disable authorization. Run the project and in the browser go to ‘http://localhost:port/api/values‘ and now you should get 2 values.
Change ‘Controllers/ValuesController.cs’ with the following code to enable CRUD operations, [Link]. This controller now accepts HTTP GET, POST, PUT, and DELETE to receive a list of values, add a value, update a value, and delete a value. Currently, these values are stored in the Web Server memory, but ideally they will be saved in the database. I recommend using Repository Pattern for it, [More info].
Let’s write a simple html page to call these api endpoints. For example, the following code can be used for receiving the list of current values:
12345
$.ajax({
type: "GET",
url: 'http://localhost:port/api/values',
success: function (_d) { alert(JSON.stringify(_d));}
}).fail(function (_d) { alert(JSON.stringify(_d)); });
view rawapi_tester.js hosted with ❤ by GitHub
The full list of API calls by JavaScript can be found here. At this point, you will notice that all the API calls are returning errors. That’s because we haven’t added Cross-Origin Resource Sharing (CORS) support to the server.
3. Enabling Cross-Origin Resource Sharing (CORS) support 
To Enable CORS support, first install Microsoft.AspNet.WebApi.Cors by NuGet. Open up ‘App_Start/WebApiConfig.cs’ and add the following line in the Register method:
12345
public static void Register(HttpConfiguration config)
{
config.EnableCors();
// other stuff
}
view rawWebApiConfig.cs hosted with ❤ by GitHub
Then open your API Controller, ‘Controllers/ValuesController.cs’ and add the following line before the class definition:
123
[EnableCors(origins: "*", headers: "*", methods: "*")]
// [Authorize]
public class ValuesController : ApiController { /*Class Definition*/}
view rawValuesController.cs hosted with ❤ by GitHub
It tells the server the accept all types requests. You can obviously filter out the requests. For more customization, read this.
4. Cleaning up the Views from the project
You should notice that the VS template created some views in the project. As we are building a pure Web API, there will be no views. So, delete App_Start/[BundleConfig,RouteConfig].cs, Areas/*, Content/*, Controllers/HomeController.cs, fonts/*, Scripts/*, Views/*, Project_Readme.html, andfavicon.ico. Finally, remove the following lines from Global.asax.cs:
12
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
view rawGlobal.asax.cs hosted with ❤ by GitHub
At this point, we have completed Objectives 1 and 2. The code up to this point can be  downloaded fromhttps://github.com/rfaisal/ASPWebAPI_Example_OAuth_CORs/tree/crud_cors_only_v1.
5. Adding oAuth 2.0 support
In the simplest terms, here is how oAuth (or most token based authorization) works. The client request an Access Token from the Authorization Server. The Authorization Server verifies the identity of the client somehow and returns an Access Token, which is valid for a limited time. The client can use the Access Token to request resources from the Resource Server as long as the Access Token is valid. In our case, both Authorization Server and the Resource Server are the same server, but they can be separated easily.
Ideally, you need to write an OWIN Middleware in the IIS integrated pipeline for oAuth. But, the VS template generates the necessary codes for the OWIN Middleware. Watch this video to learn more about these implementations.
Now, we will add 2 more functionality, namely registering a new user and requesting a Access Token based on the username and password.
The user registration controller (Controllers/AccountController.cs) is already generated by the Template. First add the following line in the AccountController to allow CORS:
1
[EnableCors(origins: "*", headers: "*", methods: "*")]
Then you can call the end point http://localhost:port/api/Account/Register/ and HTTP POST an object consisting of UserName, Password, and ConfirmPassword to register an account.
Now, the endpoint for requesting an Access Token is also generated by the template. The code is in App_Start/Startup.Auth.cs :
12345678910
//other stuff
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
//other stuff
view rawStartup.Auth.cs hosted with ❤ by GitHub
It says that the client can request an Access Token by calling http://localhost:port/Token endpoint and HTTP POSTing grant_type, username, and password as Url Encoded String. This endpoint, however, is not an API endpoint. To enable CORS to this endpoint we need to add the following code segment to the ConfigureAuth function of App_Start/Startup.Auth.cs file.
1234567891011121314151617181920212223242526
public void ConfigureAuth(IAppBuilder app)
{
//other stuff
app.Use(async (context, next) =>
{
IOwinRequest req = context.Request;
IOwinResponse res = context.Response;
if (req.Path.StartsWithSegments(new PathString("/Token")))
{
var origin = req.Headers.Get("Origin");
if (!string.IsNullOrEmpty(origin))
{
res.Headers.Set("Access-Control-Allow-Origin", origin);
}
if (req.Method == "OPTIONS")
{
res.StatusCode = 200;
res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET", "POST");
res.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "authorization", "content-type");
return;
}
}
await next();
});
//other stuff
}
view rawStartup.Auth.cs hosted with ❤ by GitHub
We are almost done. We have to modify all the API calls to pass this Access Token. First of all, un-comment [Authorize] attribute on the ValuesController and run to make sure that all of the API calls are returning 401 Unauthorized. Add the following property with each ajax call to pass the Access Token as the Bearer Token:
123
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", 'Bearer ' + _access_token);
},
view rawbearer_token.js hosted with ❤ by GitHub
At this point, we have completed Objectives 1, 2, and 3. The code up to this point can be  downloaded from https://github.com/rfaisal/ASPWebAPI_Example_OAuth_CORs/tree/crud_cors_oauth.
6. Enforce SSL for all API calls
Any information that is not transferred over SSL is not secure. So, we are going to reject any request that doesn’t come over HTTPS. First we will write a filter that can be used to filter out non-https requests. Here is the code:
1234567891011121314151617
public class RequireHttpsAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
{
actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
{
ReasonPhrase = "HTTPS Required"
};
}
else
{
base.OnAuthorization(actionContext);
}
}
}
When we add this class to our project, we have [RequireHttps] available. Add this attribute to all the Controller class. For example,
12345
[RequireHttps]
[EnableCors(origins: "*", headers: "*", methods: "*")]
[Authorize]
[RoutePrefix("api/Account")]
public class AccountController : ApiController {/*class definition*/}
1234
[RequireHttps]
[EnableCors(origins: "*", headers: "*", methods: "*")]
[Authorize]
public class ValuesController : ApiController {/*class definition*/}
view rawValuesController.cs hosted with ❤ by GitHub
Finally, we also want the Token request to be enforced over HTTPS. To do so, remove ‘AllowInsecureHttp = true’ from Startup.Auth.cs.
123456
OAuthOptions = new OAuthAuthorizationServerOptions
{
//other stuff
TokenEndpointPath = new PathString("/Token")
// AllowInsecureHttp = true
};
view rawStartup.Auth.cs hosted with ❤ by GitHub
To test the SSL enforcement, change the SSL Enabled property to true for the Development Server in Visual Studio and use the SSL Url, [screenshot].
A screenshot of the client, [screenshot].

22 thoughts on “Building your own API and Securing it with oAuth 2.0 in ASP.NET WebAPI 2

  1. Anas KVC April 3, 2014 at 11:49 pm Reply
    Great article.
    To run the sample project in VS 2012 we need to do the following changes.
    1. Add the missing nuget packages using package manager console
    install-package Microsoft.AspNet.Identity.Core
    install-package Microsoft.AspNet.Identity.EntityFramework
    2. Open the local db on vs server explorer.
    It looks like AspNetUsers table doesn’t have the default columns which is mapped from IdentityUser object. (It will throw the error when we try to register a new user)
    So,
    remove the __MigrationHistory table.
    remove the AspNetUsers table and execute the new query on server explorer.
    CREATE TABLE [dbo].[AspNetUsers] (
    [Id] NVARCHAR (128) NOT NULL,
    [Email] NVARCHAR (256) NULL,
    [EmailConfirmed] BIT NOT NULL,
    [PasswordHash] NVARCHAR (MAX) NULL,
    [SecurityStamp] NVARCHAR (MAX) NULL,
    [PhoneNumber] NVARCHAR (MAX) NULL,
    [PhoneNumberConfirmed] BIT NOT NULL,
    [TwoFactorEnabled] BIT NOT NULL,
    [LockoutEndDateUtc] DATETIME NULL,
    [LockoutEnabled] BIT NOT NULL,
    [AccessFailedCount] INT NOT NULL,
    [UserName] NVARCHAR (256) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
    );
    This will resolve the issues.
  2. Faisal R. April 4, 2014 at 6:45 am Reply
    Thanks Anas!
  3. dave April 21, 2014 at 5:38 am Reply
    Is it possible to use Web API 2′s build in external authentication with Angular JS being hosted on a different web-server? If so does anyone know of an example?
    I’m struggling to get it working. The facebook request is giving me a CORS issue. I’m not sure what is going on.
    My only guess is the redirect is coming from a different domain than the web api is hosted on. Which is what is doing the facebook configuration.
    • Faisal R. April 21, 2014 at 6:53 am Reply
      Hi Dave-
      I am assuming you just uncomment app.UseFacebookAuthentication inStartup.Auth.cs and using it the same way the Web API template example is using, except the WebAPI and client is hosted in different servers.
      In that case, adding the domain urls for both your hosts to facebook app settings should work. If not, can you please send me your login flow.
  4. dave April 21, 2014 at 11:02 am Reply
    Sure. My login flow is as follows:
    1.) User navigates to my login page at http://localhost:8000/app/index.html#/login
    2.) On page load I make a request to my web api to load the ExternalLogins at api/Account/ExternalLogins?returnUrl=%2F&generateState=true. This loads the URLS for when the user clicks the login buttons (exactly how its done with Microsoft SPA template)
    3.) When the user clicks login with facebook button, the web api endpoint api/Account/ExternalLogin. The user is not authenticated to the ChallengeResult is returned. This is where the redirect to the facebook login page should happen. I see the request being made in chrome dev tools but the redirect gives me a No Access-Control-Allowed-Origin error.
    I notice the redirect request has a Origin header with a null value. I think this is the problem but I don’t know why its there. I can duplicate the api call in fiddler to my api/Account/ExternalLogin api, but remove the Origin header, and I dont get the No Access-Control-Allowed-Origin error.
    The origin header gets sent to my API from my angular js client, but im not sure why its on the redirect, or why the value is null.
    Any idea on what could be going on? Thanks
  5. dave April 21, 2014 at 11:47 am Reply
    Ok. Thanks for the response. I did find things like this –https://bugs.webkit.org/show_bug.cgi?id=98838
    Not sure if thats the problem.
  6. dave April 22, 2014 at 11:56 am Reply
    Any luck?
    • Faisal R. April 22, 2014 at 11:58 am Reply
      Hi Dave-
      Sorry, I haven’t had a chance to look into this yet. I will do it tonight, please check back tomorrow.
    • Faisal R. April 22, 2014 at 6:02 pm Reply
      Hi Dave-
      I tested it and it worked just fine for me. This is what I did:
      1. Added my facebook appId and appSecret to the project of the blog post. and run it
      2. Added http://localhost:49811/ in my facebook app’s “site url”
      3. Run api/Account/ExternalLogins?returnUrl=%2F&generateState=true to get a list of urls
      4. Created a new SPA project and its login.viewmodel.js–>self.loginnction –> set window.location to the url I get from Step 3 (hard coded)
      5. Run the SPA and click on the login with facebook button.
      It took me to WebAPI’s root url with a access_token in the url (meaning successful authentication)
  7. dave April 22, 2014 at 7:43 pm Reply
    Faisal,
    I’m going to start fresh and try exactly what you just did. Thanks for the response. I will let you know how it goes.
  8. Jimmy May 2, 2014 at 4:42 am Reply
    Hello
    is there a second part or has this tutorial changed after getting published ?
    I can’t see any details about DB in here so I’m confused how to authenticate and store user data for this application?
    I can see one comment regarding a table called ‘AspNetUsers’ and EF framework but not mentioned in the tutorial it self
    Cheers
    • Faisal R. May 2, 2014 at 12:45 pm Reply
      Hi Jimmy-
      No there is no 2nd part. You can change the database info in Web.config file. By default, it uses a .mdf file in your local file system for data storage
  9. Alexander Smotritsky (@gyrevik) August 10, 2014 at 8:59 pm Reply
    I think Jimmy may have asked his question because he and other readers may not know that when you create an asp.net web api project you can specify authentication — individual users accounts and this will generate the database/mdf and entity framework layer for it.
  10. mohit September 4, 2014 at 3:29 am Reply
    this post is very helpful
    question 1: But instead of using entity framework …how can we implement it with simple ado.net ?
    question 2 : can it be done without using MVC?
    • Faisal R. September 4, 2014 at 9:41 am Reply
      1. It doesn’t matter what data-source you use and how you use it. It will still work with MySQL, MongoDB and of course, ADO.Net. You need to modify theAccountController.cs file only.
      2. Yes, it can be done. In fact, in the example, there is no view only Model and Controller.
  11. Sultan Mehmood September 20, 2014 at 4:12 am Reply
    Hi Faisal,
    I am newbie to Web APIs. I wanted to know if we dont have Owin Middleware, still your code will work ? Because I am trying to run your code and its giving me 404 for Requested URL localhost:(myport)/Token.
    Your response will be highly appreciated.
    Thanks
    • Faisal R. September 20, 2014 at 11:28 am Reply
      I am pretty sure you need OWIN. 404 is a “Not Found” error. Without looking into details I can only advise to make sure that the API project is running.
      • Sultan Mehmood September 20, 2014 at 11:50 am
        Thanks fir your reply. I was able to figure it out.
    • Paco October 7, 2014 at 1:23 pm Reply
      You mentioned you resolved your issue…care to elaborate? I’m having the same issue where I get a 404 when hitting my TokenEndpointPath at /token.
      • Sultan Mehmood October 8, 2014 at 11:56 pm
        Can you please post your code here ? without looking your code I can not tell what exactly you are having….
  12. monique ma October 8, 2014 at 2:51 pm Reply
    I tried the same structure but using the MVC as test site. When I tried to get token, I got bad request error.
    Code as following:
    public string GetToken(string userName, string userPW)
    {
    var content = “grant_type=password&username=” + userName + “&password=” + userPW;
    string uri = baseUri + “Token”;
    using (HttpClient client = new HttpClient())
    {
    client.BaseAddress = new Uri(baseUri);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(“application/x-www-form-urlencoded”));
    var response = client.PostAsJsonAsync(uri, content).Result;
    return response.Content.ToString();
    }
    Where is my problem, I need get this token to set further request.
    Like this:
    public Member GetMemberByID (int memberId)
    {
    var token = GetToken(“xinm”, “Test1234″);
    string uri = baseUri +”api/member/170/GetMember”;
    using (HttpClient client = new HttpClient())
    {
    client.BaseAddress = new Uri(baseUri);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(newMediaTypeWithQualityHeaderValue(“application/json”));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token);
    Task response = client.GetStringAsync(uri);
    return JsonConvert.DeserializeObjectAsync(response.Result).Result;
    }
    }

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...