Authenticate Desktop Application with ASP .NET Identity Database

This is one of those rare scenarios which are only applicable to a niche audience. We had a legacy application in VB .NET which with change of requirements was now required to be authenticated with the same credentials as the web application end users were utilizing.

It might not make sense in a day to day operation but it made sense to the business owners and we had to implement it. The website was relatively new and used ASP .NET Identity to authenticate users.

To Authenticate users in the desktop application, we reverse engineered the ASP .NET Authentication and replicated it in our own class to match the password stored in it. We used Entity Framework to connect to the Identity database and used the below code to verify passwords.  You can download the complete code at the end of the post.

Public Shared Function VerifyHashedPassword(ByVal hashedPassword As String, ByVal password As String) As Boolean
	Dim bytes As Byte()
	If (hashedPassword Is Nothing) Then
		Return False
	End If
	If (password Is Nothing) Then
		Throw New ArgumentNullException("password")
	End If
	Dim numArray As Byte() = Convert.FromBase64String(hashedPassword)
	If (CInt(numArray.Length) <> 49 OrElse numArray(0) <> 0) Then
		Return False
	End If
	Dim numArray1(15) As Byte
	Buffer.BlockCopy(numArray, 1, numArray1, 0, 16)
	Dim numArray2(31) As Byte
	Buffer.BlockCopy(numArray, 17, numArray2, 0, 32)
	Using rfc2898DeriveByte As Rfc2898DeriveBytes = New Rfc2898DeriveBytes(password, numArray1, 1000)
		bytes = rfc2898DeriveByte.GetBytes(32)
	End Using
	Return Crypto.ByteArraysEqual(numArray2, bytes)
End Function

We used the below code to authenticate the user from the Windows Form:

Private Function ValidateUser(uName As String, pwd As String) As String
	Dim result As String = String.Empty
	Using db As New IdentitydevMEntities
		Dim user = (From u In db.AspNetUsers Where u.UserName.Equals(uName, StringComparison.InvariantCultureIgnoreCase) 
		Select u).FirstOrDefault()

		If Not (user Is Nothing) Then
			If (Crypto.VerifyHashedPassword(user.PasswordHash, pwd)) Then
				result = user.Id
			End If
		End If

	End Using

	Return result
End Function

NOTE: We used secure SQL Connection to connect to our databases in cloud.

You can download the code here: AuthCode

Set Development Databases to Simple Recovery

If you develop SharePoint Solutions and have SharePoint installed in your development environment then this script will come in real handy to you.

This script uses a cursor and sets all non system databases to simple recovery. This will help you in terms of performance as it reduces the number of disk writes by SQL along with that you will not face the problem of SQL logs filling your hard drive.

USE MASTER
declare
@cmd varchar(2000),
@dbname varchar(64),
@logfile varchar(128)

declare c1 cursor for 
	SELECT  d.name, mf.name as logfile
	FROM sys.master_files mf
		inner join sys.databases d
		on mf.database_id = d.database_id
	where recovery_model_desc <> 'SIMPLE'
		and d.name not in ('master','model','msdb','tempdb') 
		and mf.type_desc = 'LOG'	
		
open c1
	fetch next from c1 into @dbname, @logfile
		While @@fetch_status <> -1
		begin
			select @cmd = 'ALTER DATABASE [' + @dbname + '] SET RECOVERY SIMPLE'
			exec(@cmd)
			select @cmd='USE [' + @dbname + '] checkpoint'
			exec(@cmd)
			select @cmd='USE [' + @dbname + '] DBCC SHRINKFILE ([' + @logfile + '], 1)'
			exec(@cmd)
			fetch next from c1 into @dbname, @logfile
		end
close c1
deallocate c1

You can also download the script here: SETDBSIMPLE