Need help with implementing Forms Authentication

Posted on 2005-04-19
Last Modified: 2010-05-18
I used the following tutorial for Forms Authentication.

I did what the tutorial said and am able to register and login with my WebApp and my Classes database.

Now I don't know what to do.  After I login I need to be taken to my Main.aspx page.  Also, I need to make sure that people can't just directly go to one of my pages without logging in.  How do I accomplish this?

Here is my web.config file.

<authentication mode="Forms">
            <forms loginUrl="logon.aspx" name="sqlAuthCookie" timeout="60" path="/">

            <deny users="?" />
            <allow users="*" />

Here is what I have in my Logon.aspx code behind.

Imports System.Web.Security
Imports System.Security.Cryptography
Imports System.Data.SqlClient
Public Class Login
    Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

    End Sub
    Protected WithEvents Label1 As System.Web.UI.WebControls.Label
    Protected WithEvents Label2 As System.Web.UI.WebControls.Label
    Protected WithEvents txtUserName As System.Web.UI.WebControls.TextBox
    Protected WithEvents txtPassword As System.Web.UI.WebControls.TextBox
    Protected WithEvents btnLogin As System.Web.UI.WebControls.Button
    Protected WithEvents lblMessage As System.Web.UI.WebControls.Label
    Protected WithEvents btnRegister As System.Web.UI.WebControls.Button

    'NOTE: The following placeholder declaration is required by the Web Form Designer.
    'Do not delete or move it.
    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Put user code to initialize the page here
    End Sub
    Private Shared Function CreateSalt(ByVal size As Integer) As String
        ' Generate a cryptographic random number using the cryptographic
        ' service provider
        Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider
        Dim buff() As Byte = New Byte((size) - 1) {}
        ' Return a Base64 string representation of the random number
        Return Convert.ToBase64String(buff)
    End Function
    Private Shared Function CreatePasswordHash(ByVal pwd As String, ByVal salt As String) As String
        Dim saltAndPwd As String = String.Concat(pwd, salt)
        Dim hashedPwd As String = FormsAuthentication.HashPasswordForStoringInConfigFile(saltAndPwd, "SHA1")
        Return hashedPwd
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)

    End Sub

    Private Sub btnRegister_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRegister.Click
        Dim salt As String = CreateSalt(5)
        Dim passwordHash As String = CreatePasswordHash(txtPassword.Text, salt)
            StoreAccountDetails(txtUserName.Text, passwordHash, salt)
        Catch ex As Exception
            lblMessage.Text = ex.Message
        End Try
    End Sub

    Private Sub StoreAccountDetails(ByVal userName As String, ByVal passwordHash As String, ByVal salt As String)
        ' See "How To Use DPAPI (Machine Store) from ASP.NET" for information
        ' about securely storing connection strings.
        Dim conn As SqlConnection = New SqlConnection(("Server=DELL;" + ("Integrated Security=SSPI;" + "database=Classes")))
        Dim cmd As SqlCommand = New SqlCommand("RegisterUser", conn)
        cmd.CommandType = CommandType.StoredProcedure
        Dim sqlParam As SqlParameter = Nothing
        sqlParam = cmd.Parameters.Add("@userName", SqlDbType.VarChar, 255)
        sqlParam.Value = userName
        sqlParam = cmd.Parameters.Add("@passwordHash ", SqlDbType.VarChar, 40)
        sqlParam.Value = passwordHash
        sqlParam = cmd.Parameters.Add("@salt", SqlDbType.VarChar, 10)
        sqlParam.Value = salt
        Catch ex As Exception
            ' Code to check for primary key violation (duplicate account name)
            ' or other database errors omitted for clarity
            Throw New Exception(("Exception adding account. " + ex.Message))
        End Try
    End Sub

    Private Function VerifyPassword(ByVal suppliedUserName As String, ByVal suppliedPassword As String) As Boolean
        Dim passwordMatch As Boolean = False
        ' Get the salt and pwd from the database based on the user name.
        ' See "How To: Use DPAPI (Machine Store) from ASP.NET," "How To: Use DPAPI
        ' (User Store) from Enterprise Services," and "How To: Create a DPAPI
        ' Library" for more information about how to use DPAPI to securely store
        ' connection strings.
        Dim conn As SqlConnection = New SqlConnection(("Server=DELL;" + ("Integrated Security=SSPI;" + "database=Classes")))
        Dim cmd As SqlCommand = New SqlCommand("LookupUser", conn)
        cmd.CommandType = CommandType.StoredProcedure
        Dim sqlParam As SqlParameter = cmd.Parameters.Add("@userName", SqlDbType.VarChar, 255)
        sqlParam.Value = suppliedUserName
            Dim reader As SqlDataReader = cmd.ExecuteReader
            ' Advance to the one and only row
            ' Return output parameters from returned data stream
            Dim dbPasswordHash As String = reader.GetString(0)
            Dim salt As String = reader.GetString(1)
            ' Now take the salt and the password entered by the user
            ' and concatenate them together.
            Dim passwordAndSalt As String = String.Concat(suppliedPassword, salt)
            ' Now hash them
            Dim hashedPasswordAndSalt As String = FormsAuthentication.HashPasswordForStoringInConfigFile(passwordAndSalt, "SHA1")
            ' Now verify them.
            passwordMatch = hashedPasswordAndSalt.Equals(dbPasswordHash)
        Catch ex As Exception
            Throw New Exception(("Execption verifying password. " + ex.Message))
        End Try
        Return passwordMatch
    End Function

    Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click
        Dim passwordVerified As Boolean = False
            passwordVerified = VerifyPassword(txtUserName.Text, txtPassword.Text)
        Catch ex As Exception
            lblMessage.Text = ex.Message
        End Try
        If (passwordVerified = True) Then
            ' The user is authenticated
            ' At this point, an authentication ticket is normally created
            ' This can subsequently be used to generate a GenericPrincipal
            ' object for .NET authorization purposes
            ' For details, see "How To: Use Forms authentication with GenericPrincipal
            ' objects
            lblMessage.Text = "Logon successful: User is authenticated"
            lblMessage.Text = "Invalid username or password"
        End If
    End Sub
