Authorization Sample 101


This is an introduction to the Authorization Sample for RIA Services.

Authorization is implemented using attached properties. This means you can mark nearly everything in your xaml files with Authorization properties. In most cases, elements will be prepared for authorization and hidden until the framework determines access to that element is allowed. This section shows the basic markup and talks about how to use it.

For each sample, I’m assuming the following xml namespace has been added to the file. I’m using ‘s’ for ‘security’ as well as brevity.

 xmlns:s="clr-namespace:FirstLook.ServiceModel.DomainServices.Client.Security;
          assembly=FirstLook.ServiceModel.DomainServices.Client.Security"

RequiresAuthentication

The RequiresAuthentication property can be used to hide an element until the user is authenticated. This snippet will only show the hyperlink to authenticated users.

 <HyperlinkButton NavigateUri="/Accounts"
s:Authorization.RequiresAuthentication="True" />

RequiresRole

The RequiresRole property can be used to hide an element unless the user is in a specified role. This snippet will only show the hyperlink to users in the ‘Administrator’ role.

 <HyperlinkButton NavigateUri="/Accounts"
s:Authorization.RequiresRole="Administrator" />

The RequiresRole property also accepts multiple roles as input. In this snippet, the hyperlink will be shown when the user is in the ‘Administrator’ or ‘Manager’ roles.

 <HyperlinkButton NavigateUri="/Accounts"
s:Authorization.RequiresRole="Administrator,Manager" />

NavigationMode

The NavigationMode property is used to enable authorization-based navigation. It can be applied to a Frame to enable authorization. The following snippet will redirect the user to ‘/Home’ if they attempt to navigate to a page they are not allowed to access.

 <nav:Frame Source="/Home" s:Authorization.NavigationMode="Redirect" />

Each page can simply declare its access rules using the RequiresAuthentication and RequiresRole properties discussed above. This snippet shows a page that can only be accessed by authenticated users.

 <nav:Page s:Authorization.RequiresAuthentication="True" />

[Security Note]

Authorization in Silverlight should only be used for Navigation and UI Customization. For true security, you need to secure your data by adding authorization to your web services. These msdn links describe how this can be done using WCF RIA Services.

http://msdn.microsoft.com/en-us/library/ee707361(v=VS.91).aspx

http://msdn.microsoft.com/en-us/library/ee707357(v=VS.91).aspx

