interviews.dotnetthread.com

↑ Grab this Headline Animator

Wednesday, February 25, 2009

Implementing Forms Authentication in Silverlight Application.

Introduction:

Most of the time to Implement security in ASP.NET website we use Forms Authentication. Forms authentication uses an authentication ticket that is created when a user logs on to a site, and then it tracks the user throughout the site. The forms authentication ticket is usually contained inside a cookie (or passed in query string).
If you are developing a site in Silverlight with login page and other Silverlight pages and if you want to implement Forms authentication where you need to authenticate user based on the credentials entered in Silverlight based login page and display the user name in other Silverlight pages after logging in. Read this article to achieve same kind of functionality as Forms authentication in normal ASP.NET website.

Description:

• Create a new Silverlight Application using the Visual Studio installed templates.

• Add a new Web to the Solution by accepting the default options in the Add Silverlight Application wizard that pops up.

• Rename Default.aspx as UserLogin.aspx and set it as default page.

• Create a new folder say “Forms” in the Web project and all web pages which requires authentication to this folder.

• Let’s add a new page to “Forms” folder and name it as ShowDetails.aspx.

• Add the following code into web.config file to enable forms authentication.



<authentication mode="Forms">
<forms name="dotnetthread" defaultUrl="/Forms/ShowDetails.aspx" loginUrl="UserLogin.aspx" protection="All" path="/">
<credentials passwordFormat="Clear">
<user name="anil" password="anil"/>
</credentials>
</forms>
</authentication>



• Add a new web.config file into “Forms” folder and add following code to deny un authenticated users.


<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>



• Then we will create Login page in Silverlight and show it (XAML) in UserLogin.aspx page.

• Add new Silverlight User Control (login.xaml) to the Silverlight application.

• Add below code to login.xaml file to create login controls.


<Grid x:Name="loginGrid" HorizontalAlignment="Left" Width="400" Height="300" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120" />
<ColumnDefinition Width="120" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<TextBlock Text="User Login Form" Grid.ColumnSpan="2" HorizontalAlignment="Center"></TextBlock>
<TextBlock Text="UserName" Width="100" HorizontalAlignment="Right" Height="20" Grid.Row="1" Grid.Column="0"></TextBlock>
<TextBox x:Name="UserName" Width="100" Height="20" Grid.Row="1" Grid.Column="1"></TextBox>

<TextBlock Text="Password" Width="100" HorizontalAlignment="Right" Height="20" Grid.Row="2" Grid.Column="0"></TextBlock>
<TextBox x:Name="Password" Width="100" Height="20" Grid.Row="2" Grid.Column="1"></TextBox>
<Button x:Name="bntLogin" Width="80" Height="25" Content="Login" Click="bntLogin_Click" Grid.Row="3" Grid.Column="1"></Button>
</Grid>



• Login XAML preview looks like below.


• Add new Silverlight User Control (userdetails.xaml) to the Silverlight application.

• Add below code to userdetails.xaml file to create just show welcome message along with the logged in user name.


<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="Welcome: " x:Name="showtext" FontSize="20"<>/TextBlock>
<TextBlock Text="UserName" x:Name="userName" FontSize="20"<>/TextBlock>
</StackPanel>
</Grid>



• Modify the constructer in userdetails.xaml.cs to accept loginName as input and display the same in a Silverlight Textblock.


public userdetails(string loginName)
{
InitializeComponent();
userName.Text = loginName;
}



• UserDetails XAML preview looks like below.



• Create public properties PageName and LoginName in Page.xaml.cs file to store the current pagename and logged in userName. Also create two constructers in page.xaml.cs one to accept pageName as input and other to accespt pageName and LoginName as input.


public Page(string pageName)
{
InitializeComponent();
PageName = pageName;
LoadPage();
}
public Page(string pageName,string loginName)
{
InitializeComponent();
LoginName = loginName;
LoadPage();
}
public string PageName
{
get;
set;
}
public string LoginName
{
get;
set;
}



• Create a new method in Page.xaml.cs file (LoadPage()) and call this after initializecomponent in Page constructer. In this function we need to load Silverlight user control based on the PageName property. If PageName property is set to “Login” the Login.xaml file will be loaded and when PageName is set “ShowDetails” then ShowDetails.xaml file will be loaded by passing loginname as input to constructer. And this PageName/LoginName property values will be added as InitParameters when we are adding Silverlight control (.xap) in .apsx page as explained in next point.



public void LoadPage()
{
if (PageName == "login")
{
this.Content = new login();
}
else
{
this.Content = new userdetails(LoginName);
}
}



• Now in UserLogin.aspx add Register tag with tag prefix to add reference to System.Web.UI.SilverlightControls namespace. And then add ScriptManager and Silverlight control to display Silverlight content by pointing to .xap file. Here add InitParameters property to Silverlight control as InitParameters="PageName=login“ to set PageName=login attribute.


