@@ -264,6 +264,53 @@ public async Task OnValidateIdentityDoesNotRejectsWhenNotExpired()
264264 Assert . NotNull ( context . Principal ) ;
265265 }
266266
267+ [ Fact ]
268+ public async Task OnValidateIdentityDoesNotExtendExpirationWhenSlidingIsDisabled ( )
269+ {
270+ var user = new PocoUser ( "test" ) ;
271+ var httpContext = new Mock < HttpContext > ( ) ;
272+ var userManager = MockHelpers . MockUserManager < PocoUser > ( ) ;
273+ var identityOptions = new Mock < IOptions < IdentityOptions > > ( ) ;
274+ identityOptions . Setup ( a => a . Value ) . Returns ( new IdentityOptions ( ) ) ;
275+ var claimsManager = new Mock < IUserClaimsPrincipalFactory < PocoUser > > ( ) ;
276+ var options = new Mock < IOptions < SecurityStampValidatorOptions > > ( ) ;
277+ options . Setup ( a => a . Value ) . Returns ( new SecurityStampValidatorOptions { ValidationInterval = TimeSpan . FromMinutes ( 1 ) } ) ;
278+ var contextAccessor = new Mock < IHttpContextAccessor > ( ) ;
279+ contextAccessor . Setup ( a => a . HttpContext ) . Returns ( httpContext . Object ) ;
280+ var signInManager = new Mock < SignInManager < PocoUser > > ( userManager . Object ,
281+ contextAccessor . Object , claimsManager . Object , identityOptions . Object , null , new Mock < IAuthenticationSchemeProvider > ( ) . Object , new DefaultUserConfirmation < PocoUser > ( ) ) ;
282+ signInManager . Setup ( s => s . ValidateSecurityStampAsync ( It . IsAny < ClaimsPrincipal > ( ) ) ) . Returns ( Task . FromResult ( user ) ) ;
283+ signInManager . Setup ( s => s . CreateUserPrincipalAsync ( It . IsAny < PocoUser > ( ) ) ) . Returns ( Task . FromResult ( new ClaimsPrincipal ( new ClaimsIdentity ( "auth" ) ) ) ) ;
284+ signInManager . Setup ( s => s . SignInAsync ( user , false , null ) ) . Throws ( new Exception ( "Shouldn't be called" ) ) ;
285+ var services = new ServiceCollection ( ) ;
286+ services . AddSingleton ( options . Object ) ;
287+ services . AddSingleton ( signInManager . Object ) ;
288+ var clock = new SystemClock ( ) ;
289+ services . AddSingleton < ISecurityStampValidator > ( new SecurityStampValidator < PocoUser > ( options . Object , signInManager . Object , clock , new LoggerFactory ( ) ) ) ;
290+ httpContext . Setup ( c => c . RequestServices ) . Returns ( services . BuildServiceProvider ( ) ) ;
291+ var id = new ClaimsIdentity ( IdentityConstants . ApplicationScheme ) ;
292+ id . AddClaim ( new Claim ( ClaimTypes . NameIdentifier , user . Id ) ) ;
293+
294+ var ticket = new AuthenticationTicket ( new ClaimsPrincipal ( id ) ,
295+ new AuthenticationProperties
296+ {
297+ IssuedUtc = clock . UtcNow - TimeSpan . FromDays ( 1 ) ,
298+ ExpiresUtc = clock . UtcNow + TimeSpan . FromDays ( 1 ) ,
299+ } ,
300+ IdentityConstants . ApplicationScheme ) ;
301+ var context = new CookieValidatePrincipalContext ( httpContext . Object , new AuthenticationSchemeBuilder ( IdentityConstants . ApplicationScheme ) { HandlerType = typeof ( NoopHandler ) } . Build ( ) ,
302+ new CookieAuthenticationOptions ( ) { SlidingExpiration = false } , ticket ) ;
303+ Assert . NotNull ( context . Properties ) ;
304+ Assert . NotNull ( context . Options ) ;
305+ Assert . NotNull ( context . Principal ) ;
306+ await SecurityStampValidator . ValidatePrincipalAsync ( context ) ;
307+
308+ // Issued is moved forward, expires is not.
309+ Assert . Equal ( clock . UtcNow , context . Properties . IssuedUtc ) ;
310+ Assert . Equal ( clock . UtcNow + TimeSpan . FromDays ( 1 ) , context . Properties . ExpiresUtc ) ;
311+ Assert . NotNull ( context . Principal ) ;
312+ }
313+
267314 private async Task RunRememberClientCookieTest ( bool shouldStampValidate , bool validationSuccess )
268315 {
269316 var user = new PocoUser ( "test" ) ;
0 commit comments