Category Archives : Web Services and Interop

A category for WCF and interop


Documenting a ASP.NET Web API with Swagger

MVC3    +   swagger2

In this article, I’m going to take a look at some ways you could generate documentation for ASP.NET Web API.  Unless you’ve never generated a Web API website, you’ll be aware that the default templates already include functionality to generate documentation for the API which you might implement, an example of which is here at authme.ws.

Getting started

There’s more than a couple of articles already written about how to generate documentation for ASP.NET Web API using Swagger (and there’s a NuGet package called Swashbuckle which you can easily integrate), but I needed something less dynamic – in fact, I needed to generate static documentation representing what we’d promoted to production (point in time), as it needed to be provided for an audit.

The traditional documentation (e.g. Sandcastle Help File Builder) i clearly not viable as it documents managed code rather than the more important API interfaces and runtime models.

Luckily for me, there’s a toolset complimenting Swagger called Swagger codegen which generates client code to consume APIs, and for me – an ability to generate static HTML (courtesy of [1]) Unfortunately I couldn’t find a .NET port of Swagger Codegen, so I bit the bullet and compiled the Java binaries from the source using Maven and the latest JDK.

What you need

You need to be able to generate a Web API site which you can spin up in IIS or IIS Express.  Ideally, what you’d do is integrate the previously mentioned Swashbuckle NuGet package into your existing (or new) Web API Project. Once installed, all you need to do is change the project settings to generate a comments XML file (not a mandatory step, but useful – see image below) and then configure the SwaggerConfig.cs file which is inserted into the project under the App_Startup folder.

image
Enable XML comments output.

image
Swashbuckle NuGet packages (Swashbuckle and Swashbuckle.Core)

Here’s a really brief (minimal) implementation of the SwaggerConfig with the copious comments removed:

public class SwaggerConfig
{
   public static void Register()
   {
       var thisAssembly = typeof(SwaggerConfig).Assembly;
       GlobalConfiguration.Configuration 
       .EnableSwagger(c =>
       {                      
          c.SingleApiVersion("v1", "API Services");
          c.IncludeXmlComments(GetXmlCommentsPath());
       })
      .EnableSwaggerUi(c =>
       {
       });            
   }
   private static string GetXmlCommentsPath()
   {
       var path = String.Format(@"{0}bin\Services.XML", AppDomain.CurrentDomain.BaseDirectory);
       return path;
   }
}

If you compile and run, you should be able to resolve the Swagger UI, like this:

image

image

A very, very impressive dynamic documentation UI.

The key here is in the generated JSON which is accessible via the URI in the textbox, in my case it is: http://localhost:2218/swagger/docs/v1 (swagger.json)

image
Example swagger JSON

Converting to static documentation

Moving on to swagger codegen, you’ll also need a copy of the Java JDK. After installing the JDK (if you haven’t already), you’ll then need to ensure that the JAVA_HOME environment variable is correctly to the correct directory (NOT the runtime directory) and install/extract Maven binaries.

I used the latest JDK (1.8, 32 bit) which has the following directory: C:\Program Files (x86)\Java\jdk1.8.0_51 I also installed Maven into the Java directory and added it to the system path (the bin directory, specifically):

image

When ready, al you need is to extract the swagger codegen code into a local directory, browse to that directory in a command prompt and type mvn package:

image  image

Wait a while while Maven grabs all the packages

Once successfully compiled, it’s a simple matter of executing the compiled jar file.  In my case, I had placed the extracted swagger files in C:\Tools.  Open a command prompt and browse to the following location:

C:\Tools\swagger-codegen-master\

To generate a static HTML document for your API use the following syntax:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i http://localhost:2218/swagger/docs/v1 -l html

This produces a nice static document of your Web API:

image

A nice static HTML file which you can “print” to PDF, or copy and paste into Word

Troubleshooting

If your generated .json produces an empty object like this:

“Object”: {
“type”: “object”,
“properties”: {}
}

It could well be due to a lack of sufficient information about the data type in a response.  For example, take the following example Controller definition:

public class VersionController : ApiController
{
private readonly IVersionQuery _query;
public VersionController(IVersionQuery query) { Guard.That(query, "query").IsNotNull(); _query = query; }

[AllowAnonymous] public IHttpActionResult Get() { var version = _query.GetVersion(); return Ok(version); } }

What we’re missing here is an attribute which provides the return type, like this, decorating the Get() implementation:

[ResponseType(typeof(VersionInfo))]

I was assisted in making this discovery by the issues logged at [2], [3].

Alternatives:

References:


How IdentityServer3 Handles Client Credentials Flow

Identity Server 3 supports the Client Credentials OAuth2 grant.  I wrote a brief introduction to both OAuth2 and IdentityServer3 last month, this is a follow-on article exploring some other facets of authentication.

This is a little bit like basic authentication, in that the client (the application which wants to consume a WebAPI) passes a preshared key to ID3 in exchange for a bearer token.

The values passed from the Client to ID3 can be specified in either the HTTP/S header or body of the POST request.  I prefer specifying it in the Header.

The format is as follows:

Authorization: Basic (“Client ID” + “Client Secret”)

Where:

  • “Client ID” is the ID for the application (“Client”) in ID3
  • “Client Secret” is the unencrypted version of the client secret stored in ID3’s database
  • The Parenthesis indicates that the content should be Base64 encoded

The POST request also needs to contain the authorization flow type (client_credentials in this case) and intended scope (target) in the Body of the request.

The following PowerShell script demonstrates how to assemble a valid bearer token request:

function Hash($textToHash)
{
      $toHash = [System.Text.Encoding]::UTF8.GetBytes($textToHash)
      return [System.Convert]::ToBase64String($toHash)
}

$authUri = "https://identityserver/"
$authPostUri = "https://identityserver/connect/token"
$scope =  "someTargetApiName"
$client_id = "clientApplicationName"
$client_secret = "6FB76F91-B62D-4193-A795-FDDF405F94A2"
$grant_type = "client_credentials"
$value = Hash($client_id + ":" + $client_secret)
$auth = "Basic " + $value
$body = "grant_type=" + $grant_type
$body += "&scope=" + $scope
$resp = try { 
Invoke-RestMethod -Method Post -Uri $authPostUri -Headers @{ "Authorization" = $auth } -Body $body
} catch { $_.Exception.Response }

Which produces a HTTP POST request which looks like this:


 

POST https://identityserver/connect/token HTTP/1.1
Authorization: Basic c3lzdGVtQ29kZXN000JpcHQ6NkZCNzZGOTEtQjYyRC00MTkzLUE3OTUtRk000jQwNUY5NEEy
Content-Type: application/x-www-form-urlencoded
Host: identityserver
Content-Length: 55
Expect: 100-continue
Connection: Keep-Alive

grant_type=client_credentials&scope=someTargetApiName

Which, if successful, would return the following response from ID3:

@{access_token=dea839e9d3e09b4d4c00ba1fb479646a; expires_in=3600; token_type=Bearer}

Next up, I’ll show you how to generate the client secret and how to handle it on the client and within ID3’s database.


A lightweight implementation OWIN OAuth for ASP.NET Web Forms using Visual Studio 2013 – Part 1

Introduction

Disclaimer: this article assumes the reader is already familiar with OWIN and OAuth standards.  It is published in three parts.

Late last year I wanted to implement Open Web Interface for .Net (OWIN) OAuth  functionality for an administrative subdomain.  As it happened, I wanted to specifically integrate OWIN/OAuth authentication/authorization for an existing Dynamic Data site (using the .NET Framework v4.5 and the Entity Framework v5) but to just authenticate using just the Microsoft API for Microsoft Accounts.

Unfortunately for me, the out-of-the-box (OOTB) ASP.net identity packages use an implicit local DB which, in turn,  uses the Entity Framework v6 – which is entirely incompatible with Dynamic Data templates (v4 and v5 only).

Therefore, I was left with only one option – strip the ASP.net Identity packages out altogether and write a lightweight implementation directly against OWIN/OAuth packages – essentially replacing the  Microsoft OOTB ASP.net packages and removing the local DB implementation altogether.

I’m pleased to say I managed to achieve this, and now I’m going to write about what I had to do to get the final result.  In the end I opted to use an alternative set of OWIN packages (DotNetOpenAuth.*) instead of the OOTB (Microsoft.Owin.*) packages – this is discussed further, below.

I’ll be referring to a clean OOTB web forms project (as a baseline) throughout, but the steps should apply equally to an existing web project.  Note that I haven’t explored the MVC/Web API avenue, but there might be some useful info here for non-web forms based ASP.NET sites as well.

Note: this article was originally published at Sanders Technology – check here for updates to this and related articles.

In this Article

The content for this concept will run across a couple of parts, since there’s much to do to get set up properly.  This current article, Part 1, will focus on establishing the requirements for running the lightweight implementationPart 2 will look at how to configure your development environment and Part 3 will focus on the actual implementation (and will assume you have read parts 1 & 2).

Basic Setup

What you ideally want to do is start with a new site.  If that’s not possible or if you just want to retrofit onto an existing project, then you could just add the necessary packages (via NuGet Package Manager) and extra implementation to your existing project – after all, this is meant to be a very light implementation.

To show the packages I’m adding and removing, I’ve created a brand new out of the box site using Visual Studio 2013, and will compare the vanilla packages.config against my intended configuration.

image
The New Project wizard

An out-of-the-box ASP.net web forms project (as per the above diagram) produces a packages.config with the following definition:

<?xml version="1.0" encoding="utf-8"?> 
<packages> 
  <package id="Antlr" version="3.4.1.9004" targetFramework="net45" /> 
  <package id="AspNet.ScriptManager.bootstrap" version="3.0.0" targetFramework="net45" /> 
  <package id="AspNet.ScriptManager.jQuery" version="1.10.2" targetFramework="net45" /> 
  <package id="bootstrap" version="3.0.0" targetFramework="net45" /> 
  <package id="EntityFramework" version="6.0.0" targetFramework="net45" /> 
  <package id="jQuery" version="1.10.2" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.FriendlyUrls" version="1.0.2" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.FriendlyUrls.Core" version="1.0.2" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Identity.Core" version="1.0.0" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Identity.EntityFramework" version="1.0.0" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Identity.Owin" version="1.0.0" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Providers.Core" version="1.2" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.ScriptManager.MSAjax" version="5.0.0" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.ScriptManager.WebForms" version="5.0.0" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.1" targetFramework="net45" /> 
  <package id="Microsoft.AspNet.Web.Optimization.WebForms" version="1.1.1" targetFramework="net45" /> 
  <package id="Microsoft.Owin" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Host.SystemWeb" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.Cookies" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.Facebook" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.Google" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.MicrosoftAccount" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.OAuth" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Owin.Security.Twitter" version="2.0.0" targetFramework="net45" /> 
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" /> 
  <package id="Modernizr" version="2.6.2" targetFramework="net45" /> 
  <package id="Newtonsoft.Json" version="5.0.6" targetFramework="net45" /> 
  <package id="Owin" version="1.0" targetFramework="net45" /> 
  <package id="Respond" version="1.2.0" targetFramework="net45" /> 
  <package id="WebGrease" version="1.5.2" targetFramework="net45" /> 
</packages>

As mentioned in the introduction, you’ll notice that I’m using the “DotNetOpenAuth” packages created by Andrew Arnott which build upon the “DotNetOpenAuth extensions for ASP.NET (WebPages)” and “Microsoft WebPages OAuth library” which are built by Microsoft instead of the OOTB OWIN packages.  I was lead in that direction owing to the complicity of the OOTB packages, the DotNetOpenAuth implementation, IMHO, is much cleaner and easier to work with.

Note: I am referencing an updated version of the Entity Framework here (v6.0.2), in my earlier example site (mentioned in the introduction), I maintained the existing v5 version for compatibility with Dynamic Data templates.  The important point here is that the Entity Framework plays no part in implementing the lightweight OWIN/OAuth solution.

Below is the updated packages.config from my updated web forms website.

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.5.0.2" targetFramework="net45" />
  <package id="AspNet.ScriptManager.bootstrap" version="3.1.0" targetFramework="net45" />
  <package id="AspNet.ScriptManager.jQuery" version="2.1.0" targetFramework="net45" />
  <package id="bootstrap" version="3.1.0" targetFramework="net45" />
  <package id="DotNetOpenAuth.AspNet" version="4.3.4.13329" targetFramework="net45" />
  <package id="DotNetOpenAuth.Core" version="4.3.4.13329" targetFramework="net45" />
  <package id="DotNetOpenAuth.OAuth.Consumer" version="4.3.4.13329" targetFramework="net45" />
  <package id="DotNetOpenAuth.OAuth.Core" version="4.3.4.13329" targetFramework="net45" />
  <package id="DotNetOpenAuth.OpenId.Core" version="4.3.4.13329" targetFramework="net45" />
  <package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.3.4.13329" targetFramework="net45" />
  <package id="EntityFramework" version="6.0.2" targetFramework="net45" />
  <package id="jQuery" version="2.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.FriendlyUrls" version="1.0.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.FriendlyUrls.Core" version="1.0.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.Providers.Core" version="2.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.ScriptManager.MSAjax" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.ScriptManager.WebForms" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization.WebForms" version="1.1.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.Data" version="3.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.OAuth" version="3.1.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.WebData" version="3.1.0" targetFramework="net45" />
  <package id="Microsoft.Bcl" version="1.1.6" targetFramework="net45" />
  <package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="net45" />
  <package id="Microsoft.Net.Http" version="2.2.18" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Modernizr" version="2.7.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.1" targetFramework="net45" />
  <package id="Owin" version="1.0" targetFramework="net45" />
  <package id="Respond" version="1.3.0" targetFramework="net45" />
  <package id="WebGrease" version="1.6.0" targetFramework="net45" />
</packages>

