Securing APIs

Wildermuth

Shawn Wildermuth

Welcome to this review of the fourth module from the Pluralsight course Implementing an API in ASP.NET Web API by Shawn Wildermuth.

Shawn is a 14-time Microsoft MVP (ASP.NET/IIS) and is involved with Microsoft as an ASP.NET Insider, ClientDev Insider and Windows Phone Insider.

He is the author of eight books on software development, and has given talks at a variety of international conferences including TechEd, Oredev, SDC, VSLive, DevIntersection, MIX, DevTeach, DevConnections and DevReach.

The full course also contains modules on:

– Implementing an API in ASP.NET Web API
– API Basics
– Versioning
– REST Constraints
– Web API Version 2

Securing APIs

APIs and Security

The amount of effort we should give to securing our data is related to how sensitive the data is.

For example medical records and credit card numbers are highly sensitive and you could be liable for large fines if there is a data breach.

So we should start with the question “What needs to be secured?”

This was previously discussed in Shawn’s course “Web API Design” and covered again here.

The following items must be secured:

– Private or personalized data
– Sensitive data across the wire
– Credentials of any kind
– Servers against denial of service attacks

Shawn says not all of these things can be handled at the API level.

We can do Threat Modeling to understand the threats to our business.

Some of the threats discussed in this lesson are:

– Users
– Eavesdropppers (packet sniffers etc.)
– Hackers
– Personnel

Once we understand the role of the API in protecting our data, we can do some things in Web API to support that.

Requiring SSL

We want to have a way in our Web API to force the website to use HTTPS.

In this lesson, Shawn assumes that we have already figured out how to get certificates onto our IIS server.

The focus here is to make sure that Web API itself uses HTTPS even if the server isn’t configured to force it on the entire website.

There could be cases where we only want to apply HTTPS to the Web API.

We do this with Filters, and in this lesson Shawn shows us how to create a RequireHttpsAttribute class.

You may have noticed that MVC has a RequireHttpsAttribute class, however this will not work with Web API.

We need to derive from one of the filters in System.Web.Http.Filters that themselves derive from IFilter.

In this case we derive from AuthorizationFilterAttribute and override the OnAuthorization method.
This code checks if the RequestUri scheme is HTTPS, and creates a “Https is required” HTML message if not.

If it isn’t a GET, we respond with Not Found with actionContext.Response = req.CreateResponse(HttpStatusCode.NotFound)
and we set the Content of the response to a new StringContent with our HTML response, UTF8 encoding and “text/html” media type.
This sets all of the appropriate response headers.

If the request is a GET, the response is similar but it will be Found instead of NotFound.

This code block also create a HTTPS URI with UriBuilder and Port 443, and assigns this to Response.Headers.Location

With this filter written, we can apply it to our Controller by using it as an attribute, either on an action method, or on the whole controller:

[RequireHttps]
public class FoodsController : BaseApiController

We can also apply it to every controller by updating our WebApiConfig.cs

config.Filters.Add(new RequireHttpsAttribute());

This adds our filter to the standard set of filters applied to every Web API request.

Fiddler

Also in this lesson, Shawn makes a HTTP GET request to /api/nutrition/foods using Fiddler.
We see two responses: a 302 Found response, and a 502 response.

The 302 response contains the Location beginning with https:// and the message “Https is required”

The reason that we get a second response is because Fiddler immediately attempts to make a new request to the Found location.
We get a 502 error because we don’t have HTTPS configured on our test server.

On Firefox

Finally Shawn makes the same request using Firefox, and we see the URI changes to https:// automatically.

In this situation Shawn likes to use #if !DEBUG so that he can locally test the application without SSL, but all production builds will require SSL.

Cross Origin Security and JSONP

If we want to be able to support JavaScript requests that come from other domains, it won’t work by default, but we have a couple of options.

1. Support JSONP as a format

This wraps the response in a piece of JavaScript. This gives permission to execute the JavaScript when it is called back.

JavaScript files can be called from multiple domains, browsers often allow JSONP requests.

2. Enable Cross Origin Resource Sharing (e.g. CORS)

This is supported in Web API version 2. At the time of recording of this module, Web API 2 was up and coming. However a final module was later added covering Web API 2.

In Web API v1, there’s no native support for JSONP. However there is https://github.com/WebApiContrib which has implemented JSONP as a formatter.

We can download this using Nuget. The package is WebApiContrib.Formatting.Jsonp

Shawn demonstrates how to use this, creating an instance of JsonpMediaTypeFormatter with a jsonFormatter argument.

The reason that Shawn adds JsonpMediaTypeFormatter as the first formatter is the standard JSON formatter will look at Application/JavaScript and return plain JSON.

With the code written, Shawn runs up Fiddler Composer and shows the effect of using different Accept request headers.

A JSONP request wraps the HTTP response in a small piece of JavaScript that calls a function that we have implemented.

We must tell the API that there’s a query string parameter specifying the name of the callback.

In Fiddler Composer, Shawn adds ?callback=foo to the URI and executes the request.

When jQuery AJAX or Angular or another framework/library is used, it sees this is returning data type, and knows how to parse it. As part of the parsing it executes the method call.

In other words, JSONP pretends that we’re downloading a piece of JavaScript to be executed rather than pure data

Supporting CORS

At the time of recording of this lesson, Web API 2 wasn’t yet released but a preview version was available.

Shawn gives a quick overview of it’s features here. For more detail see the Web API Version 2 module.

Authentication vs. Authorization

Authentication is using credentials to determine identity

Authorization is verifying an Identity has rights to a specific resource

So what might we want to Authenticate?

– Allowing developers to use the API with App Authentication (typically an AppKey and a Secret)
– Authenticating Users to grant them access to the API (typically Basic Auth, OAuth and/or Integrated Auth)

Piggybacking on ASP.NET Authentication

This is the simplest approach. Our demo application allows users to Register or Login, and this uses the ASP.NET Authentication.

A simple case is allowing access to our API if the user is authenticated.

Up to now, we can access our API without any authentication.

We can add the built in Authorize attribute to our Web API controller.
With this added, when we request information from our API we see the message: “Authorization has been denied for this request.”
But if we login to the website we can now update the browser URI to our API and we are allowed access to that as well.

In our JavaScript we can simply redirect to the Login page if we get a 401 Unauthorized response.

But this isn’t always appropriate. Users won’t always be using a website as well as our API. Forms authentication is a Microsoft technology and it might not work cleanly with non Microsoft clients.

Shawn demonstrates a CountingKsIdenitytService which uses Thread.CurrentPrincipal.Identity.Name.

When he logs in as swildermuth instead of shawnwildermuth and then requests the API, we just see an empty array. This is because the database doesn’t know that swildermuth is a user.
The name swildermuth is fetched from memory not the database. But in the DiariesController method, it tries to get the user name from the database.

Implementing Basic Authentication

Basic Authentication allows us to take the credentials of the user and pass them in through a header.

These credentials are included in every call.

We implement this by adding a new class in Filters called CountingKsAuthorizeAttribute. This class derives from AuthorizationFilterAttribute and we override the OnAuthorization method.

This method checks whether the AuthorizationHeader exists in the request, that the Scheme is Basic, and that there is a raw credential.

If so, it gets the credentials as a byte array from the raw credential using iso-8859-1 encoding, and splits it into the username and password.

There is a Microsoft type WebMatrix.WebData.WebSecurity which has a Login method that we can use. If this returns we set the identity to the new user using System.Security.Principal.GenericPrincipal.

We also add a HandleUnauthorized method in here which sets the Response to Unauthorized and adds a WWW-Authenticate header.

Shawn also discusses the InitializeSimpleMembership attribute which is part of the ASP.NET MVC 4 template.

Testing Basic Authentication

Shawn tests this using Fiddler by making a request with following Request Headers:

Host: localhost:8901
Authorization: Basic c2hhd253aWxkZXJtdXRoOnBsdXJhbHNpZ2h0

Our credentials are encoded using http://base64encode.org/

Tokens Authentication

Shawn runs through the process of authenticating a token:

  1. Developer requests an API Key
  2. Supplies API Key and Shared Secret to API
  3. Requests Token
  4. Validates and Returns Token
  5. Uses API with Access Token until Timeout

We create a simple and naive implementation of this, starting with a TokenController deriving from BaseApiController.

This has a Post method which takes a TokenRequestModel with an ApiKey and Signature.

At the end of this lesson we head over to Fiddler again and make a POST request with the apiKey and Signature in the request body.

We get back a JSON object with an expiration date and token value.

Implementing Token Authentication

Shawn adds per user logic into the CountingKsAuthorizeAttribute.

We use an attribute called [Inject] which allows property injection, and this is part of the Ninject IoC container.

We also create a new class called NinjectWebApiFilterProvider which derives from IFilterProvider and implements GetFilters.

Shawn says it may be added either Web API itself or to the WebApiContrib project at a future date.

Walkthrough of OAuth Implementation

OAuth is similar to Token-based but there are some extra steps involved.

  1. Developer requests an API Key
  2. Supplies API Key and Shared Secret to API
  3. Requests Token
  4. Validates and Returns Token
  5. Redirects to API’s Auth URI
  6. API displays the Authorization UI “xxx’s app wants you to give permission. Approve?”
  7. User Confirms Authorization
  8. Redirects Back to Developer
  9. Request Access Token via OAuth & Request Token
  10. Returns Access Token (with Timeout)
  11. Uses API with Access Token until Timeout

Shawn says he could do a whole course and spend 6 hours building this demo.

Instead he shows us the DotNetOpenAuth project which includes implementations of OAuth 1 and 2.

Shawn talks about the OAuth2ProtectedWebApi project within the DotNetOpenAuth solution and says this is the best place to start.

These controllers use asynchronous communication with the Task type, and Shawn says this is a good idea.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s