locked
VB.Net Lightswitch HTML (VS2013 Update 5) LDAP Integration RRS feed

  • Question

  • Hi All,

    I have an existing VB.Net Lightswitch HTML application (VS 2013 Update 5) using forms authentication for a small user group that is planned to expand. Part 1 is to integrate our companies LDAP authentication so the expanded user base doesn’t have to remember yet another unique application password.

    Note: I can’t change/create AD groups, so application permissions have to come from the application. UserID in aspnet tables matches LDAP user id.

    I have a custom LogIn.aspx created that requests then authenticates the credentials.

    This issue I am seeing is on deployment the login page authenticates then redirects to the Lightswitch Applicaton which then prompts for the application forms authentication id/pass.

    I need the LDAP authentication/cookie to validate and then get the user id’s role from the aspnet tables and use that information for the application.

    Code (sensitive information replaced with generic): 

    Login aspx:

    <%@ Page language="vb" AutoEventWireup="true" %>
    <%@ Import Namespace="LightSwitchApplication" %>
    <html>
    	<body>
    		<form id="LogIn" method="post" runat="server">
    			<asp:Label ID="Label2" Runat="server">Username:</asp:Label>
    			<asp:TextBox ID="txtUsername" Runat="server"></asp:TextBox><br>
    			<asp:Label ID="Label3" Runat="server">Password:</asp:Label>
    			<asp:TextBox ID="txtPassword" Runat="server" TextMode="Password"></asp:TextBox><br>
    			<asp:Button ID="btnLogin" Runat="server" Text="Login" OnClick="Login_Click"></asp:Button><br>
    			<asp:Label ID="errorLabel" Runat="server" ForeColor="#ff3300"></asp:Label><br>
    		</form>
    	</body>
    </html>
    
    <script runat="server">
        Sub Login_Click(sender As Object, e As EventArgs)
                    
            Dim adPath As String = "LDAP://ldapaddresspath" 'Path to your LDAP directory server
            Dim adAuth As LdapAuthentication = New LdapAuthentication(adPath)
            Try
                If (True = adAuth.IsAuthenticated(txtUsername.Text, txtPassword.Text)) Then
                    Response.Cookies.Add(adAuth.GetCookie(txtUsername.Text))
                    Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, True))
    
                Else
                    errorLabel.Text = "Authentication did not succeed. Check user name and password."
                End If
    
            Catch ex As Exception
                errorLabel.Text = "Error authenticating. " & ex.Message
            End Try
        End Sub
    </script>
    

    Partial Webconfig:

    <connectionStrings>
        <add name="_IntrinsicData" connectionString="Data Source=|SqlExpressInstanceName|;AttachDbFilename=|ApplicationDatabasePath|;Integrated Security=True;Connect Timeout=30;MultipleActiveResultSets=True" />
        <add name="53683baa-4d1c-4d7e-a03c-b1d91fc47df8" connectionString="Data Source=sourcedbase;Initial Catalog=applicationname;Persist Security Info=True;User ID=dbaseuser;Password=dbasepass" />
      </connectionStrings>
      <system.web>
        <!-- LightSwitch trace.axd handler -->
        <trace enabled="true" localOnly="false" requestLimit="40" writeToDiagnosticsTrace="false" traceMode="SortByTime" mostRecent="true" />
        <httpHandlers>
          <add verb="GET" path="trace.axd" type="Microsoft.LightSwitch.WebHost.Implementation.TraceHandler,Microsoft.LightSwitch.Server,Version=12.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
          <add verb="*" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
        </httpHandlers>
        <httpModules>
          <add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
          <add name="LightSwitchModule" type="Microsoft.LightSwitch.WebHost.Implementation.LightSwitchHttpModule,Microsoft.LightSwitch.Server,Version=12.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </httpModules>
        <compilation debug="false" targetFramework="4.5">
          <assemblies>
            <add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
            <add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
            <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            <add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
            <add assembly="Microsoft.LightSwitch.Server, Version=12.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845DCD8080CC91" />
            <add assembly="Microsoft.ReportViewer.Common, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845DCD8080CC91" />
          </assemblies>
        </compilation>
        <authentication mode="Forms">
          <forms loginUrl="LogIn.aspx" name="applicationname" timeout="60" path ="/" />
        </authentication>
        <authorization>
          <deny users="?"/>
          <allow users="*"/>
        </authorization>
        <identity impersonate="true"/>
        <pages validateRequest="false">
          <controls>
            <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
            <add assembly="Microsoft.ReportViewer.WebForms, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" namespace="Microsoft.Reporting.WebForms" tagPrefix="rsweb" />
          </controls>
        </pages>
        <!-- Setting maxRequestLength to be much greater than default 4096 so that large data may be uploaded e.g. images, docs -->
        <httpRuntime requestPathInvalidCharacters="" requestValidationMode="2.0" maxRequestLength="102400" targetFramework="4.5" />
        <membership defaultProvider="AspNetMembershipProvider">
          <providers>
            <clear />
            <add name="AspNetMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="_IntrinsicData" applicationName="applicationname" requiresUniqueEmail="false" requiresQuestionAndAnswer="false" />
          </providers>
        </membership>
        <roleManager enabled="True" defaultProvider="AspNetRoleProvider">
          <providers>
            <clear />
            <add name="AspNetRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="_IntrinsicData" applicationName="applicationname" />
          </providers>
        </roleManager>
        <profile enabled="True" defaultProvider="AspNetProfileProvider">
          <providers>
            <clear />
            <add name="AspNetProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="_IntrinsicData" applicationName="applicationname" />
          </providers>
          <properties>
            <add name="FullName" />
          </properties>
        </profile>
      </system.web>
    

    Ldapauthentication class:

    Imports System
    Imports System.Text
    Imports System.Collections
    Imports System.DirectoryServices
    Imports System.Web.Security
    
    Namespace LightSwitchApplication
        Public Class LdapAuthentication
    
            Dim _path As String
            Dim _filterAttribute As String
    
            Public Sub New(ByVal path As String)
                _path = path
            End Sub
    
            Public Function IsAuthenticated(ByVal username As String, ByVal pwd As String) As Boolean
    
                Dim domainAndUsername As String = "domainname\" & username
                Dim entry As DirectoryEntry = New DirectoryEntry(_path, domainAndUsername, pwd)
    
                Try
                    'Bind to the native AdsObject to force authentication.			
                    Dim obj As Object = entry.NativeObject
                    Dim search As DirectorySearcher = New DirectorySearcher(entry)
    
                    search.Filter = "(SAMAccountName=" & username & ")"
                    search.PropertiesToLoad.Add("cn")
                    Dim result As SearchResult = search.FindOne()
    
                    If (result Is Nothing) Then
                        Return False
                    End If
    
                    'Update the new path to the user in the directory.
                    _path = result.Path
                    _filterAttribute = CType(result.Properties("cn")(0), String)
    
                Catch ex As Exception
                    Throw New Exception("Error authenticating user. " & ex.Message)
                End Try
    
                Return True
            End Function
    
            Public Function GetCookie(ByVal uid As String) As HttpCookie
    
                Dim authTicket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, uid, DateTime.Now, DateTime.Now.AddMinutes(60), False, "User")
    
                'Encrypt the ticket.
                Dim encryptedTicket As String = FormsAuthentication.Encrypt(authTicket)
    
                'Create a cookie, and then add the encrypted ticket to the cookie as data.
                Dim newCookie As HttpCookie = New HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
    
                newCookie.Expires = authTicket.Expiration
    
                Return newCookie
            End Function
    
        End Class
    End Namespace
    

    Global.asax:

    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
            ' Fires upon attempting to authenticate the use
            Dim cookieName As String = FormsAuthentication.FormsCookieName
            Dim authCookie As HttpCookie = Context.Request.Cookies(cookieName)
    
            If (authCookie Is Nothing) Then
                'There is no authentication cookie.
                Return
            End If
    
            Dim authTicket As FormsAuthenticationTicket = Nothing
    
            Try
                authTicket = FormsAuthentication.Decrypt(authCookie.Value)
            Catch ex As Exception
                'Write the exception to the Event Log.
                Return
            End Try
    
            If (authTicket Is Nothing) Then
                'Cookie failed to decrypt.
                Return
            End If
    
            Dim groups(0) As String
    
            groups(0) = "User"
    
            'Create an Identity.
            Dim id As GenericIdentity = New GenericIdentity(authTicket.Name, "LdapAuthentication")
    
            'This principal flows throughout the request.
            Dim principal As GenericPrincipal = New GenericPrincipal(id, groups)
    
            HttpContext.Current.User = principal
    End Sub
    

    Monday, October 26, 2015 4:57 PM