Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have a set of application pages stored in the _layouts virtual directory, that I'd like to secure, in order to prevent unauthorized access to the pages, as well as prevent certain actions from being executed.

My authorization structure consists of several AD Security Groups (although this is somewhat flexible, and I could create the groups in SharePoint), each of which, will have a set of application pages that they can access, and actions within each page that the user can execute. Something along these lines:

User Group | Access to Application Pages | Actions
-----------+-----------------------------+-----------------------------------------
A          | Page1.aspx, Page2.aspx      | Page1.aspx->Button1, Page2.aspx->Button2
-----------+-----------------------------+-----------------------------------------
B          | Page1.aspx                  | Page1.aspx->Button3
-----------+-----------------------------+----------------------------------------- 

An article on MSDN, suggests using SPRoleDefinitions, and verify at Page_PreLoad, for example, if a user has the required roles to access the page, and if not, redirect him to accessdenied.aspx. The same could be done for the actions within each page. However, this solution would require me to drop AD Groups, and store users and groups in SharePoint.

Another solution would be to add location tags to the web.config with allow and deny, although this solution doesn't solve the problem of preventing actions within each page from being executed.

  <location path="_layouts/Page1.aspx">
    <system.web>
      <authorization>
        <allow roles="AD\A,AD\B" />

How can this type of scenario be accomplished? What is the typical configuration used in SharePoint solutions for this use case?

share|improve this question
    
Why are you using application pages? For you scenario it seems to me, that it would be easier to have site pages and secure them by "item level security" (in which you could use your AD groups). However, to secure the actions within the pages you have to code something on your own. –  marco May 11 '12 at 17:44
    
@marco: Because it's essentially an aspx custom application built on top of SharePoint. –  João P. Silva May 11 '12 at 23:01
    
You can still divide the aspx application into usercontrols and place these user controls on a page layout and create site pages using these layouts. Also is there a specific reason why you want to use the aspx application AS-IS, without converting it into a proper integrated SharePoint App. –  Jomit May 14 '12 at 21:27
add comment

2 Answers 2

I've read an article on MSDN, that suggests using SPRoleDefinitions, and verify at Page_PreLoad, for example, if a user has the required roles to access the page, and if not, redirect him to accessdenied.aspx. The same could be done for the actions within each page. However, this solution would require me to drop AD Groups, and store users and groups in SharePoint.

This is what we do on a large number of our apps. For each AD group make a Sharepoint group, and put the AD group in the sharepoint group as the only "user". After that everything else in that paragraph should work out just fine.

share|improve this answer
1  
Point of clarification, those AD groups must be Security groups, not Distribution lists, in order to be imported and used in SharePoint groups. –  PirateEric May 11 '12 at 20:49
    
@Servy: Thank you very much for your feedback. I have a question though. By putting the AD group as a member of the SharePoint group, this will give access to SharePoint for all users that belong to the AD group, which is perfect. However, when authenticated with such a user, will the SPUser object have access to the SharePoint Group that is the "parent" of its AD Group? Or will I have to run a custom query to the AD to find out this mapping? Thanks. –  João P. Silva May 11 '12 at 23:25
    
@John I don't think that those relationships will be maintained, no. –  Servy May 12 '12 at 3:25
add comment
up vote 1 down vote accepted

I ended up with a solution loosely based on the concept of Role Definitions presented here. Here's a brief description of how this was implemented.

For every AD Security Group, create an SPGroup, whose sole member is the corresponding directory group. Then, create an SPRoleDefinition for each required page access, e.g., Page_1.aspx - Read, and an SPRoleAssignment to link the roles to the sharepoint groups. This can be easily done within a bootstrap feature receiver.

After that, roles can be accessed using the AllRolesForCurrentUser property of SPWeb.

Then, in order to hide the navigation links from the menu, preventing users who do not have the required roles from viewing them, I implemented a custom SiteMapProvider, overriding the IsAccessibleToUser, to use the roles obtained in the aforementioned property. Something along these lines (simplified; in a production environment, you'd use caching, etc.):

    public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
    {
        var roles = node.Roles.OfType<string>();
        if (roles.Contains("*")) {
            return true;
        } else {
            SPWeb web = SPContext.Current.Web;
            SPRoleDefinitionBindingCollection allUserRoles = web.AllRolesForCurrentUser;
            foreach (string role in roles) {
                SPRoleDefinition requiredRole = web.RoleDefinitions[role];
                if (allUserRoles.contains(requiredRole)) {
                    return true;
                }
            }
            return false;
        }
    }

Finally, in order to actually prevent users from accessing the page, make every ApplicationPage extend from a base page, whose OnInit event basically verifies that the current site map node is accessible to the user, and if not, redirects the user to the access denied page:

    protected void Page_Init(object sender, EventArgs e)
    {
        if (SiteMap.CurrentNode == null) {
            SPUtility.Redirect(SPUtility.AccessDeniedPage, SPRedirectFlags.RelativeToLayoutsPage,
                this.Context, "ReturnUrl=" + HttpUtility.UrlEncode(Context.Request.Url.AbsoluteUri));
        }
    }
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.