Skip to content

[Auth] refact!: Remove legacy auth challenges support#8044

Merged
bastianallgeier merged 1 commit intov6/refact/authfrom
v6/refact/auth-remove-legacy-challenge
Apr 15, 2026
Merged

[Auth] refact!: Remove legacy auth challenges support#8044
bastianallgeier merged 1 commit intov6/refact/authfrom
v6/refact/auth-remove-legacy-challenge

Conversation

@distantnative
Copy link
Copy Markdown
Member

@distantnative distantnative commented Mar 22, 2026

Description

Working on the frontend (login view) for the auth refactoring, it has become quite apparent to me how difficult it is to support old aunt challenges here. It's just a lot of wrappers and shortcomings. Which is why I propose to already do the breaking change directly in Kirby 6.

Changelog

🚨 Breaking changes

  • Custom auth challenges extending Kirby\Cms\Auth\Challenge have to be adapted to use Kirby\Auth\Challenge

Docs

Kirby 6 redesigns auth challenges around a new Kirby\Auth\Challenge base class with instance methods and a Pending data object. The Kirby 5 base class (Kirby\Cms\Auth\Challenge) used static methods and a different return convention. Any Kirby plugin that provides a custom authChallenges extension and was written for Kirby 5, extending Kirby\Cms\Auth\Challenge or any of its subclasses Kirby\Cms\Auth\EmailChallenge or Kirby\Cms\Auth\TotpChallenge need to be adapted.

In Kirby 5

use Kirby\Cms\Auth\Challenge;
use Kirby\Cms\User;

class SmsChallenge extends Challenge
{
    public static function isAvailable(User $user, string $mode): bool
    {
        return $user->content()->get('phone')->isNotEmpty();
    }

    public static function create(User $user, array $options): string|null
    {
        $code = random_int(100000, 999999);
        sendSms($user->content()->phone(), $code);
        return (string)$code; // Kirby hashed and stored this for you
    }

    // verify() was optional; the base class checked the session hash
}

In Kirby 6

use Kirby\Auth\Challenge;
use Kirby\Auth\Pending;
use Kirby\Cms\User;

class SmsChallenge extends Challenge
{
    public static function isAvailable(User $user, string $mode): bool
    {
        return $user->content()->get('phone')->isNotEmpty();
    }

    public function create(): Pending|null
    {
        $code = random_int(100000, 999999);
        sendSms($this->user->content()->phone(), $code);

        // Return a Pending object. You are responsible for hashing.
        // `secret` is kept server-side; `public` is sent to the frontend.
        return new Pending(
            secret: password_hash((string)$code, PASSWORD_DEFAULT)
        );
    }

    // verify() is now required and receives the Pending from create()
    public function verify(mixed $input, Pending $data): bool
    {
        return password_verify($code, $data->secret());
    }
}

Plugin registration is unchanged:

Kirby::plugin('your/plugin', [
    'authChallenges' => [
        'sms' => SmsChallenge::class,
    ],
]);

The Pending object

Pending carries two optional slots:

new Pending(
    public: '***-1234',
    secret: $hash // kept server-side, passed back to verify()
);

For most challenges you only need secret. Use public when you want to pass display information to the Panel (e.g. masked phone number for UI display).

TOTP / app-based challenges (no code returned from create)

If your challenge generates no code itself (the user's app does), return null from create() and do all verification in verify():

public function create(): Pending|null
{
    return null; // nothing to generate or send
}

public function verify(mixed $input, Pending $data): bool
{
    $totp = new Totp($this->user->secret('totp'));
    return $totp->verify((string)$input);
}

For review team

  • Add changes & docs to release notes draft in Notion

@distantnative distantnative self-assigned this Mar 22, 2026
@distantnative distantnative force-pushed the v6/refact/auth-remove-legacy-challenge branch 3 times, most recently from b38fd5f to c6c404c Compare March 22, 2026 11:52
@distantnative distantnative changed the title refact!: Remove legacy auth challenges support [Auth] refact!: Remove legacy auth challenges support Mar 22, 2026
@distantnative distantnative force-pushed the v6/refact/auth-remove-legacy-challenge branch from c6c404c to fe5c71e Compare March 22, 2026 20:00
@distantnative distantnative force-pushed the v6/refact/auth-remove-legacy-challenge branch 2 times, most recently from 92c09f4 to e033c5e Compare April 14, 2026 07:54
BREAKING CHANGE: Custom auth challenges extending `Kirby\Cms\Auth\Challenge` have to be adapted to use `Kirby\Auth\Challenge`
@distantnative distantnative force-pushed the v6/refact/auth-remove-legacy-challenge branch from e033c5e to e67ecd2 Compare April 14, 2026 07:58
@distantnative distantnative marked this pull request as ready for review April 14, 2026 10:12
@bastianallgeier bastianallgeier merged commit b0b3224 into v6/refact/auth Apr 15, 2026
13 checks passed
@bastianallgeier bastianallgeier deleted the v6/refact/auth-remove-legacy-challenge branch April 15, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants