Issue when specifying format when used in combination with the REST & JSON API Authentication module.

Created on 5 December 2022, almost 2 years ago
Updated 21 December 2023, 11 months ago

Problem/Motivation

I'm attempting to use this module with the REST & JSON API Authentication module β†’ and its API key authentication method. Standard requests made to /subrequests work fine. But when I specify the format with ?_format=json I get the error message "The used authentication method is not allowed on this route.".

I did some very light digging and found where the error was coming from. It's originating in Drupal\Core\Authentication::defaultFilter(). When the format isn't specified, the $provider_id variable has the value "rest_api_authentication" and the allowed authentication options are "rest_api_authentication" and "cookie". But when the format is specified, while the $provider_id value remains "rest_api_authentication", the allowed auth options are "basic_auth", "cookie", "oauth2", and "token_bearer".

I've spent an entire workday searching, but I haven't found anyone experiencing the same issue. And I'm not sure if this is even an issue with this module, or the rest api authentication module. I'm sure I COULD parse and use the default mutlipart/related response. But I'd much rather get a JSON response and I'm also afraid that this issue could be indicative of a larger one that could come back to bite me in the future.

πŸ› Bug report
Status

Active

Version

3.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States JBHUTT09

Live updates comments and jobs are added and updated live.
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 JBHUTT09

    So I've just now come back to this after a year of other projects and I think I've found a solution, though I'm not sure if it violates any conventions.

    My solution is to pass the format argument in the post body instead of in the query string. I've implemented two approaches for this solution. They both modify Drupal\subrequests\Blueprint\BlueprintManager::parse() and check for a format key in the input and apply that format to the Request object which determines the response format in Drupal\subrequests\Controller\FrontController::handle(). The default will be multipart/related just for as much consistency with the existing module as possible, though I would personally expect the default format to be JSON since this is for the JSONAPI.

    This is the first:

    public function parse($input, Request $request) {
        $decoded = $this->serializer
            ->decode($input, 'json');
        $format = $decoded['format'] ?? 'multipart-related';
        unset($decoded['format']);
        /** @var \Drupal\subrequests\SubrequestsTree $output */
        $output = $this->serializer
            ->denormalize($decoded, SubrequestsTree::class, 'json');
        $request->setRequestFormat($format);
        $output->setMasterRequest($request);
        // Forward the Host header to place nice with decoupled routers.
        $this->forwardHeader('host', $request, $output);
        return $output;
    }
    

    All this does is check for the format key and unset the key before the input is passed along to the denormalizer.

    The second, and my preferred is:

    public function parse($input, Request $request) {
        $decoded = $this->serializer
            ->decode($input, 'json');
        $format = $decoded['format'] ?? 'multipart-related';
        $subrequests = $decoded['subrequests'] ?? $decoded;
        /** @var \Drupal\subrequests\SubrequestsTree $output */
        $output = $this->serializer
            ->denormalize($subrequests, SubrequestsTree::class, 'json');
        $request->setRequestFormat($format);
        $output->setMasterRequest($request);
        // Forward the Host header to place nice with decoupled routers.
        $this->forwardHeader('host', $request, $output);
        return $output;
    }
    

    This approach changes the payload format and places the subrequests into their own subrequests key. I think this approach is cleaner as it keeps the different parts nice and separate. It also allows for flexibility as it would be simple to add more keys for future functionality. But I'm not sure if this violates some convention that influenced the original payload structure to be just an array of requests.

    I have no idea how to do things like generate patch files or propose changes. Maybe I'll look into learning that, but for now at least I wanted to share my findings in case they help others.

  • πŸ‡ΊπŸ‡ΈUnited States JBHUTT09

    Okay, so I've come to the conclusion that I've been barking up the wrong tree and that the best solution would be to allow the default response format to be set in the admin UI. That would sidestep the issue entirely.

Production build 0.71.5 2024