Skip to content

Support the authentication proofs of Symfony 8.2 - #322

Open
nicolas-grekas wants to merge 1 commit into
scheb:8.xfrom
nicolas-grekas:authentication-proofs
Open

nicolas-grekas wants to merge 1 commit into
scheb:8.xfrom
nicolas-grekas:authentication-proofs

Conversation

@nicolas-grekas

Copy link
Copy Markdown

Symfony 8.2 adds a "recent authentication" system to the Security component, and three of its pieces touch what this bundle decorates or replaces. This PR adapts the bundle to them while keeping it working unchanged on Symfony 7.4, 8.0 and 8.1.

What Symfony 8.2 adds (symfony/symfony#66064 has the whole design):

Why it matters for this bundle

  1. Scheb\TwoFactorBundle\Security\Authentication\AuthenticationTrustResolver decorates security.authentication.trust_resolver and implements the three interface methods only. On 8.2 the voter therefore finds no isAuthenticatedRecently() on it, logs the deprecation and denies IS_AUTHENTICATED_RECENTLY for every application using the bundle. The two methods are added, delegating to the decorated resolver when it has them, and answering false for a TwoFactorTokenInterface, like isFullFledged() does.
  2. TwoFactorToken implements TokenInterface directly with its own attribute bag, so it has no proofs. Since the bundle swaps the token on AuthenticationTokenCreatedEvent, the TwoFactorToken is what Symfony's listener sees when the first factor succeeds, and the password proof was lost. Both methods are added and delegate to the wrapped token, which is the one that ends up authenticated once 2fa completes.
  3. TwoFactorAuthenticator adds an AuthenticationMethodBadge for the provider whose code it checks, when the provider says which method it verifies. That is a new optional AuthenticationMethodProviderInterface with one method, getAuthenticationMethod(): string, implemented by the TOTP, Google Authenticator and email providers (all return otp). A provider that does not implement it keeps working, and its proof is recorded as unspecified by Symfony.

With the three, a Symfony 8.2 policy can require a second factor, e.g. isset($token->getAuthenticationProofs()['otp']), which is the level-of-assurance use case the RFC describes.

Backward compatibility

  • method_exists() / class_exists() guards everywhere the 8.2 API is used, so nothing changes on older Symfony versions; the added methods on the resolver and the token are plain additions.
  • The TwoFactorProviderRegistry is a new, optional, last constructor argument of TwoFactorAuthenticator, wired in the bundle's service definition.
  • TwoFactorProviderInterface is untouched; the new interface is opt-in.
  • The otp value for the email provider is a judgement call: RFC 8176 has no value for an emailed code, and otp ("one-time password") is the closest. mca (multiple-channel) would be the alternative if you prefer to distinguish it from an authenticator app.

The test for the badge is skipped until AuthenticationMethodBadge exists in the installed Symfony version; everything else runs on 8.1. phpcs and psalm are clean; php-cs-fixer was not run, as it is not part of the dev dependencies.

@scheb

scheb commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Good stuff! Will have a closer look at it, once I find some time. Thanks for opening up the PR!

Is there any timeline on this?

@nicolas-grekas

Copy link
Copy Markdown
Author

This should ship in 8.2, end of November

@scheb

scheb commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Should be doable :)

@nicolas-grekas

Copy link
Copy Markdown
Author

All merged in 8.2-dev now 馃殌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants