Determine if user can access the requested page?
Asked Answered
S

7

6

I have an ASP.Net website with multiple roles, each with access to a separate directory (i.e. admin users can access /admin, shoppers can access /shop etc), using a shared login page. If someone visits the login page with the return URL set to a directory they do not have access to (e.g. a shopper visits /login.aspx?returnurl=/admin/index.aspx), the user can authentice successfully (the login credentials are valid), but they end up back at the login page (they don't have access to the page they've requested).

How do I pick this up, so I can display a message do the user?

Substantiate answered 26/6, 2009 at 10:55 Comment(0)
S
2

I ended up doing this in the page_load event of the login page:

if (User.Identity.IsAuthenticated)
{
    LoginErrorDetails.Text = "You are not authorized to view the requested page";
}

The thinking being, if an authenticated user ends up at the login page, they have either been sent their as a result of trying to access an page they are not authorized to view, or they have authenticated and then manually gone to the log in page (unlikely).

A further action would be to send the user to the relevant home page whenever they visit the login page, if they are already authenticated.

Substantiate answered 26/6, 2009 at 13:29 Comment(1)
This is only a partial solution, most suitable if you don't have different roles that can access different pages. If you do, you can have a user that's authenticated but still can't access the ReturnUrl, possibly leading to a redirect loop.Enswathe
A
11
UrlAuthorizationModule.CheckUrlAccessForPrincipal()

is what you need to use to test user access to a location (page or folder) ( http://msdn.microsoft.com/en-us/library/system.web.security.urlauthorizationmodule.checkurlaccessforprincipal.aspx )

Amero answered 17/11, 2010 at 18:36 Comment(1)
+1. Example code is available at codeproject.com/KB/aspnet/Redirect-To-Login-Popup.aspx.Cranmer
S
2

I ended up doing this in the page_load event of the login page:

if (User.Identity.IsAuthenticated)
{
    LoginErrorDetails.Text = "You are not authorized to view the requested page";
}

The thinking being, if an authenticated user ends up at the login page, they have either been sent their as a result of trying to access an page they are not authorized to view, or they have authenticated and then manually gone to the log in page (unlikely).

A further action would be to send the user to the relevant home page whenever they visit the login page, if they are already authenticated.

Substantiate answered 26/6, 2009 at 13:29 Comment(1)
This is only a partial solution, most suitable if you don't have different roles that can access different pages. If you do, you can have a user that's authenticated but still can't access the ReturnUrl, possibly leading to a redirect loop.Enswathe
H
1

If you have different directories and you are using asp.net authentication it is very easy. All you need is to put web.config file in each directory and define roles which can access files in that directory like this:

<authorization>
    <allow roles="shoppers"/>
    <deny  users="?"/>
</authorization>

You can get more details from this article on MSDN

You can set all in main web.config like this:

    <!-- Configuration for the "sub1" subdirectory. -->
      <location path="sub1">
        <system.web>
          <httpHandlers>
            <add verb="*" path="sub1" type="Type1"/>
            <add verb="*" path="sub1" type="Type2"/>
          </httpHandlers>
        </system.web>
      </location>

      <!-- Configuration for the "sub1/sub2" subdirectory. -->
      <location path="sub1/sub2">
        <system.web>
          <httpHandlers>
            <add verb="*" path="sub1/sub2" type="Type3"/>
            <add verb="*" path="sub1/sub2" type="Type4"/>
          </httpHandlers>
        </system.web>
      </location>
    </configuration>

This is from this article on MSDN :)

EDIT:

In your page load method do this:

if(!User.IsInRole("shopper"))
{
    lblNoAccess.Visible=true;
    lnkHome.Url="PATH_TO_HOME_PAGE_OF_THIS_ROLS";
}

Hope this helps you!

Hooligan answered 26/6, 2009 at 11:16 Comment(4)
The website is already set up along similar lines to what you have posted - however, what you have posted doesn't actually seem answer my question in any way.Substantiate
Okay Now I got you, the use is authenticated but not authorized to view this page! I've edited my answerHooligan
The page_load method on the page specified by returnurl is not being fired, as the user isn't getting that far as they are not authorized to. The concept is exactly what I want to do though.Substantiate
I always use this in Page_Load, don't know if it should be used in Init. I think we need some expert advice on this.Hooligan
L
1

One approach would be to override OnLoad of your aspx forms and check if the authenticated user is allowed access to the resource based on the role. So you create a BasePage.cs (in which you define a class BasePage which inherits from System.Web.UI.Page) for example from which all your Forms (aspx) inherit, in which you do this:

protected override void OnLoad(EventArgs e)
{
    InitializeSitemap();
    if (SiteMap.CurrentNode != null)
    {
        if (!UrlHelper.IsAnonymousAllowed(SiteMap.CurrentNode) && (!HttpContext.Current.User.Identity.IsAuthenticated || !UrlHelper.IsAccesible(SiteMap.CurrentNode)))
        {
            // You can redirect here to some form that has a custom message
            Response.Redirect("~/Forms/Logout.aspx");

            return;
        }
    }
    base.OnLoad(e);
}

Then in your UrlHelper class you need that IsAccessible function used above:

public static bool IsAccesible(SiteMapNode node)
{
    bool toRole = false;

    foreach (string role in node.Roles)
    {
        if (role == "*" || HttpContext.Current.User.IsInRole(role))
        {
            toRole = true;
        }
    }

    return toRole;
}

Here is IsAnonymousAllowed in case you wondered:

public static bool IsAnonymousAllowed(SiteMapNode node)
{
    return node[AllowAnonymousAttribute] != null ? bool.Parse(node[AllowAnonymousAttribute]) : false;
}
Landreth answered 26/6, 2009 at 11:41 Comment(0)
P
0

You can redirect him on the index page, telling him that he cannot access that page;)

Petromilli answered 26/6, 2009 at 11:0 Comment(2)
How do I know that he cannot access that page though? I can determine what role he is in, but not what role can access the requested page.Substantiate
Well you should make something like levels. If you have above level 4 you can access the page. Or with roles, you should attribute at each page a specific role that can access that page.Petromilli
B
0

Well, why don't you catch the directory in the login page? If the login page can determine which directory the user is trying to access, maybe they can get redirect to the right page based on role. If someone tries to go to /admin, and authentication succeeds, you can check if they do have access there. If not, you can either redirect to basic landing page indicating they do not have access or you redirect them to the role's landing page.

EDIT: You could probably do the redirecting in the LoggedIn event of the control.

Beseem answered 26/6, 2009 at 12:7 Comment(0)
R
0

One other option is to set a session variable when you're checking rights, and displaying that on the login page.

So you could do:

if(!User.IsInRole("shopper"))
{
    session("denied") = "You don't have access to shop";
    response.redirect("/login");
}

Then in the login page:

if ( session("denied") != "" ) {
   message.text = session("denied");
   session("denied") = "";
}
Renascent answered 26/6, 2009 at 13:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.