Identifying Logon Failures on a Web Site

Several years ago, while working on the "Frontier" project at Agilent Technologies, I encountered a scenario where I needed to quickly identify logon failures on the site. The Agilent site was (and I believe still is) based on Microsoft Office SharePoint Server (MOSS) 2007, and used Forms-Based Authentication with a slightly custom version of the ActiveDirectoryMembershipProvider (in order to lookup users by email address, instead of forcing customers and partners to remember their usernames in the Agilent extranet domain).

Whenever a user failed to authenticate, I noticed that ASP.NET wrote a message to the Application event log on the Web server (Event ID: 1315) in which the Description contained the phrase:

Membership credential verification failed.

In order to help the Operations team diagnose these logon failures, I created a couple of scripts that simply query the event log based on the Event ID and Description.

The first script lists all logon failures for a particular server (i.e. one of the Web servers in the farm), while the second script looks for logon failures for a particular user (across all Web servers in the farm, which -- at least back then -- happened to be two servers: WCOSLSC0 and WCOSLSC9).

These scripts are based on a sample I found in the Script Center on TechNet for querying the event log. You should be able to easily modify them to search for other events (and subsequently parse data from).

Note

While I originally created these scripts for a solution based on MOSS 2007, you should be able to use them for any site based on ASP.NET. For example, this morning I verified the scripts still work as expected with my Fabrikam Demo site based on SharePoint Server 2010 and configured with claims-based authentication.

Important

You should obviously apply discretion when deciding when (and how often) to run these scripts against a Production envionment. With a little bit of effort, however, you could modify the scripts to work against saved event logs copied to another environment for analysis.

ListLogonFailureEventsForServer.vbs

This script searches the specified server's Application event log for ASP.NET logon failure events and subsequently parses the username from any events that are found:

 Option Explicit

If (WScript.Arguments.Count <> 1) Then
    WScript.Echo("Usage: ListLogonFailureEventsForServer.vbs {server}")    
    WScript.Quit(1)
End If

Dim strServer
strServer = WScript.Arguments(0)

WScript.Echo("Logon failure events for server: " & strServer)

Call ListLogonFailureEventsForServer(strServer)

Sub ListLogonFailureEventsForServer(ByVal strServer)

    Dim objWMIService
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strServer & "\root\cimv2")

    Dim colEvents
    Set colEvents = objWMIService.ExecQuery _
        ("Select * from Win32_NTLogEvent" _
        & " Where" _
            & " Logfile = 'Application'" _
            & " and EventCode = '1315'" _
            & " and Message LIKE '%Membership credential verification failed%'")

    WScript.Echo("Number of logon failure events (" & strServer & "): " _
        & colEvents.Count)

    Dim objEvent
    For Each objEvent In colEvents
        Dim index1
        index1 = InStr(objEvent.Message, "Name to authenticate: ")

        Dim strUser

        If (index1 < 0) Then
            strUser = "(Unknown)"
        Else
            index1 = index1 + Len("Name to authenticate: ")

            Dim index2
            index2 = InStr(index1, objEvent.Message, vbCr)

            strUser = Mid(objEvent.Message, index1, index2 - index1)
        End If

        WScript.Echo(objEvent.TimeGenerated & "    " & strUser)
    Next

    WScript.Echo()
End Sub

ListLogonFailureEventsForUser.vbs

This script searches the Application event logs for each server in the farm looking for ASP.NET logon failure events for the specified username:

 Option Explicit

If (WScript.Arguments.Count <> 1) Then
    WScript.Echo("Usage: ListLogonFailureEventsForUser.vbs {username}")    
    WScript.Quit(1)
End If

Dim strUser
strUser = WScript.Arguments(0)

WScript.Echo("Logon failure events for user: " & strUser)

Call ListLogonFailureEventsForUser(strUser, "WCOSLSC0")
Call ListLogonFailureEventsForUser(strUser, "WCOSLSC9")

Sub ListLogonFailureEventsForUser(ByVal strUser, ByVal strServer)

    Dim objWMIService
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strServer & "\root\cimv2")

    Dim colEvents
    Set colEvents = objWMIService.ExecQuery _
        ("Select * from Win32_NTLogEvent" _
        & " Where" _
            & " Logfile = 'Application'" _
            & " and EventCode = '1315'" _
            & " and Message LIKE '%Membership credential verification failed%" _
                & "Name to authenticate: " & strUser & "%'")

    WScript.Echo("Number of logon failure events (" & strServer & "): " _
        & colEvents.Count)

    Dim objEvent
    For Each objEvent In colEvents
        WScript.Echo(objEvent.TimeGenerated)
    Next

    WScript.Echo()
End Sub