1717package org .springframework .security .config .annotation .web .configurers ;
1818
1919import java .io .IOException ;
20+ import java .time .Clock ;
21+ import java .time .Duration ;
22+ import java .time .Instant ;
2023import java .util .ArrayList ;
2124import java .util .Collection ;
2225import java .util .HashSet ;
2730import jakarta .servlet .http .HttpServletRequest ;
2831import jakarta .servlet .http .HttpServletResponse ;
2932import org .jspecify .annotations .NullMarked ;
33+ import org .jspecify .annotations .Nullable ;
3034
3135import org .springframework .context .ApplicationContext ;
3236import org .springframework .security .authentication .AuthenticationManager ;
4044import org .springframework .security .core .AuthenticationException ;
4145import org .springframework .security .core .AuthenticationResult ;
4246import org .springframework .security .core .GrantedAuthority ;
47+ import org .springframework .security .core .authority .ExpirableGrantedAuthority ;
4348import org .springframework .security .core .authority .SimpleGrantedAuthority ;
4449import org .springframework .security .core .context .SecurityContextHolder ;
4550import org .springframework .security .core .context .SecurityContextHolderStrategy ;
@@ -92,6 +97,10 @@ public MfaConfigurer<B> grants(String... authority) {
9297 return grants (new SimpleAuthoritiesGranter (authority ));
9398 }
9499
100+ public MfaConfigurer <B > grants (Duration duration , String ... authority ) {
101+ return grants (new SimpleAuthoritiesGranter (duration , authority ));
102+ }
103+
95104 @ Override
96105 public void init (B http ) {
97106 ApplicationContext context = http .getSharedObject (ApplicationContext .class );
@@ -170,9 +179,20 @@ public AuthenticationResult grantAuthorities(AuthenticationResult authentication
170179
171180 static final class SimpleAuthoritiesGranter implements AuthoritiesGranter {
172181
182+ private final @ Nullable Duration grantingTime ;
183+
173184 private final Collection <String > authorities ;
174185
186+ private Clock clock = Clock .systemUTC ();
187+
175188 SimpleAuthoritiesGranter (String ... authorities ) {
189+ this .grantingTime = null ;
190+ this .authorities = List .of (authorities );
191+ }
192+
193+ SimpleAuthoritiesGranter (Duration grantingTime , String ... authorities ) {
194+ Assert .notEmpty (authorities , "authorities cannot be empty" );
195+ this .grantingTime = grantingTime ;
176196 this .authorities = List .of (authorities );
177197 }
178198
@@ -185,13 +205,23 @@ public Collection<String> grantableAuthorities() {
185205 public AuthenticationResult grantAuthorities (AuthenticationResult authentication ) {
186206 Collection <GrantedAuthority > toGrant = new HashSet <>();
187207 for (String authority : this .authorities ) {
188- toGrant .add (new SimpleGrantedAuthority (authority ));
208+ if (this .grantingTime == null ) {
209+ toGrant .add (new SimpleGrantedAuthority (authority ));
210+ }
211+ else {
212+ Instant expiresAt = this .clock .instant ().plus (this .grantingTime );
213+ toGrant .add (new ExpirableGrantedAuthority (authority , expiresAt ));
214+ }
189215 }
190216 Collection <GrantedAuthority > current = new HashSet <>(authentication .getAuthorities ());
191217 toGrant .addAll (current );
192218 return authentication .withGrantedAuthorities (toGrant );
193219 }
194220
221+ void setClock (Clock clock ) {
222+ this .clock = clock ;
223+ }
224+
195225 }
196226
197227 @ NullMarked
0 commit comments