Using OWIN Security with MultiValue Data - Part 1

OWIN is the latest framework that .NET developers are using to build ASP.NET applications. OWIN's Identity framework is an evolution of the ASP.NET 2.0 membership system which has been around for several years. It provides better flexibility than the older system, and decouples the Identity framework from IIS.

The intent of OWIN is to create a security framework that can work with ASP.NET applications, even if they aren't running on IIS. This is good news for people developing in Mono for Linux or those creating self-hosting applications.

At its core, OWIN is a middleware model to handle the separation of ASP.NET applications from the actual hosting environment. I will focus mainly on the security and membership side of things but it does much more.

If you are using ASP.NET MVC 6 for your web framework, you will have seen that OWIN is referenced automatically. By default, MVC will assume you are using the traditional ASP.NET identity model, but OWIN's identity model can be extended easily to include access to other identity systems.

When starting a new project, you will see something like the code in Figure 1 the Startup.Auth class. This code is boilerplate, and shows you some of what you can do with the OWIN security. A couple things to point out, the Startup.auth class already includes the built-in providers to handle all the common Social Media logins like Microsoft, Twitter, Facebook and Google. When creating customer-based websites, this is a really nice feature. It also has the code in place to handle Two-Factor logins, so you don't need to build this yourself any more.

Public Sub ConfigureAuth(app As IAppBuilder)
' Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)
app.CreatePerOwinContext(Of ApplicationSignInManager)(AddressOf ApplicationSignInManager.Create)
' Enable the application to use a cookie to store information for the signed in user
' and to use a cookie to temporarily store inforation about a user logging in with a third party login provider
' Configure the sign in cookie
' OnValidateIdentity enables the application to validate the security stamp when the user logs in.
' This is a security feature which is used when you change a password or add an external login to your account.
Dim _AuthenticationOption As New CookieAuthenticationOptions()
_AuthenticationOption.LoginPath = New PathString("/Account/Login")
_AuthenticationOption.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
_AuthenticationOption.Provider = New CookieAuthenticationProvider
' Place an expiration on the Login
'_AuthenticationOption.Provider.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUserStore)(TimeSpan.FromMinutes(30), Function(manager, user)
' user.GenerateUserIdentityAsync(manager)
' End Function)
app.UseCookieAuthentication(_AuthenticationOption)
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie)
' Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5))
' Enables the application to remember the second login verification factor such as phone or email.
' Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
' This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie)
' Uncomment the following lines to enable logging in with third party login providers
'app.UseMicrosoftAccountAuthentication(
' clientId:="",
' clientSecret:="")
'app.UseTwitterAuthentication(
' consumerKey:="",
' consumerSecret:="")
'app.UseFacebookAuthentication(
' appId:="",
' appSecret:="")
'app.UseGoogleAuthentication(New GoogleOAuth2AuthenticationOptions() With {
' .ClientId = "",
' .ClientSecret = ""})
End Sub

Figure 1

Another important thing to note is there are references to ApplicationDbContext, ApplicationUserManager, and ApplicationSignInManager in the Startup.Auth class. These classes are instrumental in making the identity system work. Let's look further into these pieces.

ApplicationDbContext

We'll start with the ApplicationDbContext. All this class does is handle the connections to the database and make the stored-procedure (BASIC subroutine) calls. Each of the MultiValue databases have different ways to do this, so the code you will see in <
Figure 2
> is very generic.

End Try
' Cleanup the connection
_Connection.Disconnect()
_Connection = Nothing
' Updates the Call Results
_Results.CallError.Text = _ErrorItem
_Results.RequestItem.Text = RequestItem
_Results.Data.Text = UserItem
Return _Results
End Function
''' <summary>
''' Name of the server we are connecting to.
''' </summary>
Public Property ConnectionName As String
#Region "IDisposable Support"
Private disposedValue As Boolean ' To detect redundant calls
Protected Sub CheckIfDisposed()
If disposedValue Then
Throw New ObjectDisposedException("SpectrumDBContext")
End If
End Sub
' IDisposable
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' dispose managed state (managed objects).
End If
' free unmanaged resources (unmanaged objects) and override Finalize() below.
' set large fields to null.
End If
disposedValue = True
End Sub
' This code added by Visual Basic to correctly implement the disposable pattern.
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above.
Dispose(True)
End Sub
#End Region
End Class

Figure 2

This will be the hardest part of any of the coding you will see in these examples, mainly because you have to know how to establish a connection to your MultiValue database with the .NET API offered by your database provider. If you need more examples, you can find them at
http://www.intl-spectrum.com/resource/category/44/NET.aspx.

Another issue you may run into is the fact that OWIN is based on the .NET ASYNC/WAIT/Tasks model. This can affect how you code the connection to your MultiValue Database, since many of the APIs don't natively support Async/Wait methods.

The good news is that it is really not very hard to wrap synchronous methods and functions into Task-based processes. If you have not gotten involved with Async/Wait coding yet, now is the time to start looking at it. To see an example of creating an Async/Wait-aware function from a synchronous call, take a look at CallSubroutineAsync.

The main purpose of the code in
Figure 2
is to call a subroutine with the following arguments in Figure 3.

I will get into this subroutine in a moment. For now, assume the following:

Information about the application calling this subroutine will be provided in APPLICATION.ITEM.

Request for the database and subroutine to process will be passed in using REQUEST.ITEM.

Information will be returned from the subroutine through DATA.ITEM

Any glaring errors should be returned in ERROR.ITEM

The NONE1 and NONE2 arguments are there for future reference if needed.

I would highly recommend that you always use a single subroutine as the only point of contact whenever you are working with your MultiValue data from outside of the Database. This allows you to keep your business logic where it belongs. It also gives you a choke point for turning off all functions during maintenance. And it offers a single point for audit and security.

ApplicationUser

Before you can create the ApplicationUserManager and ApplicationSignInManager, you will need to create the ApplicationUser class. This class is used to hold information about the user for the rest of the OWIN Identity system to use. It will also contain the main methods to use in order to interact with the database.

This class requires you to implement the IUser(Of String) interface [Figure 4]. The interfaces will require you to implement an Id and UserName property. There are several other properties and methods I would recommend creating in this class as well [Figure 5]:

Imports System.ComponentModel.DataAnnotations
Imports System.Security.Claims
Imports System.Threading.Tasks
Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.Owin
Imports mvOpenAPI.api
Public Class SpectrumUser
Implements IUser(Of String)
Dim _Id As String = String.Empty
Dim _UserItem As New mvDynamicArray
Public ReadOnly Property Id As String Implements IUser(Of String).Id
Get
Return _Id
End Get
End Property
Public Property UserName As String Implements IUser(Of String).UserName
Get
Return _UserItem.StringValue(1)
End Get
Set(value As String)
_UserItem.StringValue(1) = value
End Set
End Property
...
End Class
Public ReadOnly Property DBContext As SpectrumDBContext
Get
If _DBContext Is Nothing Then
Try
_DBContext = HttpContext.Current.GetOwinContext.Get(Of SpectrumDBContext)
Catch ex As Exception
End Try
If _DBContext Is Nothing Then
_DBContext = SpectrumDBContext.Create
End If
End If
Return _DBContext
End Get
End Property
Private _DBContext As SpectrumDBContext

wSaveAsync - Which will also call the subroutine to handle saving any changes made to the ApplicationUser class.

You will notice in the Figure 5 that the LoadAsync creates a variable REQUEST.ITEM (the actual variable name is _RequestItem) and in REQUEST.ITEM<1> it has a value of "READ.USER" and in REQUEST.ITEM<2> it has the Id of the user we need information for.

One of the nice things about OWIN is that you can assign an arbitrary Id (primary key, record Id) to the user instead of having to translate the UserName every time like you used to have to do in ASP.NET 2.0 membership framework. For obvious reason, this makes pulling information from the database much easier.

SPECTRUM.OWIN.USER Subroutine

Let's take a quick look at the subroutine that we are calling. The first thing we need to do is to decide which request it needs to process [Figure 6]. You will notice that the code actually has three request types, or events, that we want it respond to:

The READ.USER event is to read the OWIN user information from the database, and return it back to the ApplicationUser Class. I have not gone into the full structure of the DATA.ITEM dynamic array yet.

The WRITE.USER event is to take the information from the ApplicationClass and place it back into the database.

The last event is the FIND.USER. This event will be used to find the record to use when someone first logs in.

The DATA.ITEM will have around 20 attributes that will be used by the ApplicationUser class. As you look at the dynamic array definition I just provided, you will see there are references to two-factor authentication, claims, roles, and external providers. I will talk more about these pieces of data in later articles.

This may seem like a lot of work, but it is really just building a set of code that can be used over and over again. This first article covered much of the hard part, but there are a few more pieces that you will need to make everything connect together.

I will continue showing those other components and how it all connects together in upcoming articles in the series.