diff --git a/core/modules/navigation/js/user-block.js b/core/modules/navigation/js/user-block.js
deleted file mode 100644
index dd09467ba618579f08eed6d971f9af5c45bac0da..0000000000000000000000000000000000000000
--- a/core/modules/navigation/js/user-block.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @file
- *
- * Customizes the user block to use the current username without affecting
- * caching.
- */
-
-((Drupal, drupalSettings, once) => {
-  /**
-   * Replaces the generic 'My Account' text with the actual username.
-   *
-   * @type {Drupal~behavior}
-   *
-   * @prop {Drupal~behaviorAttach} attach
-   *   Sets the username.
-   */
-  Drupal.behaviors.navigationUsername = {
-    attach: (context, settings) => {
-      if (!settings?.navigation?.user) {
-        return;
-      }
-      once('user-block', '[data-user-block]', context).forEach((userBlock) => {
-        userBlock
-          .querySelectorAll(
-            '.toolbar-popover__control, .toolbar-popover__header',
-          )
-          .forEach((button) => {
-            const buttonLabel = button.querySelector('[data-toolbar-text]');
-            button.dataset.indexText = settings.navigation.user.charAt(0);
-            button.dataset.iconText = settings.navigation.user.substring(0, 2);
-            if (buttonLabel) {
-              buttonLabel.textContent = settings.navigation.user;
-            }
-          });
-      });
-    },
-  };
-})(Drupal, drupalSettings, once);
diff --git a/core/modules/navigation/navigation.libraries.yml b/core/modules/navigation/navigation.libraries.yml
index 8385fba66ff219b0693f33197e6bbbd2c488cd0c..7121c6a7c5193472439ed5bf50aa84f91e4cd2f0 100644
--- a/core/modules/navigation/navigation.libraries.yml
+++ b/core/modules/navigation/navigation.libraries.yml
@@ -113,13 +113,3 @@ internal.safe-triangle:
   dependencies:
     - core/drupal
     - core/once
-
-internal.user-block:
-  # Internal library. Do not depend on it outside core nor add core usage
-  # beyond the Navigation module.
-  js:
-    js/user-block.js: {}
-  dependencies:
-    - core/drupal
-    - core/drupalSettings
-    - core/once
diff --git a/core/modules/navigation/src/Hook/NavigationHooks.php b/core/modules/navigation/src/Hook/NavigationHooks.php
index cd258fc8c95b50ee4f3945da453aa67ed203ddd2..8b2cd686bdcdc6368bc390b75d8ab671c9c90629 100644
--- a/core/modules/navigation/src/Hook/NavigationHooks.php
+++ b/core/modules/navigation/src/Hook/NavigationHooks.php
@@ -3,7 +3,6 @@
 namespace Drupal\navigation\Hook;
 
 use Drupal\Component\Plugin\PluginBase;
-use Drupal\Core\Asset\AttachedAssetsInterface;
 use Drupal\Core\Block\BlockPluginInterface;
 use Drupal\Core\Config\Action\ConfigActionManager;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -270,21 +269,6 @@ public function navigationWorkspaces(): array {
     ];
   }
 
-  /**
-   * Implements hook_js_settings_alter().
-   */
-  #[Hook('js_settings_alter')]
-  public function jsSettingsAlter(array &$settings, AttachedAssetsInterface $assets): void {
-    // If Navigation's user-block library is not installed, return.
-    if (!in_array('navigation/internal.user-block', $assets->getLibraries())) {
-      return;
-    }
-    // Provide the user name in drupalSettings to allow JavaScript code to
-    // customize the experience for the end user, rather than the server side,
-    // which would break the render cache.
-    $settings['navigation']['user'] = $this->currentUser->getAccountName();
-  }
-
   /**
    * Implements hook_modules_installed().
    */
diff --git a/core/modules/navigation/src/Plugin/Block/NavigationUserBlock.php b/core/modules/navigation/src/Plugin/Block/NavigationUserBlock.php
index 9df0e04c5fc616cedfd0538763eef212554f8d44..39c13acec221dbc94f952382b6e037e2bd050e1a 100644
--- a/core/modules/navigation/src/Plugin/Block/NavigationUserBlock.php
+++ b/core/modules/navigation/src/Plugin/Block/NavigationUserBlock.php
@@ -6,13 +6,13 @@
 
 use Drupal\Core\Block\Attribute\Block;
 use Drupal\Core\Block\BlockBase;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Menu\MenuLinkDefault;
 use Drupal\Core\Menu\MenuLinkTreeElement;
-use Drupal\Core\Menu\MenuLinkTreeInterface;
 use Drupal\Core\Menu\MenuTreeParameters;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Security\Attribute\TrustedCallback;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
