Using a different master page for authenticated users in SharePoint

So, let’s say you’re building a public facing internet site using SharePoint and you want to conditionally hide content from anonymous users viewing your site from the internet.

Traditionally, you would use either a SPSecurityTrimmedControl or a LoginView.

In this post I’m going to show you yet another way to accomplish sort of the same thing (or something that you could combine with the above mentioned approaches to achieve the desired effect).

One of the things that you’ll probably want to “hide”, or in practice not render at all, from anonymous users is the ribbon. So from my point of view that shouldn’t even have to be in the master page for anonymous users and thereby reducing the complexity of that master page markup (also for the developer).
This will require me to use an alternative master page that is rendered for users who are authenticated to show them the ribbon so that they can work with page (edit, check-in, publish, and such).

You can download the source code from my github repo.

 

The authenticated Master Page approach

What you’ll need:

  • Custom Master Page/s
  • Custom Page Layout/s

But since this is public facing internet site I’ll assume that you’ll want that anyway.

Public.com

image_thumb4

So for the purpose of demoing this I’ve setup a web application called public.com

public.com is hosted on an internal url (http://private.public.com) which is setup to not allow anonymous users. I’ve created an extended web application (http://www.public.com) that allows anonymous users (or should I say enabled for anonymous access since the actual allowing of anonymous users is configured on the site collection)

image_thumb8

So OOB both these “sites” (yes, same site but with different urls and authentication) show the ribbon, although the anonymous one only shows a “sign in” option. Well, we don’t want www.public.com to show any ribbon at all.

Master Pages

image_thumb12

You’ll need two master pages. We’ll look at how these master pages look in short but for now a feature provisions two modules with a master page in each of these modules.

Module Element

image_thumb15

The only difference between these modules is that “private.master” is instructed to be hidden (PublishingHidden=true). So as you can see, after activating the feature, only public.master shows up as an option in the SharePoint picker. That’s by purpose.

public vs. private

So, what’s difference between these master pages then?
Well, I’m not going to go through all of the markup but the basic idea is that public.master has as little of the SharePoint stuff as possible and private.master will include that so the admins can work with the site in a normal way.

Here’s a brief look a the public.master:

image_thumb19

So things to notice:

  • Head tag doesn’t include any CustomJsUrl or ScriptLinks or any of that stuff.
  • It still includes the placeholders that we are used to (notice PlaceHolderAdditionalPageHeadfor example)
  • Body content is also pretty clear, no ribbon.
  • Body content includes two custom placeholders (PlaceHolderBeforeMain and PlaceHolderAfterMain). We will use these shortly.

Now let’s look a private.master:

image_thumb22

private.master inherits from (or uses public.master) using the MasterPageFile attribute.

image_thumb28

We start by overriding PlaceHolderAdditionalPageHead from public.master and start to insert a bunch of SharePoint stuff. Important thing to notice is that we repeat the placeholder again as a last option to enable page layouts to insert their custom stuff into the head tag.

image_thumb31

Next up is to insert the ribbon. We’ll do that before the PlaceHolderMain so using the PlaceHolderBeforeMain from public.master is the place to do that.

Next up is to repeat the PlaceHolderMain placeholder (important) since we’ll want content from page layouts here.

And finally add some things after the page content like the developer dashboard using the PlaceHolderAfterMain placeholder.

Page Layout

So, I briefly mentioned that you’ll need custom page layouts to make this work. Here’s why.

image_thumb36

In order to alter the master page based on whether or not the user is authenticated we’ll need a custom page layout. In the image above you can see that I’ve created a page layout (welcome-default.aspx) which is a custom page layout that can be used for welcome pages (the content type).

In the page directive for that page you can see that it inherits (code behind) from PageLayoutBase (normally a page layout would inherit from PublishingLayoutPage which is a SharePoint class).

That’s actually a class that I’ve created and that’s the class that does all the magic. Now let’s have a look at it:

namespace Public.SharePoint.PageLayouts
{
    public class PageLayoutBase : PublishingLayoutPage
    {

        protected override void OnPreInit(EventArgs e)
        {
            // this sets the MasterPageFile to public.master (if the web has been setup to use that)
            base.OnPreInit(e);

            try
            {
                if (SPContext.Current.Web.CurrentUser != null && this.MasterPageFile.EndsWith("public.master", StringComparison.OrdinalIgnoreCase))
                {
                    //the user is logged in and the site uses the public.master

                    // change it to private.master
                    this.MasterPageFile = SPUrlUtility.CombineUrl(SPContext.Current.Site.ServerRelativeUrl, string.Concat("_catalogs/masterpage/", "private.master"));

                }

            }
            catch { } // this is an error trap, don't do anything
        }
    }
}

So, if you want to set the master page for a page (asp.net) using code you’ll need to override OnPreInit. This is actually what SharePoint does internally and reads the value from the SPWeb.CustomMasterUrl property.

What I’m doing is just checking if we have a user (i.e. if the user has authenticated) plus if the page uses the public.master, then I’ll change it to use private.master

This is just an example of how you could accomplish this. There’s of course a couple of hardcodings in there that could be abstracted an such.

Also, now it checks if the user is authenticated. Another option could be to check if the IIS settings instead…like this:

image_thumb38

And the end result?

image

Here’s how the same page looks viewed with the public.master and with the private.master (which changes dynamically)

And in summary

You could still combine this approach with login views and SPSecurityTrimming if you’d want that. For me at least, this is a bit cleaner approach than just “hiding” content from anonymous users. The markup looks better using this approach.

Enjoy!!

, , , ,

  1. #1 by François on January 1, 2012 - 22:22

    A very neat idea, thank you very much for detailing it in a clear way. I’ve never used the MasterPageFile and I’m glad to read that this seems to work flawlessly.
    Greetings from Belgium.

  2. #2 by Rikard on October 23, 2012 - 10:30

    Once again your blog is an excellent reference point.. 🙂

    /Rikard

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: