Posts Tagged ‘membership’

MVC Membership Starter Kit Released

// August 7th, 2009 // 36 Comments » // MVC

Almost six months after the official release of Asp.Net MVC 1.0 and nearly a year after the last release of the starter kit, I’ve finally rewritten and released the Asp.Net MVC Membership Starter Kit. If you’re already familiar with what it is and want to grab it, you can find the release on the CodePlex project site:

http://mvcmembership.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=22875

(more…)

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC Membership – Preview 5

// September 6th, 2008 // 12 Comments » // MVC

Last weekend I posted a release of the MVC Membership Starter Kit that targets Preview 5 of the ASP.Net MVC framework. There was no packaged release targeting Preview 4 (though if you downloaded the latest source, it worked), so this release essentially packages the changes from both previews. (more…)

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC Membership – Preview 3

// July 2nd, 2008 // 17 Comments » // MVC

Tonight we posted a new release of the MVC Membership Starter Kit. This release is an update to migrate the starter kit to the new Preview 3 release of the MVC framework. While several bugs have been squashed, no major new functionality has been added.

If you couldn’t wait and downloaded the source prior to the official Preview 3 release, you’ll still want to download tonight’s official release as several important issues have been addressed.

Bug Fixes in 1.3:

  • The System.Web.Abstraction, System.Web.Mvc, and System.Web.Routing DLLs being used prior to tonight were from an earlier Preview 3 release and were not signed by Microsoft.
  • Routing ambiguities caused a 404 error to occur when a user enters an incorrect username/password combination on the login page.
  • Several errors were occurring on various password recovery screens which created a bad user experience.
  • Errors on the administration section’s Create User and Display User pages were preventing that functionality from working at all.

Thanks for all of the interest everyone has shown in this project and thanks to Maarten and Greg for their contributions; especially to Maarten as he did most of the grunt work in upgrading our code base to Preview 3. Please send any feedback you have our way, we’d love to hear it!

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC Membership Starter Kit – 1.2

// April 28th, 2008 // 6 Comments » // MVC

This weekend I posted a new release of the MVC Membership Starter Kit. This release is an update to migrate the starter kit to the new interim release of the MVC framework. If you do not feel comfortable using the interim release, please continue using the 1.1 release and wait for Microsoft to release Preview 3; we will update the Starter Kit soon thereafter.

Changes in 1.2:

  • WindowsLive is now a supported authentication scenario (read Maarten’s blog post on this).
  • Per Andrew Arnott’s suggestion, the starter kit now uses the DotNetOpenId library rather than the code previously used (which was created by Mads Kristensen). This gives us a more robust and secure implementation that will develop and improve independently of this project.
  • All actions that previously expected a username in the route now expect the user’s ProviderUserKey (a Guid) instead. This was done because users with OpenID urls as their username could not previously be accessed.
  • "Whitelist support" has been added to the OpenID implementation, allowing you to setup regular expressions that dictate which OpenID providers are allowed to be used when logging into your site. By default there is no whitelist, so all providers are allowed.
  • The starter kit now offers greater control over which authentication scenarios your site supports and which is the default. Out-of-the-box only FormsAuthentication is enabled and is obviously the default.
Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC: New Membership Starter Kit Release

// April 11th, 2008 // 12 Comments » // MVC

The Starter Kit

If you haven’t had a chance to read about the MVC Membership Starter Kit I’ve created, read this post first.

New Release

Since we first created the starter kit a week and a half ago, Maarten Balliauw and I have been hard at work fleshing out the implementation to provide as much functionality as possible. Last night we finished the last stretch of things we had identified for this release and have posted the code as a new release on CodePlex. Keep in mind you can also always download our latest builds from CodePlex as well without waiting for a new release.

New Features

OpenID

Mads Kristensen released a lightweight OpenID consumer earlier this year that I then proceeded to flesh out with a security patch. The reason I did so was so that I could include OpenID in this release of the Starter Kit.

Out of the box you can create a route to the OpenIDLogin action, which displays the following view:

OpenID

Once the user has entered their OpenID url, the starter kit will take care of the rest for you, with one critical exception: you have to map the url to a user in your membership database. To do so, you simple override a virtual method and return a MembershipUser, like so:

   1: protected override MembershipUser AssociateOpenIDToMembershipUser( string identity, string name, string email )
   2: {
   3:     return Membership.GetUser(identity);
   4: }

Note that the above implementation maps the OpenID url to a user’s UserName, which may or may not be what you want for your application. Adjust accordingly.

Password Recovery Tools

Maarten did a great job providing users with a way to manage their passwords. While logged in they can change their password:

ChangePassword

Or if they are having trouble logging in, they can submit their username…

ForgotPassword

…and then answer their password question (if the system is configured to require it)…

PasswordQuestion

…and they will then receive their password via email (or a newly generated password — depending on system configuration).

Client-Side Validation

All non-administrative forms now include basic client-side validation. The validations even change based upon your Membership settings.

For instance, by default the ASP.Net Membership provider requires passwords to contain at least 1 non-alphanumeric character. If a user entered a password of “password” they would see the following alert:

ClientSideValidation

Components: Login & LoginStatus

Maarten created components that emulate the functionality of the old Login and LoginStatus controls. Now it is easy to have a Login box on every page.

Major Refactoring

Most of the controller and filter code has been broken out into a separate assembly.

Your FormsAuthentication and FormsAuthenticationAdministration controllers should now inherit from a base version of each. Maarten has created a boat load of virtual method hooks for each action (OnBeforeBlah, OnAfterBlah, OnErrorBlah) that provides you with easy extensibility points without needing to directly modify the starter kit base code.

Hopefully this refactoring will make it easy for you to upgrade to future versions of the starter kit’s code as they become available.

The Future

Currently we’ve cleared our plate and have no more planned features to attend to. Does this mean that we are done? No. This is what you can expect to see us working on next:

  • Preview3 updates, whenever it becomes available.
  • Validations on the administrative side.
  • Bug fixes, of course. :-)
  • If you have suggestions for what you would like to see in the next release, please drop me a line and let me know!

You can download the new release from CodePlex.

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC: Membership Starter Kit

// April 2nd, 2008 // 12 Comments » // MVC

A newer version of the Membership Starter Kit is now available. Click here to see what has changed.

Introduction

One of my very first blog posts (and most definitely my most popular so far) revolved around how to integrate ASP.Net membership and forms authentication into the ASP.Net MVC framework which had just been released in it’s December CTP flavor. It has remained popular to this day, but unfortunately the Preview 2 release of the MVC framework has caused much of the code I released in that article to no longer function correctly.

Even before the release of Preview 2, I had been planning to extend the samples I was providing to offer more useful features. I don’t know about you, but nearly every website I ever create with ASP.Net requires some kind of security/membership system. My preference is to use the built-in system when possible (except for the horrible Profiles sub-system). This means creating login, logout, & registration functionality every time, as well as creating administrative screens for managing the users that enter your system.

WebForms provides some controls to help with the login and registration process, but user administration has always been delegated to either (a) the built-in tool that runs separately and doesn’t work remotely or (b) rolling your own solution. The development of the MVC framework seems to me like a good time to resolve this scenario and provide the community with an array of pre-built tools to help boot-strap projects so that we can stop working on infrastructure and start working on the heart of the individual application.

With that in mind I have created a CodePlex project: the ASP.Net MVC Membership Starter Kit. It currently provides controllers and views for all of the common authentication and user administration needs, including:

  • Login/Logout
  • Registration
  • List of Registered Users
  • User Details / Administration
  • Role Management

A big thanks goes out to Rob Conery, as I borrowed his recent Authentication Filters and included those, along with my recently released Error Handling Filters.

Okay, enough wall o’text. Let’s take a look at some screenshots:

Screenshot Tour

Here is the menu when you first log in:

Menu-LoggedOut

The registration page:

Registration

The login page (note that the Administrator’s credentials are displayed to make it easy to get started, you’ll obviously want to change them and remove that note):

Login

Having logged in, here is what the menu looks like now:

Menu-LoggedIn

The current options upon clicking the Security tab:

Security

Clicking “Manage Users” brings you to a list of all users currently registered:

ManageUsers

Clicking on the user takes you to a form that allows you to view their details and edit a few aspects of their profile…

User-Top

as well as view/change the roles they are in and help with password issues:

User-Bottom

From the Security tab you can also go to a list of all the system’s roles, from which you can add/delete roles as you need:

Roles

Clicking on a role from the roles list or the user profile allows you to view/modify the users in that role:

UsersInRole

And finally, the Security tab offers a link to another registration form, geared toward Administrators:

CreateUser

NSFAQ (Not-So Frequently Asked Questions)

Q: Does this compete with MvcContrib?
A: No. MvcContrib is a great project that aims to features like alternate routing and view engines, and IoC integration. This project is simply a starter kit to help get membership-based applications off the ground a little quicker. There is no reason you could not use both projects together.

Q: What dependencies does using this starter kit saddle me with?
A: Ideally, none, other than the ASP.Net Membership API. Every measure will be taken to avoid using third party libraries, be it JavaScript or .Net. We will strive to separate the code and rely on default settings as much as possible to make it easy for you to customize your installation without anything in the starter kit getting in the way.

