If an anonymous user does not permission to access content, then an anonymous user is unable to access a custom 403 (access denied) page.

Steps to reproduce:

  1. node/add/page > Title 'Custom 403 page' > Save (node/1)
  2. admin/settings/error-reporting > Default 403 (access denied) page: node/1
  3. admin/user/permissions > anonymous user: de-select 'access content' under 'node module' > Save

Outcome:
Accessing the site as an anonymous user will display the default Access denied message. The expected result is view the contents of node/1.

I tried to do some digging and discovered that the default 403 page was being casued by MENU_ACCESS_DENIED being returned in menu_execute_active_handler(). I got lost after menu_get_item().

Comments

simon.males’s picture

Version: 6.0-beta4 » 6.0-rc1

Bug can be replicated in 6.0-rc1, updated version accordingly.

Anonymous’s picture

Version: 6.0-rc1 » 6.x-dev
Status: Active » Needs review
StatusFileSize
new649 bytes

I was able to reproduce this in 6.x-dev. Patch is attached. Removed check for MENU_ACCESS_DENIED, which doesn't make sense when attempting to serve the custom access denied page.

tonyn’s picture

Bug replicated in RC2... I am unsure about current status of patch, as MENU_ACCESS_DENIED may or may not need to stay there.

Anonymous’s picture

Anyone mind taking a look at this? It's a relatively minor change and I think should be patched in 6.x, and applied to 7.x as well.

joemoraca’s picture

Version: 6.x-dev » 6.0
Status: Needs review » Active

This is still a bug in the production release. It seems the above patch was included in -- but seems to still not give access to the "custom page"

Anonymous’s picture

Status: Active » Needs review

The patch was never applied to core. It still needs review.

Anonymous’s picture

Version: 6.0 » 7.x-dev

Moving to 7.x in hopes of being backported.

Patch still applies successively to HEAD.

Freso’s picture

Subscribing, and will probably be willing to backport to 6/5.x if needed and if noone beats me to it.

simon.males’s picture

Pretty sure this a non issue in 5.x, I have this setup working in 5.x and was trying to do the same in 6 when I discovered the bug.

vladimir.dolgopolov’s picture

Here is a test for Simpletest module for this issue.
The patch #2 has passed the test.


class TestCase198975 extends DrupalTestCase {
  function get_info() {
    return array(
      'name' => t('[198975] Custom 403 page not available to user who doesn\'t have \'access content\' permissions'),
      'desc' => t('If an anonymous user does not permission to access content, then an anonymous user is unable to access a custom 403 (access denied) page.'),
      'group' => t('Drupal 7 Tests'),
    );
  }
  
  function testIssue() {

    // save original perms for 'anonymous user'
    $anonymous_user_perm_orig = db_result(db_query('SELECT perm FROM {permission} WHERE rid = %d', DRUPAL_ANONYMOUS_RID));

    // create a custom 'Default 403 (access denied) page'
    $web_user = $this->drupalCreateUserRolePerm(array('edit own page content', 'create page content'));
    $this->drupalLoginUser($web_user);
    $edit = array();
    $edit['title']    = 'Custom 403 page ' . $this->randomName();
    $edit['body']     = 'Custom 403 page ' . $this->randomName();
    $this->drupalPost('node/add/page', $edit, 'Save');
    $node = node_load(array('title' => $edit['title']));
    $this->drupalGet('logout');

    // set a custom 'Default 403 (access denied) page'
    $this->drupalVariableSet('site_403', "node/{$node->nid}");

    // check 'anonymous user' can reach custom 403 page with 'access content' perm
    db_query("DELETE FROM {permission} WHERE rid = %d", DRUPAL_ANONYMOUS_RID);
    db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", DRUPAL_ANONYMOUS_RID, 'access content');
    $this->drupalGet('admin'); // a common restricted url
    $this->assertWantedRaw($edit['title'], "Check with 'access content': %s");

    // check 'anonymous user' can reach custom 403 page without 'access content' perm
    db_query("DELETE FROM {permission} WHERE rid = %d", DRUPAL_ANONYMOUS_RID);
    $this->drupalGet('admin'); // a common restricted url
    $this->assertWantedRaw($edit['title'], "Check without 'access content': %s");

    // delete the custom 403 page
    node_delete($node->nid);

    // restore original anonymous user perms
    if (!empty($anonymous_user_perm_orig)) {
      db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", DRUPAL_ANONYMOUS_RID, $anonymous_user_perm_orig);
    }
    
  }

}

gábor hojtsy’s picture

Status: Needs review » Needs work

@Vladimir, thanks for the tests, looks good and should be good for further iterations of the patch as well.
@Everyone: Why would getting a custom 403 page result in a MENU_ACCESS_DENIED return value at all? The idea of this check is if there was no return value, or it was a stock menu constant, the stock error page should be output, if I understand this right.

simon.males’s picture

I'm not sure that I've gone about this the right way, but shouldn't the developer who committed the change be contacted. In this case 'goba'.

http://cvs.drupal.org/viewvc.py/drupal/drupal/includes/common.inc?view=d...

gábor hojtsy’s picture