End Class
Question by:jettman26
    LVL 20

    Accepted Solution

    Your code needs to return some roles that the user belongs to, create authentication ticket and store it in HttpResponse cookie collection. Then you're also need to check the authentication cookie on every request. Just like described in this article:

    Author Comment

    I read thru the article.   I don't want to use the roles based part of it.  I have no roles.  Everyone is admin.  So what I got out of the article is that I entered this in my Logon.aspx page:  
    FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, False)
    It is called if the username and password are verified.

    Then on my Main.aspx page I put the following in the Page_Load:
    If User.Identity.IsAuthenticated Then
                lblIdentity.Text = ("The current user is " + User.Identity.Name)
                lblIdentity.Text = "The current user is not authenticated."
            End If

    The article says this:  
    When you tell ASP.NET to use forms authentication, it checks to see whether a particular cookie is present with each request. Calling the RedirectFromLoginPage method creates this cookie and drops the specified identity into it. When ASP.NET goes to authenticate a user, it checks for this cookie and rebuilds the identity if it finds the cookie

    I viewed the Logon.aspx page in my browser and Logged in.  It took me to Main.aspx.  I did a search for "sqlAuthCookie" on my computer and the search couldn't find it.
    Why Not?
    I thought a cookie was supposed to be written.
    LVL 20

    Expert Comment

    >>  I don't want to use the roles based part of it...
    There wouldn't be any problem, but you still need to handle AuthenticateRequest events in global.asax code behind. There you'll grab the cookie and create a principal object then assign to current context http request. With this at least you know if one request is made anonimously or from a valid user.

    >> I thought a cookie was supposed to be written.
    It is written. But since you specified createPersistentCookie parameter equal to false in the RedirectFromLoginPage method, the cookie is created in memory and not persisted to a cookie file.
    Note: Use browser like mozilla or netscape to watch memory cookies.

    Author Comment

    Thanks for the info.

    Featured Post

    How to improve team productivity

    Quip adds documents, spreadsheets, and tasklists to your Slack experience
    - Elevate ideas to Quip docs
    - Share Quip docs in Slack
    - Get notified of changes to your docs
    - Available on iOS/Android/Desktop/Web
    - Online/Offline

    Join & Write a Comment

    This article discusses the ASP.NET AJAX ModalPopupExtender control. In this article we will show how to use the ModalPopupExtender control, how to display/show/call the ASP.NET AJAX ModalPopupExtender control from javascript, how to show/display/cal…
    International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
    Migrating to Microsoft Office 365 is becoming increasingly popular for organizations both large and small. If you have made the leap to Microsoft’s cloud platform, you know that you will need to create a corporate email signature for your Office 365…
    how to add IIS SMTP to handle application/Scanner relays into office 365.

    734 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    19 Experts available now in Live!

    Get 1:1 Help Now