-use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\user\Entity\User;
 
 /**
  * Defines a user navigation block.
@@ -23,103 +23,70 @@
   id: 'navigation_user',
   admin_label: new TranslatableMarkup('User'),
 )]
-final class NavigationUserBlock extends BlockBase implements ContainerFactoryPluginInterface {
+final class NavigationUserBlock extends BlockBase {
 
   const string NAVIGATION_LINKS_MENU = 'navigation-user-links';
 
-  /**
-   * Constructs a new SystemMenuBlock.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin ID for the plugin instance.
-   * @param array $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
-   *   The container.
-   * @param \Drupal\Core\Menu\MenuLinkTreeInterface $menuTree
-   *   The menu link tree.
-   */
-  public function __construct(
-    array $configuration,
-    $plugin_id,
-    $plugin_definition,
-    protected ContainerInterface $container,
-    protected MenuLinkTreeInterface $menuTree,
-  ) {
-    parent::__construct($configuration, $plugin_id, $plugin_definition);
-  }
-
   /**
    * {@inheritdoc}
    */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container,
-      $container->get('navigation.menu_tree'),
-    );
+  public function build(): array {
+    return [
+      '#create_placeholder' => TRUE,
+      '#lazy_builder' => [static::class . '::buildLinks', [$this->configuration['label']]],
+      '#cache' => [
+        'keys' => ['navigation_user_block'],
+      ],
+    ];
   }
 
   /**
-   * {@inheritdoc}
+   * Lazy builder callback.
    */
-  public function build(): array {
-    $menu_name = static::NAVIGATION_LINKS_MENU;
+  #[TrustedCallback]
+  public static function buildLinks(string $label): array {
     $parameters = new MenuTreeParameters();
     $parameters
       ->setMinDepth(0)
       ->setMaxDepth(2)
       ->onlyEnabledLinks();
-    $subtree = $this->menuTree->load($menu_name, $parameters);
+    /** @var \Drupal\Core\Menu\MenuLinkTreeInterface $menu_tree */
+    $menu_tree = \Drupal::service('navigation.menu_tree');
+    $subtree = $menu_tree->load(static::NAVIGATION_LINKS_MENU, $parameters);
 
+    // Load the current user so that they can be added as a cacheable dependency
+    // of the final render array.
+    $account = User::load(\Drupal::currentUser()->id());
+
+    $menu_definition = [
+      'menu_name' => static::NAVIGATION_LINKS_MENU,
+      'route_name' => 'user.page',
+      'route_parameters' => [],
+      'title' => $account->getDisplayName(),
+      'description' => '',
+      'options' => [],
+      'provider' => 'navigation',
+      'enabled' => '1',
+    ];
     // Create a parent link that serves as a wrapper.
     // If the menu is removed for any reason, this item shows a link to the
     // user profile page as a fallback.
-    $link = MenuLinkDefault::create($this->container, [], 'navigation.user_links.user.wrapper', $this->menuLinkDefinition());
+    $link = MenuLinkDefault::create(\Drupal::getContainer(), [], 'navigation.user_links.user.wrapper', $menu_definition);
     $tree = new MenuLinkTreeElement($link, TRUE, 1, FALSE, $subtree);
 
     $manipulators = [
       ['callable' => 'menu.default_tree_manipulators:checkAccess'],
       ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
     ];
-    $tree = $this->menuTree->transform([$tree], $manipulators);
-    $build = $this->menuTree->build($tree);
-    $build['#title'] = $this->configuration['label'];
-    $build += [
-      '#attached' => [
-        'library' => [
-          'navigation/internal.user-block',
-        ],
-      ],
-      '#attributes' => [
-        'data-user-block' => TRUE,
-      ],
-    ];
+    $tree = $menu_tree->transform([$tree], $manipulators);
+    $build = $menu_tree->build($tree);
+    $build['#title'] = $label;
+    $build['#cache']['contexts'][] = 'user';
+    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
+    $cacheable_metadata->addCacheableDependency($account);
+    $cacheable_metadata->applyTo($build);
 
     return $build;
   }
 
-  /**
-   * Custom wrapper element definition.
-   *
-   * @return array
-   *   The menu link definition.
-   */
-  protected function menuLinkDefinition(): array {
-    return [
-      'menu_name' => 'navigation-user-links',
-      'route_name' => 'user.page',
-      'title' => $this->t('My Account'),
-      'description' => '',
-      'options' => [],
-      'provider' => 'navigation',
-      'enabled' => '1',
-    ];
-
-  }
-
 }
