owin : setting up basic authentication

Setting up basic OAuth with OWIN is very simple using username/password flow.

Install nuget

Microsoft.Owin.Security.OAuth

Once you install it, you will need to do two things

  1. First, write a class which implement authentication logic
  2. Second, integrate that class with OWIN.

Implementing provider

Lets define a class which implements `OAuthAuthorizationServerProvider`

[sourcecode language=”csharp”]

public class SimpleAuthorizationProvider : OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
await Task.Run(() => context.Validated());
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (context.Password != context.UserName)
{
context.SetError("invalid_password", "The user name or password is incorrect.");
return;
}
await Task.Run(() => context.Validated(new ClaimsIdentity(context.Options.AuthenticationType)));
}
}

[/sourcecode]

Integrate Provided

Now we need to configure OWIN to use OAUTH. so change the existing OwinConfiguration class to look like below

[sourcecode language=”csharp”]

public class OwinConfiguration
{
public void Configuration(IAppBuilder app)
{
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
Provider = new SimpleAuthorizationProvider()
});

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
Provider = new OAuthBearerAuthenticationProvider()
});
}
}

[/sourcecode]

Setting the authentication mode to active will help us in having `IPrincipal` set for web-api’s.

Testing

Owin provides its own testing framework as well. Please install nuget:

Microsoft.Owin.Testing

Once installed please add below tests and make sure that they passes.

[sourcecode language=”csharp”]

[TestFixture]
public class OwinTests
{
[Test]
public async Task Should_Authenticate_User()
{
using (var server = TestServer.Create<OwinConfiguration>())
{
var response = await server.CreateRequest("/token")
.And(x => x.Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", "admin"),
new KeyValuePair<string, string>("password", "admin"),
new KeyValuePair<string, string>("grant_type", "password")
})).PostAsync();

response.IsSuccessStatusCode.Should().BeTrue();
response.StatusCode.Should().Be(HttpStatusCode.OK);
}
}

[Test]
public async Task Should_Fail_Authentication()
{
using (var server = TestServer.Create<OwinConfiguration>())
{
var response = await server.CreateRequest("/token")
.And(x => x.Content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", "admin"),
new KeyValuePair<string, string>("password", "wrong-password"),
new KeyValuePair<string, string>("grant_type", "password")
})).PostAsync();

response.IsSuccessStatusCode.Should().BeFalse();
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
}
}

[/sourcecode]

self-hosting webapi 2 using Owin/Topshelf

OWIN is an abstraction between .NET web servers and web applications. It decouples the application from the server, making it ideal for self-hosting. OWIN can serve as host for webapi, nancy or even as ftp server.

  • Host application in your own process, independent of IIS e.g. in a windows service.
  • Easily port application between hosts and potentially entire platforms/operating systems.
  • Reduces middle ware components, works as pipeline transparently.
  • Simple workflow due to pipelines, and improved efficiency due to reduce pipeline.

OWIN is a community-owned specification, not an implementation. The Katana project is Microsoft’s implementation of OWIN.

This tutorial shows how to host ASP.NET Web API in a console application, using OWIN to self-host the Web API framework.

Step 1 : Create a project and install Nugets

Create a project of type Console Application, to host our webapi using own. 
Install nugets
> Microsoft.AspNet.WebApi.OwinSelfHost
> Topshelf
We will use topshelf to host owin inside a windows service.

Step 2: Setup Webapi

Create HelloWorldApiController.cs

[sourcecode language=”csharp”]
public class HelloWorldApiController : ApiController
{
[HttpGet]
public string Get()
{
return "Hello World";
}
}
[/sourcecode]

Also register the controller with route provider, using

[sourcecode language=”csharp”]
public class WebApiConfig
{
public static HttpConfiguration Register()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("DefaultApi",
"api/{controller}/{id}",
new { id = RouteParameter.Optional });
return config;
}
}
[/sourcecode]

Step 3: Register the web application with Owin

To register webapi with owin, create a class OwinConfiguration.cs

[sourcecode language=”csharp”]
public class OwinConfiguration
{
public void Configuration(IAppBuilder app)
{
app.UseWebApi(WebApiConfig.Register());
}
}
[/sourcecode]

Step 4: Host owin inside windows service

Topshelf hosts OWIN as console application while debugging using visual studio.

To register OWIN with topself create below class

[sourcecode language=”csharp”]
public class HostingConfiguration : ServiceControl
{
private IDisposable _webApplication;

public bool Start(HostControl hostControl)
{
Trace.WriteLine("Starting the service");
_webApplication = WebApp.Start<OwinConfiguration>("http://localhost:8089");
return true;
}

public bool Stop(HostControl hostControl)
{
_webApplication.Dispose();
return true;
}
}
[/sourcecode]

Also change the main method as below
[sourcecode language=”csharp”]
public static int Main()
{
var exitCode = HostFactory.Run(x =>
{
x.Service<HostingConfiguration>();
x.RunAsLocalSystem();
x.SetDescription("Owin + Webapi as Windows service");
x.SetDisplayName("owin.webapi.test");
x.SetServiceName("owin.webapi.test");
});
return (int)exitCode;
}
[/sourcecode]

Step 5: Test

Vist the url http://localhost:8089/api/HelloWorldApi in your favorite browser to make sure it works.

Note: To install it as windows service using topshelf, start CMD as an administrator and run command `install` & `start` on the project.exe