Support the authentication proofs of Symfony 8.2 - #322
Open
nicolas-grekas wants to merge 1 commit into
Open
nicolas-grekas wants to merge 1 commit into
nicolas-grekas wants to merge 1 commit into
Conversation
nicolas-grekas
force-pushed
the
authentication-proofs
branch
from
September 15, 2026 07:40
8938d13 to
d1a298f
Compare
nicolas-grekas
force-pushed
the
authentication-proofs
branch
from
September 15, 2026 07:41
d1a298f to
c152fa6
Compare
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? |
Author
|
This should ship in 8.2, end of November |
Owner
|
Should be doable :) |
Author
|
All merged in 8.2-dev now 馃殌 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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):
IS_AUTHENTICATED_RECENTLYandIS_AUTHENTICATED_VERY_RECENTLY, decided byAuthenticationTrustResolver::isAuthenticatedRecently()/isAuthenticatedVeryRecently(). Both methods are declared onAuthenticationTrustResolverInterfaceas@methodannotations; a resolver that does not implement them gets a deprecation and the attribute is denied ([Security] Decide IS_AUTHENTICATED_RECENTLY through the trust resolver聽symfony/symfony#66035, [Security] Add IS_AUTHENTICATED_VERY_RECENTLY, decided by the trust resolver聽symfony/symfony#66066).TokenInterface::getAuthenticationProofs()/setAuthenticationProofs(), a map of the authentication methods the user proved, as RFC 8176amrvalues (pwd,otp,hwk, ...), to the time of the last proof of each. Also@methodannotations in 8.2, implemented byAbstractToken; a token without them gets a deprecation and holds no proofs ([Security] Record which authentication methods were proven, and when聽symfony/symfony#66065).AuthenticationMethodBadge, which an authenticator adds to its passport to state which method it verified; the listener records it on the token, additively, so a second factor lands next to the password ([Security] Add AuthenticationMethodBadge, for an authenticator to state which methods it verified聽symfony/symfony#66069).Why it matters for this bundle
Scheb\TwoFactorBundle\Security\Authentication\AuthenticationTrustResolverdecoratessecurity.authentication.trust_resolverand implements the three interface methods only. On 8.2 the voter therefore finds noisAuthenticatedRecently()on it, logs the deprecation and deniesIS_AUTHENTICATED_RECENTLYfor every application using the bundle. The two methods are added, delegating to the decorated resolver when it has them, and answeringfalsefor aTwoFactorTokenInterface, likeisFullFledged()does.TwoFactorTokenimplementsTokenInterfacedirectly with its own attribute bag, so it has no proofs. Since the bundle swaps the token onAuthenticationTokenCreatedEvent, theTwoFactorTokenis 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.TwoFactorAuthenticatoradds anAuthenticationMethodBadgefor the provider whose code it checks, when the provider says which method it verifies. That is a new optionalAuthenticationMethodProviderInterfacewith one method,getAuthenticationMethod(): string, implemented by the TOTP, Google Authenticator and email providers (all returnotp). 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.TwoFactorProviderRegistryis a new, optional, last constructor argument ofTwoFactorAuthenticator, wired in the bundle's service definition.TwoFactorProviderInterfaceis untouched; the new interface is opt-in.otpvalue for the email provider is a judgement call: RFC 8176 has no value for an emailed code, andotp("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
AuthenticationMethodBadgeexists 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.