diff --git a/core/modules/navigation/tests/src/Functional/NavigationShortcutsBlockTest.php b/core/modules/navigation/tests/src/Functional/NavigationShortcutsBlockTest.php
index d859663d90c6d4c92fb673040301bb72b1c6d72d..93fd7df80ca49f78e1495f3773d26964db394913 100644
--- a/core/modules/navigation/tests/src/Functional/NavigationShortcutsBlockTest.php
+++ b/core/modules/navigation/tests/src/Functional/NavigationShortcutsBlockTest.php
@@ -41,14 +41,15 @@ public function testNavigationBlock(): void {
 
     // Ensure that without enabling the shortcuts-in-page-title-link feature
     // in the theme, the shortcut_list cache tag is not added to the page.
-    $this->drupalLogin($this->drupalCreateUser([
+    $admin_user = $this->drupalCreateUser([
       'administer site configuration',
       'access navigation',
       'administer shortcuts',
       'access shortcuts',
-    ]));
+    ]);
+    $this->drupalLogin($admin_user);
     $this->drupalGet('admin/config/system/cron');
-    $expected_cache_tags = [
+    $expected_cache_tags = array_merge([
       'CACHE_MISS_IF_UNCACHEABLE_HTTP_METHOD:form',
       'block_view',
       'config:block.block.title',
@@ -61,7 +62,7 @@ public function testNavigationBlock(): void {
       'config:system.menu.navigation-user-links',
       'http_response',
       'rendered',
-    ];
+    ], $admin_user->getCacheTags());
     $this->assertCacheTags($expected_cache_tags);
 
     \Drupal::configFactory()
diff --git a/core/modules/navigation/tests/src/Functional/NavigationUserBlockTest.php b/core/modules/navigation/tests/src/Functional/NavigationUserBlockTest.php
index 94115bc52fe287635cf44c5b202e2afa185d7aed..ec14212edb149d3ece789312597baabbeecdb6d0 100644
--- a/core/modules/navigation/tests/src/Functional/NavigationUserBlockTest.php
+++ b/core/modules/navigation/tests/src/Functional/NavigationUserBlockTest.php
@@ -79,7 +79,7 @@ public function testNavigationUserBlock(): void {
     $this->verifyDynamicPageCache($test_page_url, 'HIT');
     // We should see the users name in the navigation menu.
     $rendered_user_name = $this->cssSelect('[aria-controls="navigation-link-navigationuser-linksuserwrapper"] > .toolbar-button__label')[0]->getText();
-    $this->assertEquals('My Account', $rendered_user_name);
+    $this->assertEquals($this->normalUser->getDisplayName(), $rendered_user_name);
 
     // We should see all three user links in the page.
     $link_labels = ['View profile', 'Edit profile', 'Log out'];
@@ -97,7 +97,7 @@ public function testNavigationUserBlock(): void {
     $this->verifyDynamicPageCache($test_page_url, 'MISS');
     $this->verifyDynamicPageCache($test_page_url, 'HIT');
     $rendered_user_name = $this->cssSelect('[aria-controls="navigation-link-navigationuser-linksuserwrapper"] > .toolbar-button__label')[0]->getText();
-    $this->assertEquals('My Account', $rendered_user_name);
+    $this->assertEquals($this->adminUser->getDisplayName(), $rendered_user_name);
     // The Edit profile link should link to the users edit profile page.
     $links = $this->getSession()->getPage()->findAll('named', ['link', 'Edit profile']);
     $this->assertStringContainsString('/user/edit', $links[0]->getAttribute('href'));
@@ -123,7 +123,7 @@ public function testNavigationUserBlockFallback(): void {
     $this->drupalLogin($this->normalUser);
     // We should see the users name in the navigation menu in a link.
     $rendered_user_name = $this->cssSelect('a.toolbar-button--icon--navigation-user-links-user-wrapper')[0]->getText();
-    $this->assertEquals('My Account', $rendered_user_name);
+    $this->assertEquals($this->normalUser->getDisplayName(), $rendered_user_name);
   }
 
 }
diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
index 9874723b82703cbfb01075be5eb4383b591fd1bd..974d9ddd05aaf690efed49cc17d5d44dccf6bb0a 100644
--- a/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
+++ b/core/modules/navigation/tests/src/FunctionalJavascript/PerformanceTest.php
@@ -89,7 +89,7 @@ public function testLogin(): void {
       ],
       'CacheDeleteCount' => 0,
       'CacheTagChecksumCount' => 3,
-      'CacheTagIsValidCount' => 29,
+      'CacheTagIsValidCount' => 30,
       'CacheTagInvalidationCount' => 0,
       'ScriptCount' => 2,
       'ScriptBytes' => 215500,