Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Security] Decide IS_AUTHENTICATED_RECENTLY through the trust resolver - #66035

Open
nicolas-grekas wants to merge 1 commit into
is-authenticated-recently-entry-pointfrom
is-authenticated-recently-trust-resolver
Open

[Security] Decide IS_AUTHENTICATED_RECENTLY through the trust resolver#66035
nicolas-grekas wants to merge 1 commit into
is-authenticated-recently-entry-pointfrom
is-authenticated-recently-trust-resolver

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Sep 13, 2026

Copy link
Copy Markdown
Member
Q A
Branch? 8.2
Bug fix? no
New feature? yes
Deprecations? yes
Issues -
License MIT

Part 4 of the sudo mode stack, on top of #66016. This answers the point raised on #66014: time is a reasonable default but a poor sole signal, and an application should be able to weigh other risk factors, such as whether the IP address changed since the last authentication, a last-activity timer, or a recently confirmed second factor.

AuthenticationTrustResolver::isAuthenticatedRecently() is where that decision now lives, so overriding it replaces the whole strategy without touching the attribute it answers:

class StepUpTrustResolver extends AuthenticationTrustResolver
{
    public function isAuthenticatedRecently(?TokenInterface $token = null): bool
    {
        return parent::isAuthenticatedRecently($token) && $this->sameClientAsAtLogin($token);
    }
}

BC

The method is announced with @method on AuthenticationTrustResolverInterface rather than declared on it, so DebugClassLoader reports a custom resolver that does not implement it, and until the method joins the interface in 9.0 AuthenticatedVoter denies IS_AUTHENTICATED_RECENTLY for such a resolver rather than guessing. Failing closed is the right direction for an authorization attribute, and it keeps the voter free of a second copy of the strategy. Covered under #[Group('legacy')].

The lifetime and the clock move from AuthenticatedVoter to AuthenticationTrustResolver, which is where the strategy now is; the voter takes only the trust resolver again. Both arguments were introduced in #66014 in this same stack and have never been released, so nothing is owed for the move. security.recent_authentication_lifetime is unchanged, it is simply wired to the trust resolver instead.

Being full fledged stays an invariant of the attribute

The voter keeps checking isFullFledged() itself before consulting the strategy. That is not distrust of the resolver: it is that the relationship between the attributes belongs to the attribute, not to the strategy. IS_AUTHENTICATED_RECENTLY is strictly stronger than IS_AUTHENTICATED_FULLY, and a remember-me cookie is precisely not proof that the user still holds their credentials, so the easiest possible override (returning true from some risk heuristic) must not be able to grant sudo on one. A test pins it.

It is not over-restrictive either: isFullFledged() is itself a method of the trust resolver, so an application that redefines what full fledged means still has that respected. The default isAuthenticatedRecently() keeps its own guard as well, because it is public API that can be called on its own; an override does not need to repeat it.

Deliberately unchanged

A last-activity timer is the one signal on that list that would be wrong to fold into the default. Refreshing the stamp on activity would make the attribute measure presence rather than possession of credentials, which is the opposite of what sudo mode is for. An application that genuinely wants that can express it in an override, which is exactly why this is an extension point rather than a config flag.

@nicolas-grekas
nicolas-grekas added this pull request to stack #66017 September 13, 2026 08:43
@symfony symfony deleted a comment from carsonbot Sep 13, 2026
@symfony symfony deleted a comment from carsonbot Sep 13, 2026
@nicolas-grekas
nicolas-grekas force-pushed the is-authenticated-recently-trust-resolver branch from 3272500 to 1998c56 Compare September 13, 2026 08:54
Time is a reasonable default but a poor sole signal: an application may want to weigh
whether the IP address changed, how long ago the last activity was, or whether a second
factor was confirmed recently. AuthenticationTrustResolver::isAuthenticatedRecently()
is where that decision now lives, so overriding it replaces the strategy without
touching the attribute it answers.

The method is announced with @method on the interface rather than declared on it, so a
custom trust resolver keeps working and gets a deprecation until 9.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants