static void

Owin

Owin is an abstraction layer for web hosting, with Katana being Microsoft's Owin wrapper for IIS/System.Web. You can also self-host with Owin (for webApi - MVC 5 still depends on system.web, but can use Owin middleware).

Owin was introduced with Visual Studio 2013/MVC 5/webApi 2/.net 4.5.1 (Oct 2013). WebApi 2 can entirely use Owin, but MVC5 just uses Owin middleware for authentication. .net Core depends entirely on an Owin-compatible stack (System.Web is no longer used)

Unlike System.Web, Owin is modular by design (and constructed from nuget packages). There are no interfaces or base classes- Startup.Configuration and Middleware.Invoke are by convention and are discovered by reflection.

ASP.Net 4.5/MVC5: Install-package Microsoft.Owin.Host.SystemWeb
The error if you forget is that HttpContext has no extension GetOwinContext().

Startup

Startup replaces global.asax ...
but you can have both (necessary for WebApi/MVC as MVC5 can't use OWIN)- Application_Start() runs first, then Startup.Configur[e|ation]().

In ASP.Net 4.5 it uses method Configuration(IAppBuilder app)
In ASP.Net 5.0 it uses method Configure(IApplicationBuilder app)

public class Startup
{
    //using Owin
    public void Configuration(IAppBuilder app)
    {
 
        //use the "appFunc" - Func<IDictionary<string, object>, Task>
        //the dictionary is the loosely typed HttpContext
        app.Use(async (dictionary, nextTask) =>
        {
            Console.WriteLine("Requesting " + dictionary.Request.Path);
 
            //next in pipeline
            await nextTask();
        });
        //include webapi- must configure routes
        var config = new HttpConfiguration();
        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}",
            new { Id = RouteParameter.Optional });
        app.UseWebApi(config);
 
        //Microsoft turns the "own.ResponseBody" stream into a typed Response.
        app.Run(ctx => ctx.Response.WriteAsync("<p>Hello world</p>"));
    }
}

For app.UseWebApi(config) you need Install-Package Microsoft.AspNet.WebApi.Owin

Forms Authentication

See OWIN authentication - more

ASP.Net 4.5/MVC 5: Install-package:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login")
        });
    }
}

AccountController

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel loginModel)
{
    if (ModelState.IsValid && Validate(loginModel))
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, loginModel.Username),
            //NameIdentifier + IdentityProvider needed for anti-forgery
            //or set AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
            new Claim(ClaimTypes.NameIdentifier, loginModel.Username),
            new Claim(
                "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
                "Custom"),
        };
        var identity = new ClaimsIdentity(claims,
            DefaultAuthenticationTypes.ApplicationCookie);
 
        var authMgr = HttpContext.GetOwinContext().Authentication;
        authMgr.SignIn(identity);
 
        return RedirectToAction("Index", "Home");
    }
    return View(loginModel);
}
 
 
public ActionResult LogOff()
{
    var authMgr = HttpContext.GetOwinContext().Authentication;
    authMgr.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
    return RedirectToAction("Login");
}

Self hosting (ASP.Net 4.5)

class Program
{
    static void Main(string[] args)
    {
        using (Microsoft.Owin.Hosting.WebApp.Start<Startup>("http://localhost:8080"))
        {
            Console.WriteLine("Self hosting");
            Console.ReadLine();
        }
    }
}

To make the console hosted in IIS:

Middleware

Middleware are pipeline components (like ASP's HttpModule), and chain themselves like decorators. You add them in Startup.Configuration with app.Use(lambda) or app.Use<MyMiddleware>(), or the equivalent extension method.

Example middleware: authentication, webapi, Microsoft.Owin.Diagnostics

All the state (equal to HttpContext) is in the IDictionary<string, object>

Standard keynames include:

Katana 3 gives a typed IOwinContext with Request/ Response properties.
ASP.Net 5.0/MVC 6 has HttpContext (which isn't System.Web.HttpContext, but is based on IFeatureCollection)

public class MyMiddleware
{
    private readonly Func<IDictionary<string, object>, Task> _next;
    public MyMiddleware(Func<IDictionary<string, object>, Task> next)
    {
        _next = next;
    }
 
    public async Task Invoke(IDictionary<string, object> environment)
    {
        //access the raw owin dictionary
        Console.WriteLine("Requesting " + environment["owin.RequestPath"]);
 
        //a katana content is easier
        var context = new OwinContext(environment);
 
        // authenticate
        context.Request.User =
            new GenericPrincipal(new GenericIdentity("Me"), null);
 
        await _next(environment);
    }
}

Authentication Middleware

There are built-in AuthenticationMiddleware classes.

public class CustomAuthenticationOptions : AuthenticationOptions
{
    //ctor takes AuthenticationType
    public CustomAuthenticationOptions()
        : base("Custom")
    {
    }
    //public string ExtraProperty { get; set; }
}
 
//per-request handler, using Microsoft.Owin.Security.Infrastructure.
public class CustomAuthentication :
    AuthenticationHandler<CustomAuthenticationOptions>
{
    protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
    {
        var authHeader = Request.Headers.Get("Authorization");
        if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Custom ", StringComparison.OrdinalIgnoreCase))
        {
            return null;
        }
        var keyToken = authHeader.Substring("Custom ".Length).Trim();
        //if this was Basic, you would Convert.FromBase64String, split username:password and validate
        if (!string.Equals(keyToken, "Secret", StringComparison.OrdinalIgnoreCase))
        {
            return null;
        }
        var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, keyToken),
                new Claim(ClaimTypes.NameIdentifier, keyToken),
                new Claim(
                    "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
                    "Custom"),
            };
        var identity = new ClaimsIdentity(claims, "Custom");
 
 
        var ticket = new AuthenticationTicket(identity, new AuthenticationProperties());
        return Task.FromResult(ticket);
    }
}
 
public class CustomAuthenticationMiddleware :
    AuthenticationMiddleware<CustomAuthenticationOptions>
{
    public CustomAuthenticationMiddleware(OwinMiddleware next, CustomAuthenticationOptions options)
        : base(next, options)
    {
    }
 
    protected override AuthenticationHandler<CustomAuthenticationOptions> CreateHandler()
    {
        return new CustomAuthentication();
    }
}

WebAPI

Changes from v1 to v2/owin

Basic authentication

Windows authentication

For self-hosting look at the underlying HttpListener to enable Windows authentication (asp.net).

public static IAppBuilder UseWindowsAuthentication(this IAppBuilder app)
{
    object value;
    if (app.Properties.TryGetValue("System.Net.HttpListener", out value))
    {
        var l = value as HttpListener;
        if (l != null)
        {
            l.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
        }
    }
    return app;
}