Custom authentication provider returns 403 for _access: 'TRUE' The Jenny module implements an API and needs to authenticate based on this header...

Authorization: Jenny 8675309


Here is my API route...

jenny.api.get:
  path: '/api/jenny'
  defaults:
    _controller: '\Drupal\jenny\Controller\ApiController::get'
  methods: [GET]
  requirements:
    _access: 'TRUE'


The API returns data for any type of user, but for some roles additional data is included.

Here is my implementation for AuthenticationProviderInterface...

public function applies(Request $request) {
  if ($header = $request-&gt;headers-&gt;get('Authorization')) {
    if(strpos($header, 'Jenny ') !== FALSE) {
      \Drupal::logger('jenny')-&gt;info('this applies');
      return TRUE;
    }
  }
  return FALSE;
}

public function authenticate(Request $request) {
  \Drupal::logger('jenny')-&gt;info('authenticate');
  return $this-&gt;entityTypeManager-&gt;getStorage('user')-&gt;load(1);
}


This example code authenticates the admin user whenever there is an Authorization: Jenny header. Obviously the real code implements the logic to authenticate the proper user.

Here's what shows up in the log...

uid  type            message
0    jenny           this applies
0    jenny           this applies
0    jenny           authenticate
1    jenny           this applies
1    jenny           this applies
1    jenny           this applies
1    accesss denied  /api/jenny


It shows the uid changing, so it suggests that my authentication provider is doing it's part, but for some reason it's still coming back 403 access denied even though the route is _access: 'TRUE'. A request for /api/jenny without an Authorization: Jenny header returns the expected data.

This makes no sense to me. Could someone please point out what I'm doing wrong or why this isn't working? Thanks.

Upon further review, this is happening on all routes if there is an Authorization: Jenny header, even though the authentication provider is returning the admin user.
Routes need to specify the authentication providers they want to support.

By default, that's session, so authenticating with something else is not allowed.

You do this by specifying _auth: ['your_authentication_provider'] within the options: key of your route.