Custom Access Denied Page in SharePoint 2013

In SharePoint 2010, it was quite easy to tell SharePoint to use a custom access denied page that you developed and deployed to the farm instead of the out of the box page. There are many reasons that lead to the need for this, such as changing the text of the message or adding a more dynamic page / form to collect information from the user or perform some other function. Once you build your page and get it deployed, all it took was a call to SPWebApplication.UpdateMappedPage or the PowerShell cmdlet Set-SPCustomLayoutsPage with the proper parameters and you’re off and running. Plenty of posts on the Internet on doing that task so I won’t cover it here.

What I do want to cover, however, is where things stand on this topic with 2013. As of the writing of this post, you can’t do this. Although the same UpdateMappedPage method and Set-SPCustomLayoutsPage cmdlet exists in 2013, there is an identified bug in the product related to the property. The custom location can be set using either of these methods, but SharePoint will not recognize them and will continue to use the out of the box accessdenied.aspx page. I’ve verified this through a Microsoft internal distribution group as well as a support case submitted by me on behalf of one of my clients. Hopefully this gets fixed in a hotfix or CU, but until then you are out of luck.

There are a couple other options, though.

  1. Supported Option:  Create an HTTP handler (covered a bit in this forum post) to intercept each request and redirect to your custom page if the server is sending the user to the out of the box accessdenied.aspx page. I don’t like this since it adds overhead to every SharePoint page request.
  2. Unsupported Option, proposed by a co-worker of mine, Lester Sconyers:
    1. Add a delegate control to the error.master like below. (I know, I know. Not ideal)
    2. <SharePoint:DelegateControl runat=”server” ControlId=”MyDelegate” AllowMultipleControls=”true” />

    3. Create a user control to be deployed to _controltemplates
    4. Create an elements.xml file which will add the control to the delegatecontrol.
    5. <ControlId=”MyDelegate”ControlSrc=”~/_controltemplates/15/mycontrols/redirect.ascx”Sequence=”1″ />

    6. On the pageload method of the user control check the request url. If it is for access denied, redirect users to your custom page

A nice option for those who are ok with modifying out of the box pages.

I should note that the UpdateMappedPage and Set-SPCustomLayoutsPage are not just for access denied. They are used for the following pages:

  • AccessDenied
  • Confirmation
  • Error
  • Login
  • RequestAccess
  • Signout
  • WebDeleted

I haven’t tested to see if changing the setting for pages other than AccessDenied are respected or not.

20 thoughts on “Custom Access Denied Page in SharePoint 2013”

  1. Hi,

    I have had the same experience with Error and AccessDenied. My custom Login and Signout pages work great though.

    Thanks for the post!

    1. Wes, good to know. I have gotten a custom login page to work as well, although not using this method. I set the login page through the web application settings in Central Administration. I also noticed after doing that, checking Get-SPCustomLayoutsPage for the login page didn’t reflect my update, even though it was working. I’d be interested in hearing which method you found to be successful.

      1. Hi Ryan,

        The feature receiver for my custom Login page uses the following snippet:

        iisSetting.ClaimsAuthenticationRedirectionUrl = new Uri(“~/_layouts/15/sampleProject/login.aspx”, UriKind.Relative);
        spWebApplication.Update();

        If you check Get-SPCustomLayoutsPage it does not display the custom page Url for the Login (as you stated above).

        1. Ok, same behavior I observed. Thanks!

  2. Sad to say I had to open a support ticket with Microsoft regarding the Custom Sign Out 🙁

    The SharePoint product group is currently investigating the issue.

    Cheers.

  3. Hi,

    I just received confirmation from the product group that this issue is scheduled to be addressed in the SharePoint 2013 Feb ’14 timeframe. The fix covers both AccessDenied and SignOut pages.

    Cheers.

    1. Thanks for the update, Wes. I’ll keep an eye out!

    2. Rodrigo says:

      Can you give me the url reference which microsoft talks about this issue and the possible date for solution?

      thanks

    1. I haven’t seen one yet.

  4. Maqsood Ashiq says:

    Hi Ryan,

    We have installed Microsoft SharePoint Server 2013 Service Pack 1 (SP1), but still this issue persists, any information about it?

    -Thanks.

  5. Deepu says:

    Hi Ryan,

    I think the latest CU from Microsoft released on May 7th has fixed this issue. Visit here for more details.

    Thanks.

    1. Thanks Deepu, that seems to be the case. I’ve seen others successfully deploy custom access denied pages, although I haven’t confirmed it personally.

      Here’s the link to info on the April 2014 CU that fixes the issue: http://blogs.technet.com/b/stefan_gossner/archive/2014/05/08/april-2014-cu-for-sharepoint-2013-has-finally-been-released.aspx

  6. Senthilkumaran says:

    Hi Ryan/Deepu, Thanks for the update.
    We wanted to check with you that April 2014 CU fixed custom access denied page? is there any other configuration or settings need to be done after CU upgrade?
    Since we patched this CU at different environments ensured it was upgraded successful, but we didn’t get any luck in this issue :(.. its still taking us to the OOB Access Denied Page not to our Custom Access Denied page (the issue still persist).

    Any help or support is appreciated..
    Thanks,
    Senthil

  7. Paul Ewert says:

    An ideas, Ryan, what those people did to get it working? We’ve installed the July 2014 CU (and SP1), but I’m not seeing any change. It’s ignoring the path given by Get-SPCustomLayoutsPage for both AccessDenied and Signout (quite likely other or all page types are affected).

    1. Paul Ewert says:

      No ideas why, but the CU fixing this issue kicked in after a few days. I’m certainly not going to complain–much. At least it’s now working! Well, working for the most part. Sites using the 2013 UI are getting the custom Access Denied page, but sites using the 2010 UI are not. Can’t find anything about this dichotomy. Not even finding how it is SharePoint substitutes your custom page with the out-of-box page when the URL isn’t changing when it does work (SP2013 UI).

      1. Paul Ewert says:

        As it turns out, the question about the UI is quite important. If your site is using the 2013 UI, you’re fine: By default Get-SPCustomLayoutsPage, Set-SPCustomLayoutsPage, and Microsoft.SharePoint.Administration.SPWebApplication.UpdateMappedPage(…) work with a CompatibilityLevel = 15. That’s right, CompatibilityLevel! There is an undocumented parameter on these cmdlets and method (presumably added with the April 2014 CU). If your site is using the 2010 UI, you’ll need to specify a CompatibilityLevel = 14 when using these cmdlets or method. Just be sure to give the correct path for the correct hive/UI: The path must start with “/_layouts/15/” for the 2013 UI (CompatibilityLevel = 15, or omitted), and must start with “/_layouts/” for the 2010 UI (CompatibilityLevel = 14).

        Just be sure you deploy your custom pages to both hives. For me, I had packaged the pages in a farm solution. Just needed to deploy the pages to both hives by specifying CompatibilityLevel = All when executing Install-SPSolution. (Unfortunately, there’s no way to do this from the deployment in CA.)

        Of course, this means you are able to have different pages for each of the mapped pages for each of the hives. Want one Access Denied page for the 2010 UI and a different one for the 2013 UI? No problem!

        1. Hi Paul, glad to hear you were able to get it figured out. And thanks for sharing the info on the differences for UI, good stuff!

  8. Is there a way to do customize the Access Denied and PageNotFound pages WITHOUT access to the server?

  9. Great article. Thanks for it.
    Just one correction on point 1 of your solution you mention a custom handler should be used. I think you meant custom HttpModule 🙂
    Other than that, good article

Leave a Reply

Your email address will not be published. Required fields are marked *