Click here to Skip to main content
15,892,927 members
Articles / Web Development / ASP.NET

Secure Persistent ASP.NET Forms Authentication

Rate me:
Please Sign up or sign in to vote.
4.00/5 (3 votes)
27 Aug 2008LGPL33 min read 71.2K   534   51  
An ASP.NET system for having two authentication cookies, one secure and one insecure, to have multiple tiers of security by folder.
Licensing
----------

Copyright (c) 2008 Pathfinder Software, LLC.  All Rights Reserved.
Pathfinder Software <http://www.pfasoft.com>
PartialAuthenticationSystem is distributed under the terms of the GNU Lesser General Public License (GPL)

PartialAuthenticationSystem is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

PartialAuthenticationSystem is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with PartialAuthenticationSystem.  If not, see <http://www.gnu.org/licenses/>.

The basic rules of the license are the you can use and change the code here as you see fit,
but you can't remove the license and you can't sell the code.  Please review the license
for more details.


Overview
---------

While the ASP.NET Forms Authentication system is a great system for authentication, it has
one significant shortcoming for a lot of sites. You can only restrict it to always pass the
authentication cookies in a secure manner or always pass them even if the connection is not
secure. There is no intermediate method of authentication available to you. This means
that if you are operating a web store you have a problem.

Normally, a web store wants the customer identified as soon as they come to the site, and
throughout the shopping experience. However, when the user goes to edit their account or checkout,
you want to switch them to a secure mode. In order to be secure, the cookie used to authenticate
them for checkout must be restricted to SSL connections. This means that to maintain their login,
you would have to remain in SSL from the moment they sign in forward, which adds a lot of unnecessary
server load. Plus, it can cause headaches with external content you might want to include on your page
that isn't encrypted.

The solution is to modify the forms authentication system to use a pair of cookies. One is valid only
to identify you but not access secure functions, doesn't require SSL to be transmitted, and is persistent
across sessions. The other is a full authentication and requires SSL to be transmitted.

The basic method this system uses is adding two additional HttpModules to your web.config file,
PartialAuthenticationModule and PartialAuthorizationModule.

The PartialAuthenticationModule works by adding to the existing FormsAuthenticationModule.  The
FormsAuthenticationModule is used as normal to process authentication for the secure authentication
cookie (requireSSL should be set to true for the forms module in web.config).  The
PartialAuthenticationModule kicks in after the FormsAuthenticationModule.  If there is no user on the
current request (i.e. not a secure request, so client didn't transmit the cookie) then the user is added
to the context from the secondary insecure cookie instead.  The user that is added will have the
"Partial" AuthenticationType instead of "Forms".  In case the login has changed, it will also clear the
old secondary cookie if the username doesn't match with the secure cookie.

The PartialAuthorizationModule processes later in the request life cycle.  It uses the <authorization>
section of the <partialAuthenticationSystem> section of your web.config files to identify security
requirements on each folder.  You just add a web.config file to each subfolder as required.  This section
supports two key fields.  requiresLogin is either true or false, and specifies if the folder requires a
secure login using the primary FormsAuthentication cookie.  It verifies this by checking the
AuthenticationType on the logged in user.  The second field is requireSSL, which can be None, Optional,
or Required.  This will automatically redirect the request to or from https based on how you want the
folder to be handled.  This allows you to use normal app-relative URLs throughout your application
without worrying about switching to and from https.  Normally, for most folders you would use
requiresLogin="false" and requireSSL="None", and for secure folders you would use requiresLogin="true"
and requireSSL="Required".

I've also implemented a PartialAuthentication static class that is very similar to the
FormsAuthentication static class.  It actually uses a lot of the methods from the FormsAuthentication
class to help it with a lot of the processing.  In particular, you should switch any login or logoff code
to use the methods in the PartialAuthentication class instead of FormsAuthentication.  This will create
or remove both of the necessary cookies.  To sign off a user from the secure section but still leave the
persistent insecure cookie, use the FormsAuthentication.SignOff method instead.

As far as security is concerned, the partial authentication cookie is generated using a
FormsAuthenticationTicket just like with FormsAuthentication.  It only difference is that the name of the
cookie is prepended to the username in the ticket, and on decryption that string is validated.  This
prevents a client from editing their cookie file to set the secure cookie to have the same value as the
insecure cookie.  The cookies are encrypted using the same machine authentication keys as the forms
authentication tickets, so they should work on web farms in the same manner.

Please note that this library is designed for .NET 3.5 and Visual Studio 2008, though it should be easily
convertible back to .NET 2.0 if you change the project settings.


Web.config Settings
--------------------

Add the following to your root web.config file.  These sections will probably already exist,
you will just add the additional entries to them:

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <configSections>
    <sectionGroup name="partialAuthenticationSystem">
      <section name="authentication" type="PartialAuthenticationSystem.PartialAuthenticationSection, PartialAuthenticationSystem" allowDefinition="MachineToApplication" />
      <section name="authorization" type="PartialAuthenticationSystem.PartialAuthorizationSection, PartialAuthenticationSystem" />
    </sectionGroup>
  </configSections>
  
  <system.web>
    <httpModules>
      <add name="PartialAuthorization" type="PartialAuthenticationSystem.PartialAuthorizationModule,PartialAuthenticationSystem" />
      <add name="PartialAuthentication" type="PartialAuthenticationSystem.PartialAuthenticationModule,PartialAuthenticationSystem" />
    </httpModules>
  </system.web>
  
  <partialAuthenticationSystem>
    <authentication timeout="172800" name=".ASPXIDENTITY" requireSSL="false" />
    <authorization requireSSL="None" requireLogin="false" />
  </partialAuthenticationSystem>
</configuration>

You must also enable forms authentication in the <authenctication> section under <system.web>, and if you are
using SSL then you will probably set requireSSL to true there as well.

Note that you can customize the settings under <partialAuthenticationSystem> as you see fit.  The timeout is the
timeout for the persistent cookie.  The cookie name must be different than the cookie name used for forms
authentication.

You can also add the <authorization> section from <partialAuthenticationSystem> to web.config files in
subfolders like this:

<?xml version="1.0"?>
<configuration>
  <partialAuthenticationSystem>
    <authorization requireSSL="Required" requireLogin="false" />
  </partialAuthenticationSystem>
</configuration>

You must also change your code to use the PartialAuthentication static class to login and logout, rather than
the FormsAuthentication class. This will create or remove both of the necessary cookies. To sign off a user
from the secure section but still leave the persistent insecure cookie, use the FormsAuthentication.SignOff
method instead. If you are using the Login standard control, just override the LoggedIn event.

Revision History
-----------------

1.0.1.0		5/28/2008	Fixed problems with HTTP redirection of secure WebResource.axd and ScriptResource.axd requests

1.0.0.0		5/13/2008	Initial Release

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) Pathfinder Software
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions