JWT Path Auth claim always fails.

Created on 5 August 2024, 5 months ago

I am sorry, if I understand the fundamentals of the JWT claim world false, but I can't get it to work. Even if JWT Sessions and JWTAuth works as expected, the lines:

    $uid = $jwt->getClaim(['drupal', 'path_auth', 'uid']);
    // The JWT must include a claim matching the path after the host name,
    // or a prefix of the path.  E.g. "/system/files/". Note that this
    // must include any base path if the site is in a subdirectory.
    $path = $jwt->getClaim(['drupal', 'path_auth', 'path']);
    $request_path = $request->getBaseUrl() . $request->getPathInfo();
    if ($uid && $path && strpos($request_path, $path) === 0) {

will always fail, because nowhere (?) in the JWT modules is a Claim set with `['drupal', 'path_auth', 'uid']` or at least `path_auth` in it. So by looking at it, I can the first claim setup with a an EventSubscriber like so:

  public function setPathAutoClaims(JwtAuthGenerateEvent $event) {
    $event->addClaim(['drupal', 'path_auth', 'uid'], $this->currentUser->id());
  }

but the second claim is a bit more tricky. That's why I think the JWT PATh AUTO module should implement the `hook_file_url_alter(string &$uri) ...` and add that claim there.

*edit* I think I accomplished what I needed to do. Maybe not the best, but for everyone stumpling accross the same problem here it is:

/**
 * Implements hook_file_url_alter(). // Taken partially from the private_file_token module
 */
function foobar_file_url_alter(string &$uri): void {
  /** @var \Drupal\Core\StreamWrapper\StreamWrapperManager $stream_wrapper_manager */
  $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager');
  if ($stream_wrapper_manager::getScheme($uri) == 'private') {
    // Alter happens in "file_create_url". If returned uri with query strings
    // would contain the private wrapper, then injected query string arguments
    // would get url encoded at the end of that function within
    // Drupal\Core\StreamWrapper\PrivateStream::getExternalUrl(). Thus let's do
    // that instead already here and attach query string arguments to full uri.
    $private_wrapper = $stream_wrapper_manager->getViaUri($uri);
    $uri = $private_wrapper->getExternalUrl();

    $provider = \Drupal::getContainer()->get('jwt.authentication.jwt');
    $token = $provider->generateToken();

    $transcoder = \Drupal::getContainer()->get('jwt.transcoder');
    $jwt = $transcoder->decode($token);

    // Here we check if the given path is stored in the config
    $config = \Drupal::config('jwt_path_auth.config');
    $allowed_path_prefixes = (array) $config->get('allowed_path_prefixes');

    $URL = parse_url($uri);

    $path_matched = '';
    foreach ($allowed_path_prefixes as $prefix) {
      if (str_starts_with($URL['path'], $prefix)) {
        $path_matched = $prefix;
        break;
      }
    }

    if ($path_matched) {
      $jwt->setClaim(['drupal', 'path_auth', 'path'], $path_matched);

      $token = $transcoder->encode($jwt);

      $token_query = [
        'jwt' => $token,
      ];

      $uri .= (strpos($uri, '?') !== FALSE ? '&' : '?') . UrlHelper::buildQuery($token_query);
    }
  }
}

This seem to work.

Please advise, if that is somehow wrong.

🐛 Bug report
Status

Active

Version

2.1

Component

Code

Created by

🇩🇪Germany ro-no-lo

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024