Anonymous users can't access republished nodes via JSON API and Basic Auth

Created on 15 June 2021, over 3 years ago
Updated 29 August 2024, about 1 month ago

Problem/Motivation

We are experiencing a strange behavior in our decoupled site that is using JSON API to get nodes' data from CMS and Basic Auth for authentication. The behavior is as follows: if a node is published on the site, anonymous users are able to see it. If for some reason we unpublish this node, it will no longer be accessible for anonymous users, as expected. Now if we were to publish the same node again, anonymous users should be able to view the node, but they still keep getting a 401 response instead.
After some debugging, we found out that 401 responses from JSON API have the '4xx-response' cache tag, and even though Drupal invalidates it after node updates (here) it seems that Basic Auth is returning a cached exception from challengeException method.

Steps to reproduce

  1. Enable jsonapi.
  2. Enable basic_auth.
  3. Create a published node and check that this node is accessible for anonymous users via JSON API. For example, given a published article, making a request to /jsonapi/node/article/<uuid>.
  4. Unpublish the node created in the previous step, and check that the node is no longer accessible for anonymous users. (The request to /jsonapi/node/article/<uuid> is returning 401 which is OK).
  5. Publish the node again.
  6. Verify that anonymous users are still not able to view the published node. (The request to /jsonapi/node/article/<uuid> is returning 401 even though the article is published)

Proposed resolution

We are not 100% sure the correct way to fix this issue, but what we did to make it work was adding the '4xx-response' cache tag to the UnauthorizedException thrown by Basic Auth's challengeException method. Suggestions are welcome!

diff --git a/web/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php b/web/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
index 72b81a7b..256f7ecf 100644
--- a/web/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
+++ b/web/core/modules/basic_auth/src/Authentication/Provider/BasicAuth.php
@@ -154,7 +154,7 @@ public function challengeException(Request $request, \Exception $previous) {
     // @see \Drupal\Core\EventSubscriber\ClientErrorResponseSubscriber()
     // @see \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onAllResponds()
     $cacheability = CacheableMetadata::createFromObject($site_config)
-      ->addCacheTags(['config:user.role.anonymous'])
+      ->addCacheTags(['config:user.role.anonymous', '4xx-response'])
       ->addCacheContexts(['user.roles:anonymous']);
     return $request->isMethodCacheable()
       ? new CacheableUnauthorizedHttpException($cacheability, (string) $challenge, 'No authentication credentials provided.', $previous)
๐Ÿ› Bug report
Status

Needs work

Version

11.0 ๐Ÿ”ฅ

Component
Cacheย  โ†’

Last updated 1 day ago

Created by

๐Ÿ‡ฆ๐Ÿ‡ทArgentina guillerecalde

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States jeffschuler Boulder, Colorado

    We're experiencing this too, just as you lay out in the "steps to reproduce", and your changes fix the issue.

    I don't know the internals here very well, but this comment in BasicAuth::challengeException():

      // 2. Have the 'config:user.role.anonymous' cache tag, because the only
      //    reason this 401 would no longer be a 401 is if permissions for the
      //    'anonymous' role change, causing the cache tag to be invalidated.
    

    ...does seem to leave out the possibility that a 401 would no longer be a 401 because changing an entity status to Published gives the anonymous user access.

    Here are your changes as a patch against 11.x-dev. That patch is applying and working in 10.2.2 as well.

  • Status changed to Needs work 8 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Thanks for reporting, will need test coverage to show the issue.

    Also recommend using an MR as patches are being phased out.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia samit.310@gmail.com

    samit.310@gmail.com โ†’ made their first commit to this issueโ€™s fork.

  • ๐Ÿ‡ฎ๐Ÿ‡ณIndia samit.310@gmail.com

    HI @jeffschuler,

    The 4xx-response Cache tag is already there while following the Steps to reproduce You can check core/lib/Drupal/Core/EventSubscriber/ClientErrorResponseSubscriber.php, The onRespond function is used to Sets the '4xx-response' cache tag on 4xx responses.

    I am also adding adding the working screenshots.

    Not sure but it might be because of some other contrib modules that you are using.

    My Drupal Version is 11.x and PHP is 8.3.10.

    Thanks
    Samit K.

Production build 0.71.5 2024