@@ -541,7 +541,7 @@ protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync(
541541 Logger . ReceivedIdToken ( ) ;
542542 ticket = ValidateToken ( authorizationResponse . IdToken , properties , validationParameters , out jwt ) ;
543543
544- nonce = jwt ? . Payload . Nonce ;
544+ nonce = jwt . Payload . Nonce ;
545545 if ( ! string . IsNullOrEmpty ( nonce ) )
546546 {
547547 nonce = ReadNonceCookie ( nonce ) ;
@@ -599,22 +599,25 @@ protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync(
599599 authorizationResponse = tokenResponseReceivedContext . ProtocolMessage ;
600600 tokenEndpointResponse = tokenResponseReceivedContext . TokenEndpointResponse ;
601601
602- // We only have to process the IdToken if we didn't already get one in the AuthorizationResponse
603- if ( ticket == null )
604- {
605- // no need to validate signature when token is received using "code flow" as per spec
606- // [http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation].
607- validationParameters . RequireSignedTokens = false ;
602+ // no need to validate signature when token is received using "code flow" as per spec
603+ // [http://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation].
604+ validationParameters . RequireSignedTokens = false ;
608605
609- ticket = ValidateToken ( tokenEndpointResponse . IdToken , properties , validationParameters , out jwt ) ;
606+ // At least a cursory validation is required on the new IdToken, even if we've already validated the one from the authorization response.
607+ // And we'll want to validate the new JWT in ValidateTokenResponse.
608+ JwtSecurityToken tokenEndpointJwt ;
609+ var tokenEndpointTicket = ValidateToken ( tokenEndpointResponse . IdToken , properties , validationParameters , out tokenEndpointJwt ) ;
610610
611- nonce = jwt ? . Payload . Nonce ;
611+ // Avoid reading & deleting the nonce cookie, running the event, etc, if it was already done as part of the authorization response validation.
612+ if ( ticket == null )
613+ {
614+ nonce = tokenEndpointJwt . Payload . Nonce ;
612615 if ( ! string . IsNullOrEmpty ( nonce ) )
613616 {
614617 nonce = ReadNonceCookie ( nonce ) ;
615618 }
616619
617- var tokenValidatedContext = await RunTokenValidatedEventAsync ( authorizationResponse , tokenEndpointResponse , properties , ticket , jwt , nonce ) ;
620+ var tokenValidatedContext = await RunTokenValidatedEventAsync ( authorizationResponse , tokenEndpointResponse , properties , tokenEndpointTicket , tokenEndpointJwt , nonce ) ;
618621 if ( tokenValidatedContext . CheckEventResult ( out result ) )
619622 {
620623 return result ;
@@ -626,6 +629,15 @@ protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync(
626629 jwt = tokenValidatedContext . SecurityToken ;
627630 nonce = tokenValidatedContext . Nonce ;
628631 }
632+ else
633+ {
634+ if ( ! string . Equals ( jwt . Subject , tokenEndpointJwt . Subject , StringComparison . Ordinal ) )
635+ {
636+ throw new SecurityTokenException ( "The sub claim does not match in the id_token's from the authorization and token endpoints." ) ;
637+ }
638+
639+ jwt = tokenEndpointJwt ;
640+ }
629641
630642 // Validate the token response if it wasn't provided manually
631643 if ( ! authorizationCodeReceivedContext . HandledCodeRedemption )
0 commit comments