Displaying a login dialog based on page attributes in Silverlight 3

by StefanOlson 19. June 2009 15:44

Update: The latest version of the code is available for download here. This page has been re-written for the .net ria Services July CTP.

One of the feature requests I described in my post Issues with the Silverlight Navigation architecture was the ability to use an attribute to declare the required roles to display a particular page.  e.g:

[RequiresAuthentication]
public partial class CategoryPage : Page

Unfortunately this is not part of Silverlight 3, so I set about implementing it myself based on the custom URI mapper I have developed in previous posts.

Let me introduce the AuthenticatingUriMapper!  You can download the source code and example here.

All source code described below is part of the sample.  It shows how you can provide attributes on a page to automatically have a login dialog displayed when navigating to it if required!  The sample is based on the Silverlight business application template, that is installed as part of the .net RIA services.  Sample requires the .net RIA services to be installed.

e.g:

image

Using it couldn't be simpler! Just like the custom URI mapper, you add it as your uriMapper (in the Frame or as a StaticResource):

<Navigation2:AuthenticatingUriMapper DefaultPage="/Views/EmptyPage.xaml">
    <Navigation2:CustomUriMapper.CustomUriMappings>
        <UriMappingNavigationSample:AboutBoxRoute/>
        <routing:CustomRoute/>
    </Navigation2:CustomUriMapper.CustomUriMappings>
</Navigation2:AuthenticatingUriMapper>

See my previous post for details on the default page attribute used above.

Then in your mainpage constructor, you tell it about the frame and handle any authentication requests:

public MainPage()
{
    InitializeComponent();
    this.loginContainer.Child = new LoginControl();
    
    (ContentFrame.UriMapper as AuthenticatingUriMapper).Frame = frame;
    (ContentFrame.UriMapper as AuthenticatingUriMapper).AuthenticationRequired += MainPage_AuthenticationRequired;
}

In the MainPage_AuthenticationRequired function, you simply display the login dialog.  We are passing the event arguments so that later on, when login has been completed, we can verify , that , the new login credentials are valid for the page the user wishes to go to.

void MainPage_AuthenticationRequired(object sender, AuthenticationRequiredEventArgs e)
{
    LoginWindow dialog = new LoginWindow { AuthenticationRequiredEventArgs = e};
    dialog.Show();
}

Then, in the pages we wish to require authentication for, add either of the following two attributes:

[RequiresAuthentication]
public partial class UserPage : Page

Or, if you need specific roles:

[RequiresRoles("Administrator")]
public partial class AdminPage : Page

In the login dialog we can make some changes to make use of the AuthenticationRequiredEventArgs.

When the login is successful , we need to verify that now that the user is logged in they passed the authentication requirements of the page they are going to . Here's how we do this:

else if (loginOp.LoginSuccess)
{
    DialogResult = true;
    if (AuthenticationRequiredEventArgs != null)
    {
        AuthorizationAttribute attribute = AuthenticationRequiredEventArgs.RecheckAttributes();
        // verify the newly logged in account meets the requirements of the page we are visiting
        if (attribute == null)
        {
            // now we know we've passed the requirements, we can navigate to the page the user 
            // originally wanted to go to
            AuthenticationRequiredEventArgs.Frame.Navigate(AuthenticationRequiredEventArgs.UnmappedUri);
_authOp=null;
DialogResult=false; return; } if (attribute is RequiresRolesAttribute && RiaContext.Current.User.IsAuthenticated) { MessageBox.Show("This account does not have authorization to view the page you are requesting.");


DialogResult = false;
_authOp=null;



return; } } }

For this  demo we're going to display a message if you are logged in using an account that doesn't have the appropriate level of credentials. For example, if you need administrator credentials to access a page but don't currently have them we wish the login dialog to indicate that.  In the picture below, we are currently logged on under the user account, but we actually need administrative privileges, so you can see that a message is displayed to that effect:

image

The code to achieve this is pretty simple, We just display the yellow box if appropriate when the event arguments are set:

private AuthenticationRequiredEventArgs _authenticationRequiredEventArgs;
public AuthenticationRequiredEventArgs AuthenticationRequiredEventArgs
{
    get { return _authenticationRequiredEventArgs; }
    set { _authenticationRequiredEventArgs = value;
        if (AuthenticationRequiredEventArgs.AuthorizationAttribute is RequiresRolesAttribute && RiaContext.Current.User.IsAuthenticated)
        {
            _RoleRequired.Visibility = Visibility.Visible;
        }
    }
}
You can try this all out yourself by downloading the source code and making use of it in your own applications!

…Stefan

Tags:

Silverlight | .net ria services

Comments

6/23/2009 9:28:48 PM #

Pingback from silverlight-travel.com

Silverlight Travel » Displaying a login dialog based on page attributes in Silverlight 3

silverlight-travel.com

6/29/2009 2:36:15 AM #

This is very cool but....
Wouldn't it be better to not display the links, menu items, buttone, or whatever if the user was not in the correct role? It would seem to be a very anoying application that makes you do something only to find out you don't have required permissions.

Jim

6/29/2009 8:23:33 AM #

@Jim,

In some cases, hiding options that are not applicable would be the right way to do it. However, there are situations where the user may not realize that they have access to this functionality because they aren't currently logged in. So, sometimes it's better to make it clear that the feature is available and ask them to login when they need to access it.

An example of this is on http://www.trademe.co.nz/, where the my trade me link requires you to login to access this area of the site.

...Stefan

StefanOlson

7/30/2009 9:19:47 AM #

Hi, Stefan:

I like this article, but I download the source cdoe and found it didnot compatible with RIA July Release, any hints to work with RIA July release, thanks,

jon

8/2/2009 3:40:27 PM #

There are changes required to work with the July release.  I had to make so many changes to get my project working that I'd entirely forgotten I've made changes to the uri mapper. I will upload an update in the next few days.

…Stefan

StefanOlson

8/3/2009 9:55:11 AM #

I have now uploaded an updated release to work with the July CTP of the .net RIA services. You can find it here: www.olsonsoft.com/.../...or-Silverlight-3-RTW.aspx

...Stefan

StefanOlson

2/18/2010 7:15:34 PM #

Updates to the Custom and Authenticating URI Mappers for Silverlight 3 RTW

Updates to the Custom and Authenticating URI Mappers for Silverlight 3 RTW

Stefan Olson's Blog

5/11/2010 4:53:32 PM #

I'm a TOTAL silverlight newbie. Your post seems to discuss the exact problem that I am trying to solve, but I'm using the Silverlight 4 in VS2010 and unfortunately your examples won't build. Do you have any plans to update them for the latest releases?

Regards

Steve

SteveI

Add comment




biuquote
  • Comment
  • Preview
Loading



About the author

Stefan Olson is the Managing Director of Olson Software.  He has been developing software using Microsoft Technologies for nearly 20 years.

He is currently working on building the next generation Virtual Tour software in WPF and Silverlight for www.palacevirtualtours.com.

Tag cloud