ASP.NET (and Silverlight) authentication woes
March 17, 2010 5 Comments
For one of my Silverlight projects, I need to allow my users to create account on my database. It’s not at all obvious how to go about this, but I was able to solve it after tons of googling.
[For a simpler method, see this blog post a minimal silverlight authentication implementation]
If you start out with a standard Visual Studio installation, a SQL Server Express installation is included – and that database will automatically be used for authentication. I didn’t include SQL Server Express with my installation, so I’ve had to add the authentication tables afterwards. And that actually suits me just fine, because I really want my authentication tables to be stored with the rest of my application data, in a database that’s been custom designed for this project.
If you create a Silverlight application based on the Silverlight Buisness Application template, you’ll be using the ASP.NET authentication system. Unless you override it with your own MembershipProvider, but I’ll save that for a later blog…
The tables you’ll need
Looking at a database that’s prepared for handing ASP.NET authentication, the following tables must exist on your database;
aspnet_Applications
aspnet_Membership
aspnet_Paths
aspnet_PersonalizationAllUsers
aspnet_PersonalizationPerUser
aspnet_Profile
aspnet_Roles
aspnet_SchemaVersions
aspnet_Users
aspnet_UsersInRoles
aspnet_WebEvent_Events
They’re all all be placed in the dbo namespace. On top of these tables, you’ll also find these views;
vw_aspnet_Applications
vw_aspnet_MembershipUsers
vw_aspnet_Profiles
vw_aspnet_Roles
vw_aspnet_Users
vw_aspnet_UsersInRoles
vw_aspnet_WebPartState_Paths
vw_aspnet_WebPartState_Shared
vw_aspnet_WebPartState_User
And loads and loads of stored procedures.
Adding asp.net tables to an existing database
If you, like me, have an existing database to which you’d like to add these tables, you must use the tool ASP.NET SQL Server Registration Tool (Aspnet_regsql.exe). According to the documentation, it should be found in “[drive:]\%windir%\Microsoft.NET\Framework\version” on your webserver/development machine, but I found that I only have it in the v2.0.50727 folder, not the v3.0 or v3.4 folders.
It’s fairly straight forward to use, just start it and you’ll be greeted with a wizard to walk you through the process.
Silverlight Business Application login fails
“Load operation failed for query ‘Login’. Could not connect to SQL Server.”
If you’ve followed my instructions this far, you’ll get the above error message whenever you try to login. Why? Well, so far, the application doesn’t know where to find the tables.
By default, the .NET framework will try to use the AspNetSqlMembershipProvider and it will try to find the required tables on a server specified by the connection-string “LocalSqlServer”.
Connecting your application to your new authentications
Create a connection string in your Web.config file that points to the database that contains your login information;
<connectionStrings>
<remove name="LocalSqlServer"/>
<add
name="LocalSqlServer"
connectionString="Data Source=localhost;Initial Catalog=ImageEvolvatron;Integrated Security=True"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Now update your membership provider to use the connectionstring in question;
<membership>
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="7"
minRequiredNonalphanumericCharacters="1"
passwordAttemptWindow="10"
passwordStrengthRegularExpression=""
requiresQuestionAndAnswer="false"/>
</providers>
</membership>
Still can’t login…
But that’s to be expected – at least the error message indicates that we’re oh, so close now. We’ll need to create the account first, hit “Register now” and fill out the form. And voila, we have login success;
But I want my own tables!
[For a simpler method, see this blog post a minimal silverlight authentication implementation]
If you’re like me, you don’t want to store your information in these tables, you’ll want to design your own tables. To do this, you’ll have to implement a number of your own support classes.
For my Silverlight project, I tried to only implement the MembershipProvider, but I failed because it seems I also need a role provider and a ProfileProvider.
The code below is cut from the Web application that was generated with my Silverlight Business Application;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
public void AddUser(RegistrationData user)
{
// RoleProvider is used in the background
if (!Roles.RoleExists(UserRegistrationService.DefaultRole))
{
Roles.CreateRole(UserRegistrationService.DefaultRole);
}
// MembershipProvider is used in the background
MembershipCreateStatus createStatus;
Membership.CreateUser(user.UserName, user.Password, user.Email, user.Question, user.Answer, true, null, out createStatus);
if (createStatus != MembershipCreateStatus.Success)
{
throw new DomainException(ErrorCodeToString(createStatus));
}
// RoleProvider is used in the background
Roles.AddUserToRole(user.UserName, UserRegistrationService.DefaultRole);
// Profile provider is used in the background
ProfileBase profile = ProfileBase.Create(user.UserName, true);
profile.SetPropertyValue("FriendlyName", user.FriendlyName);
profile.Save();
}
MembershipProvider
You’ll need your own MembershipProvider, how to implement your own is explained in multiple examples online, for instance here and here. The MembershipProvider is responsible for storing your accounts, retrieving the accounts and authenticating the accounts.
RoleProvider
You’ll need your own RoleProvider, how to implement your own is explained in multiple examples online, for instance here and here. The RoleProvider is responsible for storing retrieving roles and connecting users to Roles. If you don’t intend to use roles, you can probably do without it – but my attempts to skip it has so far failed…
ProfileProvider
You’ll need your own ProfileProvider. The ProfileProvider is responsible for storing additional information about your users, information that’s not handled by the MembershipProvider. If you don’t intend to store additional information, or you intend to store it in somekine of separate storage, you can probably do without it. But again, my attemps to skip it has so far failed…
Pingback: (Silverlight) Switching between LINQtoSQL and Entity Framework « Mattias Fagerlund's Coding Blog
Pingback: Silverlight, Minimal Authentication Implementation « Mattias Fagerlund's Coding Blog
Pingback: 2010 in review « Mattias Fagerlund's Coding Blog
Hi
Nice post, Im in the same boat as you, however I just need to tweek the registration part. You see I dont need the security question. How can I remove it from the register window? Also I have my own tables for users which holds user data. In fact I have another table which holds a list of valid users. How can I validate a username against my own table when a user tries to register. So as to limit who is able to register. (by username)
thanks in advance
mike okon
Did you check out the next blog post http://lotsacode.wordpress.com/2010/03/19/silverlight-minimal-authentication-implementation/ – that uses custom storage and should be closer to what you need.