We have created 403 pages and set them via the general site information page [0] > error pages where we entered the URL to the node that should be displayed when a 403 response is triggered. In our case it is /node/237.

[1]: https://www.ourwebsite.com/admin/config/system/site-information

But pages protected by permissions_by_term always redirect to /system/403 ignoring our setting in the general site information page.

Are we doing something wrong?

Comments

criscom created an issue. See original summary.

criscom’s picture

Issue summary: View changes
kevin.pfeifer’s picture

StatusFileSize
new610 bytes

The problem here is the "$redirect_url = new \Drupal\Core\Url('system.403');"

This always uses the route "system.403" from the file docroot/core/modules/system/system.routing.yml which is "/system/403".

The easy way out is to just throw a Symfony Expcetion which handles all we need instead of creating our own response.
See here: https://drupal.stackexchange.com/questions/215627/programmatically-redir...

With this the URL also doesn't change.

criscom’s picture

Status: Active » Needs review
kevinquillen’s picture

This patch caused this fatal error many times over:

"Fatal error: Maximum function nesting level of '256' reached, aborting! in /vendor/symfony/http-foundation/ParameterBag.php on line 84".

Reverting the patch makes this go away.

kevinquillen’s picture

Status: Needs review » Needs work
kevinquillen’s picture

The approach is correct, as the exception should be thrown. However my bug results in the fact I did not have a custom 403 page defined in my site settings, and (I think) somehow caused a redirect loop. Adding a value (I created a node) for the 403 page then made the error vanish, and the URL is retained (instead of redirect you to another page). I can't tell if this is just an error for me, or is triggered if no 403 url exists. If I remove the 403 url value, I get it again.

Other than that, its preferable to use the use ... statement so then it would be:

use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

...

  private function sendUserToAccessDeniedPage() {
    throw new AccessDeniedHttpException();
  }

But we likely will want to add a test for this.

kevinquillen’s picture

Version: 8.x-2.3 » 8.x-2.5
kevinquillen’s picture

Ok, this seems replicable by:

1. Create a node
2. Assign a term
3. DONT have a custom 403 url in Site Settings
4. Have an authenticated user with no other role visit the node
5. You get max nesting level exceeded error
6. Adding a custom url makes the page render correctly, or adding a role to the user

I think the fix lies in checking the master request in the initial event:

  /**
   * Access restriction on kernel request.
   */
  public function onKernelRequest(GetResponseEvent $event)
  {
    // only return a response for a master request
    if (!$event->isMasterRequest()) {
      return;
    }

After that, I could no longer get the fatal error, no matter if I have a 403 url or not or if the user has roles or not, or if the node has no terms added or not.

See: https://drupal.stackexchange.com/questions/232796/how-to-issue-404-from-...

I am not sure if this applies to the other event as well, as I am not using tag autocomplete.

kevinquillen’s picture

StatusFileSize
new2.05 KB

Attached is an updated patch with the aforementioned changes.

I removed the method `sendUserToAccessDeniedPage`, because what we should do is just throw the exception. The method is superfluous and not needed.

It also adds the early return if the evaluated event is not the master request, fixing the other bugs with missing terms or a user without roles.

kevinquillen’s picture

Status: Needs work » Needs review
kevinquillen’s picture

Opened a PR for this on Bitbucket.

stacypendell’s picture

Your new patch fixed the problem on my site. Thanks! I'm running 8.x-2.5, core 8.6.3.

jepster_’s picture

Status: Needs review » Postponed (maintainer needs more info)

@Kevin Quillen : I have created a Behat test (browser based acceptance test; http://behat.org/en/latest/) which is proving that custom 403 http status pages work. How do I need to modify the test to prove a bug here? Right now I am not able to reproduce your issue.

See PR: https://bitbucket.org/peter_majmesku/permissions_by_term/pull-requests/1...

Please do not merge this PR right now. It is just for presentation right now. There is no business logic modified currently. The PR contains just the test.

jepster_’s picture

See working CI pipeline: https://bitbucket.org/peter_majmesku/permissions_by_term/addon/pipelines...

Newly added scenario is named "I want to be redirected to a custom page by the 403 HTTP status code".

kevinquillen’s picture

I'm not following, what am I to be looking at here? The OP and #9 outlines both scenarios which the un-patched version triggers.

jepster_’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

@kevinquillen:

1. Create a node
2. Assign a term
3. DONT have a custom 403 url in Site Settings
4. Have an authenticated user with no other role visit the node
5. You get max nesting level exceeded error
6. Adding a custom url makes the page render correctly, or adding a role to the user

I have tried exactly this and my authenticated user is redirected to a access denied page. No max. nesting exceeded error. Looks like this is something on your end. May you check your other modules which might interfere or your php.ini settings.

kevinquillen’s picture

Status: Closed (cannot reproduce) » Active

Why so quick to close? Were the 403 exception and master request check changes committed to dev? Those are the two issues outlined here, regardless of max nested exception error.

jepster_’s picture

Status: Active » Postponed (maintainer needs more info)

I cannot reproduce the issue, as described. I won't commit code just in doubt. You could not describe me, how I can reproduce the issue. If you can describe me, how I can reproduce the issue on a Drupal instance with PbT, I will come back to this issue.

kevinquillen’s picture

Let me rephrase that; I'm not asking for blind commits. There are two issues here that a few have reported:

  1. The 403 setting in the admin is ignored.
  2. The kernel listener class in some circumstances can be caught in a loop, throwing a max nesting level exceeded exception.

The patch in #10 resolves both - including throwing an AccessDeniedHttpException instead of doing a hard redirect to system.403 (which preserves the current URL, among other things).

jepster_’s picture

Which circumstances, how can I reproduce them?

The 403 route is being used. Drupal is handling it. I could successfully test the custom 403 url.

Sorry, without concrete answers I am not committing anything.

kevinquillen’s picture

If you look through core, there are no examples of access denials being redirected to system.403. Instead, AccessDeniedHttpException is thrown.

A subscriber in Drupal core already handles it (when thrown):

  /**
   * Handles a 403 error for HTML.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event
   *   The event to process.
   */
  public function on403(GetResponseForExceptionEvent $event) {
    $this->makeSubrequest($event, '/system/403', Response::HTTP_FORBIDDEN);
  }

So at the very least, there is no need to do this and instead just throw the exception.

edit:

change record https://www.drupal.org/node/1616360

mrweiner’s picture

Status: Postponed (maintainer needs more info) » Needs review

Re-opening this. I can confirm that I've been experiencing the same issue where permissions_by_term was ignoring the 403 url set in the admin area. This was remedied by the patch in 10 and I believe it is the correct approach.

I believe the breakdown here is that:

  1. sendUserToAccessDeniedPage() is redirecting users straight to the path defined by system.403
  2. system.403 is defined in system.routing.yml as '/system/403/' and does not change
  3. the admin form in question sets the value of page.403, not the value of system.403
  4. the behat test is confirming that, when hitting a 403 error, the user is sent to the path defined by page.403. This is irrelevant because the sendUserToAccessDeniedPage() is not throwing a 403 error -- it is simply redirecting the user directly to system.403.

Am I off base, here?

silverham’s picture

+1 Drupal core does not redirect on 403 access denied, nor should this module.

This alse means i lose the contextual information to create a link like below based on current (denied) path.

http://mysite.com/user/login?destination=my/denied-page

themic8’s picture

StatusFileSize
new1.85 KB

Rerolled the patch for version 2.18.

themic8’s picture

StatusFileSize
new1.36 KB

Rerolled the patch for version 2.18, updated.

Probably not needed anymore.

  • Peter Majmesku committed 5dd097d on 3009470-403-url-settings-ignored authored by themic8
    Issue #3009470 by themic8, kevinquillen, kevin.pfeifer: 403 URL settings...

  • Peter Majmesku committed 5dd097d on 8.x-2.x authored by themic8
    Issue #3009470 by themic8, kevinquillen, kevin.pfeifer: 403 URL settings...
jepster_’s picture

Status: Needs review » Fixed

@themic8: Thanks for your patch!

I have slightly modified it and resolved the issue. See Drupal\permissions_by_term\Listener\KernelEventListener.

Check PbT version 8.x-2.22: https://www.drupal.org/project/permissions_by_term/releases/8.x-2.22

jepster_’s picture

Status: Fixed » Closed (fixed)