---
title: "Feature: #106743 - Introduce Sudo-Mode Events"
manual: "TYPO3 Core Changelog"
version: "main"
permalink: "https://docs.typo3.org/permalink/changelog:feature-106743-1747931468"
source: "Changelog/12.4.x/Feature-106743-IntroduceSudoModeEvents.rst"
typo3-version: "12.4.x"
typo3-major: 12
type: "feature"
issue: 106743
forge: "https://forge.typo3.org/issues/106743"
tags: ["Backend", "ext:backend"]
rendered: "2026-09-20T18:31:11+00:00"
---

# Feature: #106743 - Introduce Sudo-Mode Events {#feature-106743-1747931468}

See [forge#106743](https://forge.typo3.org/issues/106743)

## Description {#description}

The fix for the security advisory [TYPO3-CORE-SA-2025-013](https://typo3.org/security/advisory/typo3-core-sa-2025-013)
requires step-up authentication when attempting to manipulate backend user accounts.
However, this behavior may pose challenges when integrating remote single sign-on (SSO)
providers, as these typically do not support a dedicated step-up authentication process.

To address this, new PSR-14 events have been introduced:

-   `\TYPO3\CMS\Backend\Security\SudoMode\Event\SudoModeRequiredEvent` is triggered before
    showing the sudo-mode verification dialog
-   `\TYPO3\CMS\Backend\Security\SudoMode\Event\SudoModeVerifyEvent` is triggered before
    actually verifying the submitted password

This event allows developers to conditionally bypass and adjust the step-up authentication
process based on custom logic, such as identifying users authenticated through an SSO system.

### Example {#example}

The following example demonstrates how to use an event listener to skip the step-up authentication
for persisted `be_users` records with an active `is_sso` flag:

**EXT:my_extension/Configuration/Services.yaml**

```yaml
services:
  Vendor\MyExtension\EventListener\SkipSudoModeDialog:
    tags:
      - name: event.listener
        identifier: 'ext-myextension/skip-sudo-mode-dialog'
  Vendor\MyExtension\EventListener\StaticPasswordVerification:
    tags:
      - name: event.listener
        identifier: 'ext-myextension/static-password-verification'
```

**EXT:my_extension/Classes/EventListener/SkipSudoModeDialog.php**

```php
<?php
declare(strict_types=1);

namespace Vendor\MyExtension\EventListener;

use TYPO3\CMS\Backend\Hooks\DataHandlerAuthenticationContext;
use TYPO3\CMS\Backend\Security\SudoMode\Access\AccessSubjectInterface;
use TYPO3\CMS\Backend\Security\SudoMode\Access\TableAccessSubject;
use TYPO3\CMS\Backend\Security\SudoMode\Event\SudoModeRequiredEvent;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Utility\MathUtility;

final class SkipSudoModeDialog
{
    public function __invoke(SudoModeRequiredEvent $event): void
    {
        // Ensure the event context matches DataHandler operations
        if ($event->getClaim()->origin !== DataHandlerAuthenticationContext::class) {
            return;
        }

        // Filter for TableAccessSubject types only
        $tableAccessSubjects = array_filter(
            $event->getClaim()->subjects,
            static fn (AccessSubjectInterface $subject): bool => $subject instanceof TableAccessSubject
        );

        // Abort if there are unhandled subject types
        if ($event->getClaim()->subjects !== $tableAccessSubjects) {
            return;
        }

        /** @var list<TableAccessSubject> $tableAccessSubjects */
        foreach ($tableAccessSubjects as $subject) {
            // Expecting format: tableName.fieldName.id
            if (substr_count($subject->getSubject(), '.') !== 2) {
                return;
            }

            [$tableName, $fieldName, $id] = explode('.', $subject->getSubject());

            // Only handle be_users table
            if ($tableName !== 'be_users') {
                return;
            }

            // Skip if ID is not a valid integer (e.g., 'NEW' records)
            if (!MathUtility::canBeInterpretedAsInteger($id)) {
                continue;
            }

            $record = BackendUtility::getRecord($tableName, $id);

            // Abort if any record does not use SSO
            if (empty($record['is_sso'])) {
                return;
            }
        }

        // All conditions met — disable verification
        $event->setVerificationRequired(false);
    }
}
```

**EXT:my_extension/Classes/EventListener/StaticPasswordVerification.php**

```php
<?php
declare(strict_types=1);

namespace Example\Demo\EventListener;

use TYPO3\CMS\Backend\Security\SudoMode\Event\SudoModeVerifyEvent;

final class StaticPasswordVerification
{
    public function __invoke(SudoModeVerifyEvent $event): void
    {
        $calculatedHash = hash('sha256', $event->getPassword());
        // static hash of `dontdothis` - just used as proof-of-concept
        // side-note: in production, make use of strong salted password
        $expectedHash = '3382f2e21a5471b52a85bc32ab59ab2c467f6e3cb112aef295323874f423994c';

        if (hash_equals($expectedHash, $calculatedHash)) {
            $event->setVerified(true);
        }
    }
}
```

## Impact {#impact}

This feature provides extension developers with a flexible mechanism to skip or adjust
step-up authentication during sensitive backend operations. It is especially useful in
environments utilizing SSO, where enforcing additional verification might not be feasible
or necessary. By hooking into the new `SudoModeRequiredEvent` and `SudoModeVerifyEvent`
custom logic and behavior can be applied on a case-by-case basis.
