title: asp.net authentication of users best methods webforms
body: <p>Whats the best way for authenticating web users and storing their details which i have a class for:</p>
  
  <p>Should i use sessions or the forms auth cookie? </p>
  
  <p>How can i access it from either way say like userclass.username?</p>
  
  <p>I would like to store quite a lot of user information to stop database calls for stuff like: user type, user a full name, addresss, post code, foo1, foo2, foo3, foo4 and more. I know this could go in session or auth cookie user data. This question relates and links to <a href="https://stackoverflow.com/questions/18393122/whats-the-best-way-to-authenticate-a-user-and-store-user-details-sessions-or-fo">https://stackoverflow.com/questions/18393122/whats-the-best-way-to-authenticate-a-user-and-store-user-details-sessions-or-fo</a> which i have not had any help on</p>
  
  <p>Really could do with some help and advice here as i have a few system which i need to do this for. Any comments appreciated.</p>
  
  <p>thanks</p>
  
  <p>************************************ Links *****************************</p>
  
  <p>My code based roughly on:</p>
  
  <p><a href="http://www.shawnmclean.com/blog/2012/01/storing-strongly-typed-object-user-profile-data-in-asp-net-forms-authentication-cookie/" rel="nofollow noreferrer">http://www.shawnmclean.com/blog/2012/01/storing-strongly-typed-object-user-profile-data-in-asp-net-forms-authentication-cookie/</a></p>
  
  <p><a href="http://www.danharman.net/2011/07/07/storing-custom-data-in-forms-authentication-tickets/" rel="nofollow noreferrer">http://www.danharman.net/2011/07/07/storing-custom-data-in-forms-authentication-tickets/</a></p>
  
  <p>************************************ EDIT *****************************</p>
  
  <p>custom identity module</p>
  
  <pre><code>Public Module IdentityExtensions
  Sub New()
  End Sub
  
  Private _CustomIdentityUser As CustomIdentityUser
  
  &lt;System.Runtime.CompilerServices.Extension&gt; _
  Public Function CustomIdentity(identity As System.Security.Principal.IIdentity) As CustomIdentityUser
      'If _CustomIdentityUser Is Nothing Then
      '_CustomIdentityUser = DirectCast(identity, CustomIdentityUser)
      _CustomIdentityUser = Nothing
      If identity.GetType = GetType(FormsIdentity) Then
          _CustomIdentityUser = New CustomIdentityUser(DirectCast(identity, FormsIdentity).Ticket)
      Else
          If identity.IsAuthenticated Then
              FormsAuthentication.RedirectToLoginPage()
          End If
      End If
  
      Return _CustomIdentityUser
  End Function
  End Module
  </code></pre>
  
  <p>My Custom identity user </p>
  
  <pre><code>Public Class CustomIdentityUser
  Implements System.Security.Principal.IIdentity
  
  Private ticket As System.Web.Security.FormsAuthenticationTicket
  Private _Auth As Auth
  
  Public Sub New(ticket As System.Web.Security.FormsAuthenticationTicket)
      Me.ticket = ticket
      _Auth = New projectabc.Auth(Me.ticket)
  End Sub
  
  Public ReadOnly Property Auth As Auth
      Get
          Return Me._Auth
      End Get
  End Property
  Public ReadOnly Property Username As String
      Get
          Return Auth.Username
      End Get
  End Property
  
  Public ReadOnly Property UserType As Enumerations.EnumUserType
      Get
          Return Auth.UserType
      End Get
  End Property
  Public ReadOnly Property OwnerType As Enumerations.EnumOwnerType
      Get
          Return Auth.OwnerType
      End Get
  End Property
  
  
  Public ReadOnly Property AuthenticationType As String Implements System.Security.Principal.IIdentity.AuthenticationType
      Get
          Return "Custom"
      End Get
  End Property
  
  Public ReadOnly Property IsAuthenticated As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated
      Get
          Return ticket IsNot Nothing
      End Get
  End Property
  
  Public ReadOnly Property Name As String Implements System.Security.Principal.IIdentity.Name
      Get
          Return Username
      End Get
  End Property
  End Class
  </code></pre>
  
  <p>Then as you can see the user class calls an auth class which basically has all the properties for the user and gets and set it etc.</p>
  
  <pre><code>Public Class Auth
  Inherits BaseUser
  
  Public Property _ticket As Web.Security.FormsAuthenticationTicket
  Public RememberMe As Boolean
  
  Private _IssueDate As DateTime?
  Public ReadOnly Property IssueDate As DateTime?
      Get
          Return _IssueDate
      End Get
  End Property
  Private _Expired As Boolean
  Public ReadOnly Property Expired As Boolean
      Get
          Return _Expired
      End Get
  End Property
  Private _Expiration As DateTime?
  Public ReadOnly Property Expiration As DateTime?
      Get
          Return _Expiration
      End Get
  End Property
  
  Public Sub New(ticket As System.Web.Security.FormsAuthenticationTicket)
      Me._ticket = ticket
      Dim SignOutUser As Boolean = False
      Try
          If Not GetUserDetails() Then
              SignOutUser = True
          End If
      Catch ex As Exception
          SignOutUser = True
      End Try
      If SignOutUser Then
          HttpContext.Current.Response.Redirect("~/", True)
          SignOut()
      End If
  End Sub
  
  Public ReadOnly Property IsAuthenticated() As Boolean
      Get
          Return HttpContext.Current.User.Identity.IsAuthenticated
      End Get
  End Property
  
  Public Function SetAuthCookie() As Int16
      Dim encTicket As String
      Dim userData As String = CreateUserDataString()
      If userData.Length &gt; 0 And userData.Length &lt; 4000 Then
          Dim cookiex As HttpCookie = FormsAuthentication.GetAuthCookie(MyBase.Username, True)
          Dim ticketx As FormsAuthenticationTicket = FormsAuthentication.Decrypt(cookiex.Value)
  
          'Dim newTicket = New FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userData, ticket.CookiePath)
          'encTicket = FormsAuthentication.Encrypt(newTicket)
  
          'Use existing cookie. Could create new one but would have to copy settings over...
          'cookie.Value = encTicket
          'cookie.Expires = newTicket.Expiration.AddHours(24)
  
          'HttpContext.Current.Response.Cookies.Add(cookie)
          Dim ticket As New FormsAuthenticationTicket(1, ticketx.Name, DateTime.Now, ticketx.Expiration, False, userData, ticketx.CookiePath)
          encTicket = FormsAuthentication.Encrypt(ticket)
          cookiex.Value = encTicket
          'Dim cookie As New HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
  
          HttpContext.Current.Response.Cookies.Add(cookiex)
      Else
          Throw New ArgumentOutOfRangeException("User data length exceeds maximum", New ArgumentOutOfRangeException)
      End If
  
      Return encTicket.Length
  End Function
  
  Public Function GetUserDetails() As Boolean
      Dim valid As Boolean = False      
  
      If _ticket IsNot Nothing Then
          With _ticket
              RememberMe = .IsPersistent
              Username = .Name
              _IssueDate = .IssueDate
              _Expired = .Expired
              _Expiration = .Expiration
  
              Try
                  If .UserData.Length &gt; 0 Then
                      valid = SetUserDataFromString(.UserData)
                  Else
                      'we have a problem
                      Return False
                  End If
              Catch ex As Exception
                  'sign them out as they may have a cookie but the code may have changed so it errors thus make them login again.
                  'SignOut()
                  Throw ex
  
              End Try
          End With
      End If
  
      Return valid
  
  End Function
  
  Private Function CreateUserDataString() As String
      Dim sData As New System.Text.StringBuilder
  
      With sData
          .Append(MyBase.UserID)
          .Append("|") 'delimeter we are using
          .Append(Int16.Parse(MyBase.UserType))
          .Append("|")
          .Append(Int16.Parse(MyBase.Security))
          .Append("|") 'delimeter we are using
          .Append(MyBase.FirstName)
          .Append("|")
          .Append(MyBase.LastName) 
      .Append("|")
          .Append(MyBase.foo1)  
      .Append("|")
          .Append(MyBase.foo2) 
          .Append("|")            
          .Append(MyBase.foo3)  
      .Append("|")
          .Append(MyBase.foo4) 
      End With
  
  
      Return sData.ToString
  End Function    
  
     Public Function SetUserDataFromString(userData As String) As Boolean
      Dim valid As Boolean = False
      Dim sData As New System.Text.StringBuilder
      'check we have a delimeter
      Dim arUserData As String() = userData.Split("|")
      Try
  
  
      If arUserData.Count &gt;= 9 Then '9 because that the user only stuff
          With arUserData
              MyBase.UserID = arUserData(0)
              MyBase.UserType = arUserData(1)
              MyBase.Security = arUserData(2)
              MyBase.FirstName = arUserData(3)
              MyBase.LastName = arUserData(4)
              MyBase.foo1 = arUserData(5)
      MyBase.foo2 = arUserData(6)
      MyBase.foo3 = arUserData(7)
      MyBase.foo4 = arUserData(8)
          End With
          valid = True
      Else
          valid = False
          End If
  
      Catch ex As Exception
          Throw New ArgumentOutOfRangeException("User data length to short", New ArgumentOutOfRangeException)
      End Try
      Return valid
  End Function
  
  Public Sub SignOut()
      FormsAuthentication.SignOut()
  End Sub
  </code></pre>