<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
TagPrefix="asp" %>





<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>
<div style="height: 100%;">
<asp:Silverlight ID="Xaml1" runat="server" InitParameters="PageName=login" Source="~/ClientBin/SilverlightFormsAuth.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
</div>



• In the similar manner add the same to showdetails.aspx page and set InitParameters as "PageName=userdetails,loginName=" + loginName from backend code in Page_Load of userdetails.aspx.cs page where loginName value is set as HttpContext.Current.User.Identity.Name to get the user name stored in the Authentication cookie.


<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>
<div style="height: 100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightFormsAuth.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
</div>






protected void Page_Load(object sender, EventArgs e)
{
string loginName = HttpContext.Current.User.Identity.Name;
Xaml1.InitParameters = "PageName=userdetails,loginName=" + loginName;
}



• These InitParameters are read and passed to Page.xaml file in App.xaml file in Application_Startup as below.



private void Application_Startup(object sender, StartupEventArgs e)
{

if (e.InitParams.Count > 1)
this.RootVisual = new Page(e.InitParams["PageName"], e.InitParams["loginName"]);
else
this.RootVisual = new Page(e.InitParams["PageName"]);
}




• Now when the user tries to access showdetails.aspx page by default he will be redirected to userlogin.aspx page showing login.xaml page. Here the user will enter UserName and Password and then clicks on the Login button. To call javascript function on Login button click by passing username and password as input, add the following code in the login.xaml.cs by adding namespace System.Windows.Browser



private void bntLogin_Click(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke("loginUser", UserName.Text, Password.Text);
}



• Add the below javascript function in UserLogin.aspx page which gets User entered login name and password as input. And now we can make use of Ajax ScriptMethods and call the Scriptmethod to validate the login details with database. For this we need to set EnablePageMethods property of ScriptManager to true.



<script language="javascript">
function loginUser(username, password)
{
PageMethods.userlogin(username, password, OnSucceeded);
}

function OnSucceeded(result, userContext, methodName)
{
if (result)
{
if ("<%=ReturnURL %>" != "")
{
window.location = "<%=ReturnURL %>";
}
else {
//some other default page.
window.location = "/Forms/ShowDetails.aspx";
}
}
}

</script>


• Need to create a static web method by adding reference to System.Web.Script.Services, System.Web.Security and System.Web.Services namespaces in which we will get username and password as input, which will be validated across Database and returns boolean value if logged in details are correct along with creating Forms Authentication cookie as below. The ReturnURL which we will get in the query string (In this case its Forms/showdetails.aspx) is stored in a public variable.



public string ReturnURL
{
get
{
if (Request.QueryString["ReturnUrl"] != null)
{
return Request.QueryString["ReturnUrl"];
}
else
{
return "";
}
}
}

[WebMethod, ScriptMethod]
public static bool userlogin(string userName, string password)
{
if (FormsAuthentication.Authenticate(userName,password))
{
FormsAuthentication.SetAuthCookie(userName, false);
return true;
}
return false;
}



• In the CallBack javascript fuction after calling the PageMethod userlogin we will read ReturnURL and redirect to this User requested URL.

function OnSucceeded(result, userContext, methodName)
{
if (result)
{
if ("<%=ReturnURL %>" != "")
{
window.location = "<%=ReturnURL %>";
}
else {
//some other default page.
window.location = "/Forms/ShowDetails.aspx";
}
}
}


• Finally Set Web project as a default project and set showdetails.aspx page as a default page, Then run the application enter userId as ‘anil’ and password ‘anil’ as set in the Web.config file.




This will work exactly as Forms Authentication Works in normal ASP.NET web application.

Download the Sample Code here.



Happy coding with Silverlight..

Submit this story to DotNetKicks

6 comments:

Anonymous said...

Hi,

When I try to run this project in VS2008 i get the following error : Unable to attach to process. A debugger is already attached.

Could you please help me out. Its urgent. Thanks.

Anonymous said...

Hi,
Given example is really good. I downloaded the code and run it...its working fine...but when i tri
ed it by my own...its giving the following error :
The type or namespace name 'SilverlightControls' does not exist in the namespace 'System.Web.UI' (are you missing an assembly reference?)
i am also unable to find system.web.silverlight refrence....could you solve my problem...thanks

Anil said...

Try using Silverlight web project template in Visual Studio 2008

Anonymous said...

Wouldn't it be saver to use also two different XAP's and place the XAP with the userdetails also in the protected folder?

Anonymous said...

it dont work with firefox ...

Anonymous said...

why is there no straight and easy way of letting me write my own authentication class or extend the extension - i wonder. i alwayz hav to do some fancy tricks to get what i want in asp done.

Post a Comment

Post your comments/questions/feedback for this Article.

 

Latest Articles