simon.males: Why should I be contacted? The patch you pointed out was http://drupal.org/node/84754 so refer there.

Anonymous’s picture

Status: Needs work » Needs review
Freso’s picture

StatusFileSize
new676 bytes

Here's a re-rolled patch that is applicable from Drupal root. Looks good, but not tested.

jpoesen’s picture

Bug replicated on a on a clean D7 from head.
Applying http://drupal.org/files/issues/403-access-denied-fix_0.patch doesn't fully work for me:

- the custom access denied page (node/1) is shown, but its body content isn't. Instead, the digit '3' is shown.

- the custom access denied page (node/1) is not shown when trying to access it directly via node/1. In this case you get the default access denied page

jpoesen’s picture

Status: Needs review » Needs work

Forgot to change status > needs work

drewish’s picture

jopsesen, i think the behavior you raise in your second point is actually correct... you only want them to be able to view the node in the context of a 403 error.

Mattias-J’s picture

Subscribing

gtaylor’s picture

Version: 7.x-dev » 6.4

I can confirm that this is a problem in 6.4 and is not a problem in 5.10. Is this being worked on now for the 6.x codeline?

Freso’s picture

Version: 6.4 » 7.x-dev

@gtaylor: Is it no longer a problem in 7.x? If it is still a problem there, that's where it should be fixed. The fix for 6.x follows after.

gtaylor’s picture

sorry for the confusion. I can't speak one way or the other to 7.x.
But I can confirm that's it's working in 5.10 if the node number is greater than 2.

Mattias-J’s picture

Uhh.. not a problem in 5.10?

We have to use a hack (revert #84754-32: Fix of non-existent/denied 403/404 pages) to allow users to get a logon screen when anonymous users don't have access to a page. So i would say this one is an issue even for 5.10.

And we have /node/7 as our 403 page.

arhak’s picture

subscribing

durum’s picture

Version: 7.x-dev » 6.5
Status: Needs work » Closed (duplicate)

Bug replicated in 6.5. Does anyone know any fixes for 6.x or somewhere where it is discussed?

BENWECHSLER’s picture

subscribing

arhak’s picture

@durum please when marking as duplicate say where is the other issue to be able to follow that one instead

durum’s picture

@arhak,@others: sorry, i don't remember.

But I found something: After adding about 20 pages(I didn't check after each page, so probably it is less) the function works regardless of the id of your custom 403 page.

Hth.

arhak’s picture

Status: Closed (duplicate) » Active

well, if somebody hits the other issue, please let us know

BENWECHSLER’s picture

Seeing this post, I added 22 pages to my site. The 403 page still does not appear, and I get the "Access Denied" still. This is a serious issue for my client. I am very seriously considering dropping Drupal if this is not fixed soon.

durum’s picture

BENWECHSLER, I am sorry about it but it worked for me. Just check it out: www.littlebigventures.com/asdasd

BENWECHSLER’s picture

durum, Can you give me details about the pages you added? I tried up to 30 new pages and still no success. See my site at http://riverwalklofts.org/content.

durum’s picture

Version: 8.x-dev » 6.5
Issue tags: -Needs backport to D7

BENWECHSLER, I am very very sorry for misleading you and others. Nothing was changed. I had just allowed unregistered user to see content and custom 404's were working and I didn't realized that nuance and my poor brain acted like it was working.

BTW, I found something else in my new site but it may not work if your default language is English. I just translated the strings for

Access denied

You are not authorized to access this page.

into something like

Under maintenance

We will be back in a few days

and I at least have the message given.

I am not sure if this will work- you can create any new Language by Languages>Add Language, and than make it default. Since it will not have any strings in it, the English strings will be used. And in Translate Interface you will be able to search for and change the string "Access denied". I think this will work and looks like the best solution among all.

Sorry again. Hope the latter solution helps.

asohn’s picture

I was having a related (if not the same) problem on my installation of Drupal 6.10
Here is my fix. It works. Use it at your own risk.
I got tired of searching through the Drupal APIs for functions to retrieve a node's title and content given its path so I just used a query.

original common.inc

function drupal_access_denied() {
  drupal_set_header('HTTP/1.1 403 Forbidden');
  watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);

  // Keep old path for reference.
  if (!isset($_REQUEST['destination'])) {
    $_REQUEST['destination'] = $_GET['q'];
  }

  $path = drupal_get_normal_path(variable_get('site_403', ''));
  if ($path && $path != $_GET['q']) {
    // Set the active item in case there are tabs to display or other
    // dependencies on the path.
    menu_set_active_item($path);
    $return = menu_execute_active_handler($path);
  }

  if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
    drupal_set_title(t('Access denied'));
    $return = t('You are not authorized to access this page.');
  }
  print theme('page', $return);
}

altered common.inc

