Need help with implementing Forms Authentication

Posted on 2005-04-19
Medium Priority
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
  • 2
  • 2
LVL 20

Accepted Solution

ihenry earned 1050 total points
ID: 13816203
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

ID: 13819010
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

ID: 13822689
>>  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

ID: 13824844
Thanks for the info.

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In an ASP.NET application, I faced some technical problems. In this article, I list them out and show the solutions that I found.  I hope it will be useful. Problem: After closing a pop-up window, the parent page should be refreshed automaticall…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Integration Management Part 2
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses

862 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