Problem/Motivation
This is the default REST resource configuration:
langcode: en
status: true
dependencies:
module:
- basic_auth
- hal
- node
id: entity.node
plugin_id: 'entity:node'
granularity: resource
configuration:
methods:
- GET
- POST
- PATCH
- DELETE
formats:
- hal_json
authentication:
- basic_auth
If you read it, you'd think it result in
- a
NodeREST resource being provisioned - which is accessible via the
GET,POST,PATCHandDELETEmethods - can be read/modified in the
application/hal+jsonformat - and requires HTTP Basic Authentication
This is almost correct. The gotcha is in point 4: anybody is always allowed to use the cookie authentication mechanism, because it is a global authentication provider
This is correct! See #12.
Proposed resolution
Either:
Modify the meaning of_auth: only things listed there are allowed, global authentication providers are not also allowed (global authentication providers then only apply to routes without the_authroute option)Introduce a new_auth_onlyroute option that exhibits the above behavior, and modify\Drupal\rest\Routing\ResourceRoutes::getRoutesForResourceConfig()to use that route option instead
Add explicit test coverage proving this.
Remaining tasks
None.
User interface changes
None.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | 2817745-12.patch | 2.99 KB | wim leers |
Comments
Comment #2
wim leersComment #3
wim leersActually, since this affects security, I think this is major.
Comment #5
dawehnerI agree, being more explicit is always a win. Changing the behaviour of existing configuration keys is tricky though. If you are honest about things, even configuration is sort of an API. Can we change it?
Comment #6
wim leersMaybe it's once again possible to provide an upgrade path to ensure consistent behavior. We managed to do #2308745: Remove rest.settings.yml, use rest_resource config entities without breaking BC (i.e. without breaking configuration, i.e. without changing the behavior that depends on configuration — behavior was the same before and after). So perhaps we can find a way to do so here too.
Comment #7
dawehnerWell I'm actually referring to the config structure itself. You cannot really provide a BC layer I guess unless you override the config object.
Comment #8
wim leersI meant in #6 that #2308745: Remove rest.settings.yml, use rest_resource config entities also changed the config structure itself. We managed to provide an upgrade path for that. Hence why I think it's once again possible to provide an update path to ensure consistent behavior.
Comment #9
wim leersTo be clear: in the update path, we'd automatically add all global authentication providers (
cookie) to the configuration, to ensure we don't break existing sites.Comment #10
wim leers#2808233: REST 403 responses don't tell the user *why* access is not granted: requires deep Drupal understanding to figure out landed recently. Which included the interdiff at #2808233-84: REST 403 responses don't tell the user *why* access is not granted: requires deep Drupal understanding to figure out. That added the following test coverage to
\Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase::testGet():IOW: this already added some of the test coverage we need. But it's testing a non-global authentication provider What this issue is about, is ensuring that even global authentication providers are treated like this.
Comment #11
wim leersComment #12
wim leersI worked on test coverage today to prove that global authentication providers are always allowed, even when they're not explicitly listed in a
RestResourceConfigentity's configuration. Not being listed there causes it to also not be listed in a REST route's_authoption.But… it turns out that actually the configuration is being respected after all! Did I really make the wrong observation way back when I opened this issue?
The ultimate test:
/node/1GET http://d8/node/1?_format=hal_json. You get an error response.rest.resource.entity.node, and addcookieto theauthkey (by default, onlybasic_authis listed).GET http://d8/node/1?_format=hal_json. You get a HAL+JSON response.Tested this with both 8.2.6 and 8.3.x. It works as expected.
In other words:
Comment #13
tedbowThe test looks good. Into it and it is the correct error message for the authentication not being applicable for the route.
RTBC!
Comment #15
cilefen commentedCommitted d20187f and pushed to 8.4.x. Thanks! We are entering a commit freeze so we can cherry-pick this to 8.3.x as early as Thursday.
Comment #17
cilefen commentedCherry-picked as d9be246 and pushed to 8.3.x. Thanks!
Comment #18
wim leersThanks!