Comments (59)

  1. LOuis says:

    Kylemc : A Hugeeeeeeeeeeeeeeeeeeeeee thank you a lot!  You help me so much!

    ABout a Business Application, when I click to logout (on the right upper), do you know how to redirect to my mainpage.xaml?

  2. kylemc says:

    You can subscribe to WebContext.Current.Authentication.LoggedOut in MainPage.xaml.cs and navigate the ContentFrame to "/Home" whenever it occurs. If you're using this library and using authorization on pages, though, it will do it automatically for you.

  3. Calisse says:

    This is great!!!  I have been pulling my hair out trying to figure out how to do this with VS2010, .net 4 and Silverlight in the predefined Business Application that you can use.

  4. Aleczander says:

    Kyle, great job, just what I was looking for. I have an issue however I'd like your advice on. In my bus app I'm using navigationmode prompt. This is exactly what I want for my registered users home page that can be navigated to from the anonymous homepage. When one actively logs out (with the logout link) while on a registered users' page, the login form popups. Obviously this is unwanted behaviour. How do I combine both navigationmode prompt AND redirection to e.g. the anonymous homepage? Thanks in advance for your help!

  5. kylemc says:

    @Aleczander

    There are two approaches you can use. First, in my authz sample, I'm using active and passive logout (responding to session timeout). This complicates things as you'd only really want to return to the homepage on active logout. Since I'm using the BAT, I could do this by adding redirection to the LogoutButton_Click handler in LoginStatus.xaml.cs. NavigationService.Navigate(…) should work. The second approach is a little easier and works if you're only using active logout. In MainPage.xaml.cs you can subscribe to the Logout event on WebContext.Current.Authentication and navigate the ContentFrame to the homepage.

  6. Naresh says:

    Hi Kyle,

      I have a main page(main.aspx) with a logout button. This mainpage hosts another page postpage.aspx which contains some aspx controls and silverlight content when i click on logout button(which is aspx button) my silverlight content stil remains active and the page is not getting redirected but this is not happening with other pages ? any clue on this……

    Thanks,

    Naresh

  7. kylemc says:

    @Naresh

    Sorry, not much of a clue. You'll have to manually communicate between ASP.NET and Silverlight. The beginning of this msdn article shows how to get started (msdn.microsoft.com/…/cc135987.aspx). When logout is pressed on the main page, your post page will need to trigger a method in your silverlight application that calls WebContext.Current.Authentication.LoadUser(). If you can do that, the silverlight content will pick up the new (anonymous) user data.

  8. shailendra says:

    Hi sir,

    Nice artical.

    After logout applicaiton is not redirecting the user to home page.

    am i missing anything.

    please help !!!

  9. kylemc says:

    @Shailendra

    Take a look at my response above where I answered a very similar question. I'll summarize it again for clarity.

    You have two options:

    1) Redirect in LogoutButton_Click handler in LoginStatus.xaml.cs. The following code should work.

       NavigationService.Navigate("/Home")

    2) In MainPage.xaml.cs, subscribe to the Logout event on WebContext.Current.Authentication. Redirect in the handler with the following code.

       ContentFrame.Navigate("/Home")

  10. shailendra says:

    Thanks..

    it is working superbly ………… 🙂

  11. narkophil says:

    Hello,

    Thanks for this control.

    I'm having a weird problem with it though when using Firefox (everything works fine in Internet Explorer):

    When navigating to a secured View for the first time I'm getting this Error:

    bei System.Windows.Navigation.PageResourceContentLoader.EndLoad(IAsyncResult asyncResult)

      bei FirstLook.ServiceModel.DomainServices.Client.Security.AuthorizationContentLoader.HandleLoadCompleted(IAsyncResult asyncResult)

      bei System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(AsyncCallback userCallback, PageResourceContentLoaderAsyncResult result)

      bei System.Windows.Navigation.PageResourceContentLoader.<>c__DisplayClass4.<BeginLoad>b__0(Object args)

    Caused by: Ein Aufrufziel hat einen Ausnahmefehler verursacht. (~"Call-Target caused an exception")

    After the second call the View works. This is happening even when logging in before navigating to the view. I'm using the "Prompt"-Option on the Navigation-Frame.

    Thanks

  12. narkophil says:

    Ok the bug seems to be specific to the new Firefox Version (3.66, maybe even earlier). With my particular View it is appearing even when the View is not secured. No Problems with IE, Chrome or Firefox 3.59 for that matter. Guess I'll have to wait for a fix from Mozilla.

    Thanks again for your Lib.

  13. James says:

    I would also like to thank you for providing this model for security.  I was hoping that something simular would have been created in Silverlight but was not able to find anything or at least nothing yet.  As soon as I added your FirstLook.* to my project, the application behave the way that I had hope it would.  Once more, that you for providing this information…

    James

  14. Chris says:

    Bravo, great job !

  15. Chris says:

    hello where can i load your librairy ? thx

  16. kylemc says:

    @Chris

    The library is included with the sample (linked above). This link will take you directly to the download page.

    code.msdn.microsoft.com/…/ProjectReleases.aspx

  17. Michael says:

    This is a great library!

    Is there a way to check that a user is in a specific role each time a new View is navigated to? I run a check User.IsInRole("myrole") but the profile doesn't pick up any changes made to the users' roles, e.g. I remove a user from the "administrator" role which should trim some menu items and deny access to certain pages, however this isn't picked up unles the user logs off / on again.

    I also use the annotation [RequiresAuthentication] and [RequiresRole roles…] but this doesn't appear to have any effect.

    Is there a way to resolve this?

  18. kylemc says:

    @Michael

    The answer is not so simple. I think you're asking "If an administrator changes a user's access rights, how does that get checked in the Silverlight application?" The Silverlight application doesn't reload the user's credentials from the server because it has no idea they have changed. This case shows why it's important to protect your data as I describe in the security note above. You could do this manually (using WebContext.Current.Authentication.GetUser()), but the challenge is how to determine if updates have been made.

    There's an alternate question of "If I reload user Roles with logging out and in, how can I update the UI?" The answer there is a bit more advanced so I'll only answer it if you're interested.

  19. Michael says:

    Hi Kyle, you're right in your assumption. I am defintely interested in your alternate question of logging the user out / in. I have been playing around with AuthenticationService.LoadUser() on each page load to force reloading of user roles then manually updating the UI. This could get pretty complicated if my scenario gets bigger.

    However since the AuthenticationService.LoadUser() call is async, the changes are obviously not reflected on that particular page load, but rather the next one or if I catch it on a button click usng the security technique as you mentioned (good practise anyway!).

    Or, is there a way to register an event and use PropertyChangedEventArgs to update the user's roles?

  20. kylemc says:

    @Michael

    One simple solution is that you don't reload role changes. You could detect unauthorized access and ask the user to refresh their application (browser page). It's not the experience you were looking for, but how often will roles be changed while an application is running and what is the harm if they are?

    I think there're two steps to take for an actual solution. First, you'll need to write a custom AuthenticationSource and AuthenticationSourceFactory. In your custom source, you can subscribe to Property/Collection changes to the Roles property on User and re-Authorize whenever something happens. This will trigger the UI to update.

    The second step might be a little trickier. You could write your own page INavigationContentLoader that delays page load until Roles has been reloaded. The downside of that solution is that you'd pay for a delay for an uncommon scenario. An alternative might be to have some periodic refresher that prompts the user for credentials when a page gets disabled.

    I think you can play around until you get the behavior you like best, but it may take a few tries to figure it out. Also, if you have any more questions on the details of this approach, feel free to contact me via this blog.

  21. paul says:

    Hi. When I close the browser and then open a new browser window to display my silvelight app it automatically logins in, even when I say don't remember me in the login box. However, if I don't use the firstlook.dll when I close the browser and reopen the app in a new browser it doesn't automatically login me in. Is this a bug?

  22. kylemc says:

    @paul

    I haven't noticed a bug along those lines before, but I'll take a second look. Also, I can look at your app to see if the issue's there if you'd like me to. Just use the 'Email Blog Author' link above.

  23. Shailendra says:

    Hello sir,

    In my silverlight 4 application I am using the forms authentication and m setting the role of the user after authentication to administrator this is working fine.

    But after setting the RequiresRole property in XAML as below s:Authorization.RequiresRole="Administrator,Manager"

    its not working …..

    Please help me by your guidance …

    Thanks in Advance

    Shailendra

  24. paul says:

    Sorry. It was my mistake. I've discovered that if there are two browser windows open on a pc and you login into an app via one browser using forms authentication and set the authentication cookie not to persist, then shut the browser window (without logging out), it is then possible to use the other browser to log straight back into the application. In other words the authentication cookie is shared between browsers instances. I don't like this behaviour as it less secure. I've found using sliverlight in OOB mode the authentication cookie isn't shared.

    Anyway, my fault and thanks for you authentication component. Hopefully microsoft will build this functionality in future releases.

  25. kylemc says:

    @paul

    I'm glad you figured it out. RIA Services authentication uses ASP.NET authentication by default. I don't remember all the options off the top of my head, but it's a very configurable system. Here's a good place to start to see if you can get the behavior you want.

    msdn.microsoft.com/…/eeyk640h.aspx

  26. mwint says:

    Hi,

    I'm having issues with this framwork in my SL4 Bus App. Bascially, I have everything working, except for the [RequiresRole] attribute in the MembershipService. When this is applied, I get an Access Denied Error thrown whilst debugging. If I let the app run as normal, the TimeoutHelper takes overs, fire LoadUser(), and the app logs out every time.

    If I remove the [RequiresRole("Administartor")] attribute, everything works fine. Whilst debugging, I found that the ServiceContect.User does not have the info of the logged in user. IsAutheniticated is false, ans the user is displayed as 'Generic'. So, for some reason, even though the client is happy with the current user, the server side is not. The Server side does not know a user is logged in, even though the log in process has completed successfully.

    Any help appreciated.

    Thanks

  27. kylemc says:

    @mwint

    If the server doesn't think you're authentication, then you're not authenticated (regardless of what the client thinks). Typically this happens when you've failed to persist the authentication correctly in your AuthenticationService. I can take a look at your service if it would help. Just use the 'Email blog author' link above and I'll email you back.

  28. JimD says:

    Kyle, I must be a complete idiot as I have added both the namespace and the RequiresAuthentication exactly as in your example and i get this build error…

    I must have missed SOMETHING but i cannot see what it is 🙁

    Error 1 The property 'RequiresAuthentication' does not exist on the type 'HyperlinkButton' in the XML namespace 'clr-namespace:FirstLook.ServiceModel.DomainServices.Client.Security; assembly=FirstLook.ServiceModel.DomainServices.Client.Security'. C:UsersAdministratordocumentsvisual studio 2010ProjectsSilverlightExperimentSilverlightExperimentMainPage.xaml 48 59 SilverlightExperiment

  29. kylemc says:

    @JimD

    Make sure you're including the 'Authorization' part in 's:Authorization.RequresAuthentication'.

  30. streaky says:

    After login, How can i redirect the page depending on type of Auth – Role?

  31. kylemc says:

    @streaky

    It depends on what your design is, but an easy way to do it would be to add a handler to the WebContext.Current.Authentication.LoggedIn event. In the handler you can navigate to the correct page.

  32. Raymond says:

    sir,

    I have just gone through the sample you provided but I do not know where you got the MembershipServiceUser class utilised within MembershipService. I assumed you created it but when I did right click, go to definition, I see an Auto generated file. Please how can I create a service like yours (MembershipService) and utilise a class (MemberShipServiceUser) that just seem to get injected into the autogenerated file, yet I know all the members that the class should have. I assumed that the service had to be receiving entities from an entity data model but no such data model was available.

    thanks,

    Raymond

  33. kylemc says:

    @Raymond

    It's defined on the server and then generated on the client. Take a look at "AuthorizationSampleAuthorizationSample.WebServicesMembershipService.cs" in the sample.

    Also, take a look at this post where I describe the MembershipService a little more.

    blogs.msdn.com/…/using-asp-net-membership-in-silverlight.aspx

  34. Raymond says:

    I have found it.

    thanks,

    Raymond

  35. streaky says:

    thanks kylemc… that wokred.  I just didnt realize how exactly to hook it up at first being new to it all.  But I did get it working a couple days ago.. thanks for your help.

  36. Raymond says:

    Hi Kyle,

    following your suggestion on navigation from LoginStatus.xaml.cs, I did this:

    NavigationService.Navigate("/Home"); but found out that the Navigate function was not available. I had to do

    NavigationService ns =new NavigationService();

    ns.Navigate("/Home"); to get it to work. but I understand that creating a new Navigation service class would mean that the frame would not have this navigation in the history since it uses a different navigation service. did you mean that a new NavigationService should be created or am I missing something?

  37. kylemc says:

    There's a NavigationService property on controls extending Page. From most controls you should be able to find either the containing Page or Frame using the FrameworkElement.FindName method.

  38. Raymond says:

    Please could you show me how to find the containing page or frame for the LoginStatus as i still have not got it.

    thanks,

    Raymond

  39. kylemc says:

    @Raymond

    It should be something like this.

    Frame contentFrame = (Frame)this.FindName("ContentFrame");

  40. Raymond says:

    Ok. Thanks. I have just inserted the line into a program I am working on and everything is OK.

    Thanks,

    Raymond

  41. nm says:

    Hi,

    this is great library, but i have one problem. On one page it working excellent, but on another it throws me an error:

    There is no dependency property with the name 'VisibiltyProperty' on the target of type 'System.Windows.Controls.Button' to bind to.

    The xaml part looks like:

    <Button… sec:Authorization.RequiresRole="Admin" sec:Authorization.TargetProperties="Visibilty" />

    Do you have any idea?

    Thanks in advance

    Best regards

  42. nm says:

    Hi,

    everything works fine. It's my mistake.

  43. Windows Authentication says:

    Hi,

    first of all great solution!

    can I use it with Windows Authentication?

    I guess that I must set the NavigationMode always to "Redirect"…

    Right?

    Thank you!

  44. kylemc says:

    @Windows Authentication

    Yes and Yes. Hope it helps.

  45. Mike says:

    This is awesome!  Thank you so much for posting this series, I've been looking for something like this for a while!  I've literally just downloaded and have not gotten any further than adding a few attributes just like in the 101 word document.  I've already noticed an odd behavior…if I require a role on a navigation page and set the navigation mode to redirect, it appears that it works and redirects me to the "Home" page, but it also appears that the page I was redirected away from loads and will run in the background, hidden so to speak.  Is this expected behavior?

  46. kylemc says:

    @Mike

    I think I would expect the first Page to get instantiated, possibly loaded, but not navigated to (Page.OnNavigatedTo). This is mostly due to how the code leverages the default page loader. For your pages, I would recommend waiting for the OnNavigatedTo method to get called before performing actions like loading data or memory-intensive processing.

  47. Kyle Parker says:

    Kyle,

    Your blog has been a great help!  Nice work.

    I'm trying to create a RoleService similar to the MembershipService you created.  I need to be able to maintain the users and their roles from inside the Silverlight app.

    First, I assume that I do have to create a new svc to handle the roles, correct?  Second, I'm not really sure what all is needed in the service.  Do you have any pointers?

    Many Thanks,

    Kyle Parker

  48. kylemc says:

    @Kyle

    I tried to describe my approach a bit more in this post (blogs.msdn.com/…/using-asp-net-membership-in-silverlight.aspx). Basically, you can do it in two steps. (1) Figure out what things you want to be able to do using the ASP.NET Roles API and (2) add DomainService operations that can be accessed securely that call into the Role API.

  49. Jim says:

    Kyle,

    I downloaded AuthorizationSample and tried to run it but got this message:

    "There was a failure using the default 'MembershipProvider'.  Please make sure it is configured correctly."

    Can you please advise how to fix it?

    THanks.

  50. kylemc says:

    @Jim

    It's pretty tough to guess what's going on. It might be worth your while to read up a little on ASP.NET Membership (msdn.microsoft.com/…/yh26yfzy.aspx). The authorization sample just relies on the stock SQL providers for membership (msdn.microsoft.com/…/6e9y4s5t.aspx), roles, and profile.

  51. Jim says:

    Thx Kyle.  The poblem was casued by the SQL server stopped running for unknown reason.  However I'm still not able to use your library.  Am I supposed to add FirstLookl…dll to References folder in my silverlight app?  But after I added it, the compilation of the project will fail.  Any advice?

  52. kylemc says:

    @Jim

    The assembly also relies on WCF RIA Services. Is that something you've installed and referenced in your project as well?

  53. visual gaurd says:

    Hi,

    good post…Two-factor authentication (TFA, T-FA or 2FA) is an approach to authentication which requires the presentation of two different kinds of evidence that someone is who they say they are.thanks to share with us….

  54. Visual Guard says:

    Hi,

    nice Thanks  for posting…………….!!!!!!!!!

    ….

  55. Paritosh says:

    Hi Kyle,

    regards for suh a Great post…..

    I have only one doubt that how can i use my custom database with this project? Also i am assuming that you are using aspnetb database, if not can you explain me on how you have used queries with database? i mean in which cs file?

    your response will be geatly appreciated…

    Thanks..

  56. Paritosh says:

    I want to use my own database, can you plz help me to accomplish it?

    Thanks.

  57. kylemc says:

    @Paritosh

    Take a look at the sample here. It shows you how to do AuthN using something other than the aspnetdb.

    code.msdn.microsoft.com/Custom-Authentication-96ca3d20

  58. Paritosh says:

    Hi kylemc….

    Thank you very much for sharing that code that helped me a lot….

    in that code you have got the role of the current user, i want to extend this concept with proviing restriction on accessing methods of with specified role….Similar to "RequireRoles("Manager")"..

    I bit confushed on how to restrict it if my current users role is "Customer"….

    Please help me…and again that or spending your valuable time…

  59. kylemc says:

    As with all the ASP.NET authorization things, if you want to use a custom database, you will need to write a custom provider. For example to use your database with the requires role attribute, you need to write a RoleProvider.

    msdn.microsoft.com/…/8fw7xh74(v=VS.100).aspx