Simple OAuth + JSONapi response when token is expired - Decoupled
Is there a reason why this is implemented like this?

200 ok is expected status code for collection resources, even if one, many, or all entities were excluded from the collection resource for access reasons.
From https://www.drupal.org/project/jsonapi/issues/2853066:

The status code for a &quot;collection resource&quot; should be entirely distinct from any or all of the entities represented at that resource.
Unless there is an access control mechanism that is explicitly a prerequisite for accessing any list of entities of a given type that we can leverage, then it must be assumed that any consumer must have access to any collection resource.
It is completely consistent with REST to return a 200 response to an empty collection, even when all those entities have been elided for access reasons.



Or is there a way to alter the response?

Of course, you can. Check the documentation about altering routes and providing custom access tagged service:

https://www.drupal.org/docs/8/api/routing-system/altering-existing-routes-and-adding-new-routes-based-on-dynamic-ones
https://www.drupal.org/docs/8/api/routing-system/access-checking-on-routes


Finally, the link you provided in the question is to oauth specs, and is irrelevant to jsonapi. Oauth resource in Drupal (/oauth/token) will correctly give you 4xx in case of any errors when obtaining a new token.