Note: I’ve removed these packages:

  <package id=”Microsoft.AspNet.Identity.Core” version=”1.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.AspNet.Identity.EntityFramework” version=”1.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.AspNet.Identity.Owin” version=”1.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Host.SystemWeb” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Security” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Security.Facebook” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Security.Google” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Security.MicrosoftAccount” version=”2.0.0″ targetFramework=”net45″ />
  <package id=”Microsoft.Owin.Security.Twitter” version=”2.0.0″ targetFramework=”net45″ />

Remember – you also need to ensure that project references need to be removed as well, simply editing the packages.config won’t remove the old packages from your life!

image
Ensure these are removed, and that the new packages are referenced.

With the ASP.net Identity implementation removed, you’ll have to roll your own classes.  This is not as bad as it sounds.

Preparing a new ASP.net web forms project

This only applies if you’re intending on modifying a new project – skip to the next section if you want to integrate with an existing project.

To get this solution compiling (for an OOTB project), you’ll have to strip out the existing OWIN implementation, as the project won’t compile.

image

The following project artefacts would need to be deleted/removed:

  • Startup.cs
  • The entire Models folder
  • App_Start\Startup.Auth.cs
  • The entire Account folder
  • Remove “Unnamed_LoggingOut” function from Global.cs

You’ll also need to edit the Web.Config accordingly:

  • Remove “Microsoft.AspNet.Identity” from <namespaces>
  • Remove entity framework references (if not using the EF)
  • Remove the Membership, profile and roleManager elements

image

You’ll also need to edit the Site.Master to remove old Account artefacts:

<AnonymousTemplate>
    <ul class="nav navbar-nav navbar-right">
        <li><a runat="server" href="~/Account/Register">Register</a></li>
        <li><a runat="server" href="~/Account/Login">Log in</a></li>
    </ul>
</AnonymousTemplate>
<LoggedInTemplate>
    <ul class="nav navbar-nav navbar-right">
        <li><a runat="server" href="~/Account/Manage" title="Manage your account">Hello, 
<%: Context.User.Identity.GetUserName() %> !</a>
</li> <li> <asp:LoginStatus runat="server" LogoutAction="Redirect" LogoutText="Log off"
LogoutPageUrl="~/" OnLoggingOut="Unnamed_LoggingOut" /> </li> </ul>
</LoggedInTemplate>

You can just remove the parts in bold, and add your own implementation later.  You’ll also need to include the “Microsoft ASP.NET Razor” package and the “Microsoft ASP.NET Web Pages” package (if not already installed) and ensure a reference to the System.Web.WebPages.Razor assembly – as this is required by elements of the OWIN assemblies.

Once you get to this point your project should compile, but will it run?  If it doesn’t you might need to double check that you’ve removed all of the parts listed above. If everything’s been done correctly you should be able to compile and run (under IIS Express by default). If you want to save time, here’s a clean OOTB site which compiles:

Clean Solution

OWIN OAuth functionality – Prerequisites

Now I’m going to state up-front: this is a very lean implementation. The functionality stripped out from the OOTB website will not be replaced. Instead, you’ll be able to effectively “log in” to a site with an OpenId, e.g. a Microsoft account.  In other words – it’s up to you to decide what functionality to build around it.

To use OAuth, you’ll need to be familiar with the requirements of each OpenID provider you want to incorporate.

The ASP.NET examples are invariably Facebook, Twitter and Microsoft Accounts, but can be extended in theory to any OpenID provider.

I’ll be using Microsoft Accounts, since that’s what I’ve used in the past.  We’ll go into more detail about this in Part 2, which establishes the development environment and I’ll walk you through how to configure for Microsoft Accounts.  You’ll need this before going any further, or you won’t be able to test or debug.

For now though, ensure you have the following packages installed:

<package id="DotNetOpenAuth.AspNet" version="4.3.4.13329" targetFramework="net45" />
<package id="DotNetOpenAuth.Core" version="4.3.4.13329" targetFramework="net45" />
<package id="DotNetOpenAuth.OAuth.Consumer" version="4.3.4.13329" targetFramework="net45" />
<package id="DotNetOpenAuth.OAuth.Core" version="4.3.4.13329" targetFramework="net45" />
<package id="DotNetOpenAuth.OpenId.Core" version="4.3.4.13329" targetFramework="net45" />
<package id="DotNetOpenAuth.OpenId.RelyingParty" version="4.3.4.13329" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages.Data" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages.OAuth" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages.WebData" version="3.1.0" targetFramework="net45" />

..and we’ll cover off the specific implementation in Part 3.

Summary and Download

So this article really just establishes how to prime a clean web forms project, or what to do to prepare an existing web site project.  We’ve only just begun…  Part 2 will establish the environment and help you to configure the Microsoft Account provider.  Part 3 will walk through the basic implementation.

Clean Visual Studio Solution

Continue to Part 2.