Q: Who is responsible for this?
A: Currently, only me, but I’d like that to change! I’m keenly interested in finding a few other developers that would like to contribute to enhancing the starter kit. Please contact me if you’d like to help!

What’s Next?

There are a few features missing that I would like to include in the very short term. Primarily these are features for end-users, like Change Password and Forgot My Password (both of which are currently available on the administration side). Beyond that, visual cleanup of the forms (and separation of the style sheets) as well as a bit of AJAX-ification of the forms would be nice. If you use the starter kit and have suggestions or criticisms, please post to the Discussions forum or Issue Tracker!

You can download the latest release from the CodePlex project. I hope you all find it useful!

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

ASP.Net MVC Membership Basics

// December 10th, 2007 // 36 Comments » // MVC

NOTE:
This article was written for the December CTP release of the MVC framework. Unfortunately, it does not entirely apply to the Preview 2 release or subsequent releases.

The MVC bits have finally arrived and I’ve spent a while digesting them. I’ve been waiting for the bits to be released to begin working on a side-project, so the first thing I did after downloading them last night was crank it up and start working on a new ASP.NET MVC Web Application project.

Typically, the first thing I do on a new project is set up the authentication/authorization system. For the project I am working on I want to use the ASP.Net Membership system, but most of the Membership controls do not work with the MVC framework because they require postbacks. I spent some time last night building a Security controller and views for Registration and Login that I thought would be worth sharing.

So far I have implemented basic functionality for Register, Login, and Logout. There are three files we will have to create. We will also have to change the routing table. Let’s start with the SecurityController:

    1 public class SecurityController : Controller

    2 {

    3 

    4     [ControllerAction]

    5     public void Login()

    6     {

    7         RenderView("Login");

    8     }

    9 

   10     [ControllerAction]

   11     public void Register()

   12     {

   13         RenderView( "Register" );

   14     }

   15 

   16     [ControllerAction]

   17     public void Logout()

   18     {

   19         FormsAuthentication.SignOut();

   20         Response.Redirect( "/" );

   21     }

   22 

   23     [ControllerAction]

   24     public void Authenticate( string userName, string password, string rememberMe, string returnUrl )

   25     {

   26         // figure out if username and password are correct

   27         if( Membership.ValidateUser( userName, password ) )

   28         {

   29             // everything is good, create an authticket and go

   30             FormsAuthentication.SetAuthCookie( userName, (rememberMe != null) );

   31             Response.Redirect( returnUrl );

   32         }

   33         else

   34         {

   35             // something was wrong, figure out which and pass it into view

   36             if( Membership.GetUser(userName) == null )

   37                 ViewData["ErrorMessage"] = "Incorrect username.";

   38             else

   39                 ViewData["ErrorMessage"] = "Incorrect password.";

   40             RenderView( "Login" );

   41         }

   42     }

   43 

   44     [ControllerAction]

   45     public void CreateUser( string userName, string emailAddress, string password, string returnUrl )

   46     {

   47         try

   48         {

   49             // try to create user and then login that user

   50             if( Membership.CreateUser( userName, password, emailAddress ) == null )

   51                 throw new MembershipCreateUserException( "An unspecified error occurred." );

   52             FormsAuthentication.SetAuthCookie( userName, true );

   53             Response.Redirect( returnUrl );

   54         }

   55         catch( MembershipCreateUserException e )

   56         {

   57             // something went wrong

   58             ViewData["ErrorMessage"] = e.Message;

   59             RenderView("Register");

   60             return;

   61         }

   62     }

   63 

   64 }

 

So we have two basic actions methods that only display views (Register and Login) and three action-only methods that have no views (CreateUser, Authenticate, Logout).

I have chosen to not have a logout page, but to instead redirect to the homepage. Switch out ‘Response.Redirect( "/" );’ for ‘RenderView( "Logout" );’ and create a Logout.aspx view if you would like to display a logout message.

Now let’s look at the Login view:

    1 <asp:Content ID="content" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">

    2 

    3     <h2>Login</h2>

    4 

    5     <% if( ViewData["ErrorMessage"] != null ){ %>

    6     <p><% =ViewData["ErrorMessage"] %></p>

    7     <% } %>

    8 

    9     <% using(Html.Form( "Authenticate", "Security" )){ %>

   10     <fieldset>

   11         <legend>Login</legend>

   12         <div><label for="userName">User Name:</label> <% =Html.TextBox( "userName" ) %></div>

   13         <div><label for="password">Password:</label> <% =Html.Password( "password" ) %></div>

   14         <div><label for="rememberMe">Remember Me:</label>

   15             <input type="checkbox" id="rememberMe" name="rememberMe" checked="checked" value="checked" /></div>

   16         <div><% =Html.SubmitButton() %></div>

   17         <% =Html.Hidden( "returnUrl", "/" ) %>

   18     </fieldset>

   19     <% } %>

   20 

   21 </asp:Content>

 

The toolkit’s Html.Checkbox(…) method annoys me. More on why in another post. For now I’ve instead just written the html out by hand. You’ll note I’ve also linked the label to the checkbox with JavaScript so that clicking the label toggles the checkbox.

Then the Register view:

    1 <asp:Content ID="content" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">

    2 

    3     <h2>Register</h2>

    4 

    5     <% if( ViewData["ErrorMessage"] != null ){ %>

    6     <p><% =ViewData["ErrorMessage"] %></p>

    7     <% } %>

    8 

    9     <% using(Html.Form( "CreateUser", "Security" )){ %>

   10     <fieldset>

   11         <legend>Register</legend>

   12         <div><label for="userName">User Name:</label> <% =Html.TextBox( "userName" ) %></div>

   13         <div><label for="emailAddress">Email Address:</label> <% =Html.TextBox( "emailAddress" ) %></div>

   14         <div><label for="password">Password:</label> <% =Html.Password( "password" ) %></div>

   15         <div><% =Html.SubmitButton() %></div>

   16         <% =Html.Hidden( "returnUrl", "/" ) %>

   17     </fieldset>

   18     <% } %>

   19 

   20 </asp:Content>

 

Another straightforward view. Not much to discuss here.

And finally, let’s add the new routes:

    1 RouteTable.Routes.Add( new Route

    2 {

    3     Url = "Login",

    4     Defaults = new {

    5         controller = "Security",

    6         action = "Login" },

    7     RouteHandler = typeof( MvcRouteHandler )

    8 } );

    9 RouteTable.Routes.Add( new Route

   10 {

   11     Url = "Register",

   12     Defaults = new {

   13         controller = "Security",

   14         action = "Register" },

   15     RouteHandler = typeof( MvcRouteHandler )

   16 } );

 

I personally like login to be http://website/login and register to be http://website/register, so that is how I have configured it. The other three actions (Logout, Authenticate, and CreateUser) I access via the default route (ex: /Security/Logout).

That’s it! You should now have a working registration/login system. I’ll leave making it pretty with CSS as an exercise for the reader.

I have included all of the code samples above in the below ZIP file. Just unzip it and place the controller into the Controllers directory, the views into the Views/Security directory (which you will have to create), and copy the code from Routes.txt to the appropriate area of your Global.asax.

MVCMembership_v1.2.zip (2.03 kb)

UPDATE (Dec 11): Johan and Steve Harman were kind enough to point out that I had foolishly set the "remember me" checkbox’s label’s "for" attribute to point to the password field instead of the checkbox itself. I have fixed the code above and provided a new zip file (1.1) for download. Thanks guys!

Update (Dec 19): oVan pointed out a bug in the routing rules defined in the routes.txt file. I have updated the zip file with the correct code. Thanks oVan!

Update (Jan 3): James Nail asked a very good question via a comment: what do you set for the loginUrl and defaultUrl in your web.config? Well James, here is how I’ve setup my web.config…

Assuming we’ll be using forms authentication and securing all pages except login and the homepage, place the following inside the <system.web>element:

    1 <authentication mode="Forms">

    2   <forms loginUrl="/Login" defaultUrl="/" />

    3 </authentication>

    4 <authorization>

    5   <deny users="?" />

    6 </authorization>

Then, somewhere outside the <system.web> element add:

    1 <location path="Default.aspx">

    2   <system.web>

    3     <authorization>

    4       <allow users="*" />

    5     </authorization>

    6   </system.web>

    7 </location>

    8 <location path="Security">

    9   <system.web>

   10     <authorization>

   11       <allow users="*" />

   12     </authorization>

   13   </system.web>

   14 </location>

   15 <location path="Login">

   16   <system.web>

   17     <authorization>

   18       <allow users="*" />

   19     </authorization>

   20   </system.web>

   21 </location>

Note that this will grant access to all actions within the Security controller. It is also worth pointing out that, dependent on your setup, your CSS and image files may not load unless you also create a location path for their directory and grant all users access like so:

    1 <location path="Content">

    2   <system.web>

    3     <authorization>

    4       <allow users="*" />

    5     </authorization>

    6   </system.web>

    7 </location>

I have not updated the zip file with these web.config settings; let me know if anyone would prefer that I add it. I hope this helps some of you!

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com