logo

ASP.NET Membership and Roles in Silverlight 3

By Peter Bromberg
Printer Friendly Version
View My Articles
1884 Views
    

Shows how to hook up ASP.NET Membership and Roles providers for a Silverlight 3 Application using a WCF Service.


Since Silverlight applications run on the client, in the browser, they do not natively have access to server-side technologies such as the ASP.NET Membership, Roles, and Profile Services.  However, it is relatively easy to provide these services through a WCF service that your Silverlight Application can consume. In this manner we can require users of our Silverlight app to authenticate, and we can even grant them specific roles, which can be stored in the Silverlight application itself once a user has authenticated.

I've seen a couple of examples where people saw somebody else's sample code that was using the default ASPNETDB.MDF SQL Server database and they actually decided to "roll their own" Membership Provider so that they would not have to use two separate databases. This is unnecessary. You can enable ANY SQL Server database for ASP.NET Membership, Roles and Profile by simply running the ASPNET_REGSQL.EXE  utility from the C:\Windows\Microsoft.NET\Framework\v2.0.50727 folder. This will prompt you to select a database, and you just "follow the wizard". You can also do this programmatically; make a "Setup.aspx" page that uses the System.Web.Management utility method. In this manner, the same SQL Server database can handle both your application's business logic persistence as well as ASP.NET Membership, Role and Profile storage. All the table names and stored procedure names will be prefixed with "aspnet" so as not to clobber your existing database schema:

Management.SqlServices.Install("server", "USERNAME", "PASSWORD", "databasename", SqlFeatures.All)

System.Web.Management -- SqlFeatures.Install Method

Here is the signature:

public static void Install (
string server,
string user,
string password,
string database,
SqlFeatures features
)

The majority of the "code" to enable a Silverlight application for Membership is actually  in the web.config, so let's go over the key areas first:

First we need to set up our connection string:

 <connectionStrings>
<
remove name ="LocalSqlServer" />
<
add name ="LocalSqlServer" connectionString ="server=(local);database=TEST;Integrated Security=SSPI" providerName ="SqlClient"/>
</
connectionStrings >

It is important to have a <remove...> element on these  first, otherwise you can end up using the ASP.NET default which is predefined in machine.config. Next, we need to allow unauthenticated users access to the stuff we'll use to authenticate them, otherwise they would never get to see our Silverlight Login "Page":

<location path="SilverlightAuthenticationTestPage.aspx">
<
system.web>
<
authorization>
<
allow users="*"/>
</
authorization>
</
system.web>
</
location>
<
location path="ClientBin/SilverlightAuthentication.xap">
<
system.web>
<
authorization>
<
allow users="*"/>
</
authorization>
</
system.web>
</
location>
<
location path="WebServices/AuthenticationService.svc">
<
system.web>
<
authorization>
<
allow users="*"/>
</
authorization>
</
system.web>
</
location>

Finally, we'll enable the RoleManager:

<roleManager enabled="true" />

And last, we need our Authentication and Membership blocks:

<authentication mode="Forms">
<
forms name="secure" enableCrossAppRedirects="true" loginUrl="/SilverlightAuthenticationTestPage.aspx" defaultUrl ="/SilverlightAuthenticationTestPage.aspx" protection="All">
</
forms>
</
authentication>
<
authorization>
<
deny users="?"/>
</
authorization>
<
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" requiresQuestionAndAnswer="false" applicationName="/" requiresUniqueEmail="false" passwordFormat="Clear" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
</
providers>
</
membership>

The security features in the above sample are deliberately weak, as it is only a demo. The last ingredient is our System.ServiceModel block, which controls our service behavior:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SilverlightAuthentication.Web.WebServices.AuthenticationServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior> 
</serviceBehaviors>
</behaviors> 
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="SilverlightAuthentication.Web.WebServices.AuthenticationServiceBehavior"
name="SilverlightAuthentication.Web.WebServices.AuthenticationService">
<endpoint address="" binding="basicHttpBinding" contract="SilverlightAuthentication.Web.WebServices.AuthenticationService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service> 
</services>
</system.serviceModel>

Moving into the codebehind for the actual WCF Service implementation, the code is very simple:

 

[ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class AuthenticationService
    {
        public AuthenticationService()
        {
          // uncomment lines below to create a user and role
            //MembershipUser user = Membership.GetUser("test");
            //if(!Roles.GetAllRoles().Contains("Administrator"))
            //Roles.CreateRole("Administrator");
            //if(user==null)
            //{
            //    MembershipCreateStatus status;
            //    Membership.CreateUser("test", "test", "test@doo.com", "hello", "goodbye", true, out status);

            //    Roles.AddUsersToRole(new string[] {"test"}, "Administrator");
            //}
        }



        [OperationContract]
        public bool Authenticate(string Username, string Password)
        {
            if (Membership.ValidateUser(Username, Password))
            {
                FormsAuthentication.SetAuthCookie(Username, false);
                return true;
            }
            return false;
        }
    }

You can see I've got some commented "utility" code in the constructor that is only used once to facilitate programmatically creating a test user and Administrator Role. The actual work is done in the  Authenticate method, which does standard Membership authentication and sets the Forms Auth cookie. It then simply returns "true" if the user authenticated. You could, of course, modify this. Instead of simply returning a Boolean, you could instead have it return the names of the Roles for the authenticated user, which can be stored in the Silverlight app for further "permissions" use.  No Roles means they simply didn't authenticate.  Finally, notice the RequirementsMode attribute. You need to have this set.

OK! That's the service side. Now we can switch over to  the client-side in all of its Silverlight goodness.

In my default Silverlight "Page" I've got a Username and Password textbox, and a login Button. The codebehind looks like this
:

private void ButtonLogin_Click(object sender, RoutedEventArgs e)
        {
            AuthenticationService.AuthenticationServiceClient authService = new AuthenticationService.AuthenticationServiceClient();
            authService.AuthenticateCompleted += new EventHandler<SilverlightAuthentication.AuthenticationService.AuthenticateCompletedEventArgs>(authService_AuthenticateCompleted);
            authService.AuthenticateAsync(TextBoxUsername.Text, TextBoxPassword.Text);
        }

        private void authService_AuthenticateCompleted(object sender, SilverlightAuthentication.AuthenticationService.AuthenticateCompletedEventArgs e)
        {
            if (e.Result)
            {
                App.CurrentUser = TextBoxUsername.Text;
                App app = (App)Application.Current;
                // Remove the displayed page
                app.root.Children.Clear();
                // Show the new page
                app.root.Children.Add(new Success());
            }
            else
            {
                TextBlockResult.Text = "Invalid username or password.";
            }
        }

We instantiate our Service proxy, set the callback, and call it's AuthenticateAsync method. In the callback, if the result is true, we set the CurrentUser of the App, clear the Child Controls, and add in our Success Control which represents, in the demo,  "the rest of the app after you have logged in". If you didn't authenticate, we show the "Invalid" message.  If you are moving from one part of your Silverlight app to another, you can check the App.CurrentUser property to see if you're still "Logged in", and be able to control permissions appropriately. After reading and implementing the "Readme.txt" instructions, make sure that the web project is your startup project in Visual Studio.

You can dowload the Visual Studio 2008 Silverlight 3 Solution here. Be sure to read the "readme.txt" file as it has complete setup instructions.


Biography - Peter Bromberg
Peter Bromberg is a C# MVP, MCP, and .NET expert who has worked in banking, financial and telephony for over 20 years. Pete focuses exclusively on the .NET Platform, and currently develops SOA and other .NET applications for a Fortune 500 clientele. Peter enjoys producing digital photo collage with Maya,playing jazz flute, the beach, and fine wines. You can view Peter's UnBlog and IttyUrl sites. Pete Tweets at peterbromberg


Didn't Find The Answer You Were Looking For?

EggHeadCafe has experts online right now that may know the answer to your question.  We pay them a bonus for answering as many questions as they can.  So, why not help them and yourself by becoming a member (free) and ask them your question right now?
Ask Question In Live Forum

If you have an OpenID and do not want to become a member of the EggHeadCafe forum, you can also sign on to Chat Chaos and post your question to our real time Silverlight chat application.
Ask Question In Chat Chaos

Article Discussion: ASP.NET Membership and Roles in Silverlight 3
Peter Bromberg posted at Saturday, May 02, 2009 2:15 PM
Original Article
 

authentication with .Net RIA Services and silverlight 3
Rachida Dukes replied to Peter Bromberg at Monday, May 04, 2009 4:42 PM

Thanks for this article, I have a request:

Is it possible to write an article showing how to hook up the ASP.NEt membership and Roles using the new .Net Ria Services and silverlight 3

Thanks so much.

 

There is an example of membership and roles with Ria Services
Peter Bromberg replied to Rachida Dukes at Tuesday, May 05, 2009 10:27 AM
in the PDF "How to" document for RIA services.
 

authentication with .Net RIA Services and silverlight 3
Rachida Dukes replied to Peter Bromberg at Tuesday, May 05, 2009 1:34 PM

thanks for responding, I did look at the document for RIA services long time ago, but it didn't provide enough information for me to build a silverlight 3 application using authentication. I need more what they provide in the document. I was wondering if you can help.

Thanks again,

Rachida

 

 

I am working on an article for same
Peter Bromberg replied to Rachida Dukes at Tuesday, May 05, 2009 2:10 PM
It will appear here in the next day or two.
 

authentication with .Net RIA Services and silverlight 3
Rachida Dukes replied to Peter Bromberg at Tuesday, May 05, 2009 2:45 PM

Thanks so much, I can't wait.

Rachida

 

 

Here it is-
Peter Bromberg replied to Rachida Dukes at Tuesday, May 05, 2009 5:49 PM
http://www.eggheadcafe.com/tutorials/aspnet/ee9d9436-5e3c-4cb5-9323-68bc8ba3e476/custom-membership-role-a.aspx
 






  $1000 Contest    [)ia6l0 iii - $231  |  Jonathan VH - $153  |  Huggy Bear - $133  |  egg egg - $100  |  F Cali - $93  |  more Advertise  |  Privacy  |   (c) 2010