function drupal_access_denied() {
  drupal_set_header('HTTP/1.1 403 Forbidden');
  watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING);

  // Keep old path for reference.
  if (!isset($_REQUEST['destination'])) {
    $_REQUEST['destination'] = $_GET['q'];
  }

  $path = drupal_get_normal_path(variable_get('site_403', ''));
  if ($path && $path != $_GET['q']) {
    // Set the active item in case there are tabs to display or other
    // dependencies on the path.
    menu_set_active_item($path);
    $return = menu_execute_active_handler($path);
  }

  if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
    if ($path && preg_match('/^node\/\d+$/', $path)) {
      $nid = preg_replace('/^node\/(\d+)$/', '$1', $path);
      $r = db_fetch_object(db_query("SELECT `title`, `body` FROM `node_revisions` WHERE `nid` = '$nid' LIMIT 1;"));
      drupal_set_title(t($r->title));
      $return = t($r->body);
    } else {
      drupal_set_title(t('Access denied'));
      $return = t('You are not authorized to access this page.');
    }
  }

  print theme('page', $return);
}
arpieb’s picture

Version: 6.5 » 6.13

Just installed the freshly-minted D6.13, and it is still having the same problem. I've also got a site that needs to have all content hidden from anonymous users, but instead of getting my defined 403 page served up, I get the stock "Access denied" page.

Is anyone working on this one? It seems like something that would be critical for a non-public site running Drupal... In our case, we are using it as a secure CMS for our customer base.

Problem page can be seen here (bear with me - it's under development so still mostly stock right now, depending on when you read this):

http://www.peirspeed.com/support

Any help would be greatly appreciated! I'm also going to look into delving into bug fixes myself in the near future, but simply don't have the time right now (large site I have to have built in 30 days - which is why I went with Drupal).

Thanks!

-R

vertikal.dk’s picture

arpieb,

As far as I can see your problem seems server related - meaning that your server doesn't redirect the error back to Drupal and lets Drupal show its message, but serves the default server based message. This might be an .htaccess or server configuration issue rather than a Drupal problem.

The problem the rest of us have (yes, I have it too), is that Drupal seems to serve it's own fairly primitive Access denied text rather than our own meticulously crafted, intelligent error page made within Drupal.

The replacement works nicely for my 404-page, but the 403-ditto reclines all appearances. Haven't tried the patches, but this certainly ought to work out of the box. As a temporary remedy I have used the translation function to write a somewhat more explanatory text in Danish (the site is in Danish), but I would very much like to be able to replace it with a real page.

Martin

vertikal.dk’s picture

Well, I solved my own 403-problem. Using URL aliases and pathauto my system had set the URL for the 403-page to a name, which contained diacritical Danish letters, and I simply pasted this URL into the admin/settings/error-reporting page.

On a hunch I tried setting the URL manually to something "harmless" and changing the 403-settings and voila! It works nicely now, and I get my custom made Access denied page with more links and more help than is available in Drupal's default message.

Martin

macpharmer’s picture

I can say #34 works for me too, except that I use a database prefix, so `node_revisions` needs to be changed to `prefix_node_revisions`. I'm not a programming expert, but hopefully someone can fix this to accommodate for database prefixes.

arhak’s picture

@#38 change where `node_revisions` for {node_revisions} and it will work for prefixes

snohio’s picture

Version: 6.13 » 6.14

Ok. I just updated a site from D5.7 - it was a pretty customized site - and ran into this issue as well. My solution was two-fold. Utilizing the code change in #34 as well as modifying the Error Pages in IIS(7.5) to point to index?q=node/4 (my 403 error page) seemed to take care of it. I did have to do BOTH..

I'm not sure why this "feature" has been ongoing since D6 and continues in D7 apparently. It would seem logical that some folks would want to create a private site where you need to be a member to gain access to the content - so content access being disallowed for Anonymous would be out of the question. I really dislike changing .inc code because I have to remember it for the next update.

peterofoz’s picture

I can confirm that this feature works in Drupal 5.19, but not in 6.14. Implemented the patch in #34 and it looks good for what I need. Thanks.

konsumer’s picture

StatusFileSize
new1.18 KB

Solution in #34 worked for me. Attached is the same, in patch form.

konsumer’s picture

StatusFileSize
new1.17 KB

Attached is a better patch, that will work with db prefix.

deboyisok’s picture

I found this bug when I referred to the custom page by its name e.g "No-Admittance" but when I referred by reference to the Node "Node/176" it worked. (Drupal 7)

naxoc’s picture

Version: 6.14 » 8.x-dev

I tried to replicate this in D8 and got an uncaught PHP exception (WSOD, but in the error log).

To replicate - use the steps described in the issue summary, only use "View published content" instead of 'access content'.

Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: "" at /Users/ckj/Sites/drupal8/core/lib/Drupal/Core/EventSubscriber/AccessSubscriber.php line 34
Exception thrown when handling an exception (Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: )
fietserwin’s picture

Issue tags: +Needs backport to D7
StatusFileSize
new1.93 KB

Unlike what #44 suggests, it does not work in D7. Attached is a patch for D7, tested with the dev version from the day of posting and with D7.18. I used the txt extension to not invoke the test suite with this patch for D7.

Comparing with the D6 patch I had to change the code of node_is_page() as well. This function determines if the rendering of a node is meant to be its full page display or as part of other content (and thus with the title as a clickable link).

Status: Active » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.