@@ -507,14 +507,7 @@ protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync(
507507 // if any of the error fields are set, throw error null
508508 if ( ! string . IsNullOrEmpty ( authorizationResponse . Error ) )
509509 {
510- Logger . AuthorizationResponseError (
511- authorizationResponse . Error ,
512- authorizationResponse . ErrorDescription ?? "ErrorDecription null" ,
513- authorizationResponse . ErrorUri ?? "ErrorUri null" ) ;
514-
515- return AuthenticateResult . Fail ( new OpenIdConnectProtocolException (
516- string . Format ( CultureInfo . InvariantCulture , Resources . MessageContainsError , authorizationResponse . Error ,
517- authorizationResponse . ErrorDescription ?? "ErrorDecription null" , authorizationResponse . ErrorUri ?? "ErrorUri null" ) ) ) ;
510+ return AuthenticateResult . Fail ( CreateOpenIdConnectProtocolException ( authorizationResponse , response : null ) ) ;
518511 }
519512
520513 if ( _configuration == null && Options . ConfigurationManager != null )
@@ -590,6 +583,7 @@ protected override async Task<AuthenticateResult> HandleRemoteAuthenticateAsync(
590583 {
591584 return result ;
592585 }
586+
593587 authorizationResponse = tokenResponseReceivedContext . ProtocolMessage ;
594588 tokenEndpointResponse = tokenResponseReceivedContext . TokenEndpointResponse ;
595589
@@ -684,20 +678,50 @@ private void PopulateSessionProperties(OpenIdConnectMessage message, Authenticat
684678 }
685679
686680 /// <summary>
687- /// Redeems the authorization code for tokens at the token endpoint
681+ /// Redeems the authorization code for tokens at the token endpoint.
688682 /// </summary>
689683 /// <param name="tokenEndpointRequest">The request that will be sent to the token endpoint and is available for customization.</param>
690684 /// <returns>OpenIdConnect message that has tokens inside it.</returns>
691685 protected virtual async Task < OpenIdConnectMessage > RedeemAuthorizationCodeAsync ( OpenIdConnectMessage tokenEndpointRequest )
692686 {
693687 Logger . RedeemingCodeForTokens ( ) ;
688+
694689 var requestMessage = new HttpRequestMessage ( HttpMethod . Post , _configuration . TokenEndpoint ) ;
695690 requestMessage . Content = new FormUrlEncodedContent ( tokenEndpointRequest . Parameters ) ;
691+
696692 var responseMessage = await Backchannel . SendAsync ( requestMessage ) ;
697- responseMessage . EnsureSuccessStatusCode ( ) ;
698- var tokenResonse = await responseMessage . Content . ReadAsStringAsync ( ) ;
699- var jsonTokenResponse = JObject . Parse ( tokenResonse ) ;
700- return new OpenIdConnectMessage ( jsonTokenResponse ) ;
693+
694+ var contentMediaType = responseMessage . Content . Headers . ContentType ? . MediaType ;
695+ if ( string . IsNullOrEmpty ( contentMediaType ) )
696+ {
697+ Logger . LogDebug ( $ "Unexpected token response format. Status Code: { ( int ) responseMessage . StatusCode } . Content-Type header is missing.") ;
698+ }
699+ else if ( ! string . Equals ( contentMediaType , "application/json" , StringComparison . OrdinalIgnoreCase ) )
700+ {
701+ Logger . LogDebug ( $ "Unexpected token response format. Status Code: { ( int ) responseMessage . StatusCode } . Content-Type { responseMessage . Content . Headers . ContentType } .") ;
702+ }
703+
704+ // Error handling:
705+ // 1. If the response body can't be parsed as json, throws.
706+ // 2. If the response's status code is not in 2XX range, throw OpenIdConnectProtocolException. If the body is correct parsed,
707+ // pass the error information from body to the exception.
708+ OpenIdConnectMessage message ;
709+ try
710+ {
711+ var responseContent = await responseMessage . Content . ReadAsStringAsync ( ) ;
712+ message = new OpenIdConnectMessage ( responseContent ) ;
713+ }
714+ catch ( Exception ex )
715+ {
716+ throw new OpenIdConnectProtocolException ( $ "Failed to parse token response body as JSON. Status Code: { ( int ) responseMessage . StatusCode } . Content-Type: { responseMessage . Content . Headers . ContentType } ", ex ) ;
717+ }
718+
719+ if ( ! responseMessage . IsSuccessStatusCode )
720+ {
721+ throw CreateOpenIdConnectProtocolException ( message , responseMessage ) ;
722+ }
723+
724+ return message ;
701725 }
702726
703727 /// <summary>
@@ -1016,7 +1040,10 @@ private async Task<AuthorizationCodeReceivedContext> RunAuthorizationCodeReceive
10161040 return authorizationCodeReceivedContext ;
10171041 }
10181042
1019- private async Task < TokenResponseReceivedContext > RunTokenResponseReceivedEventAsync ( OpenIdConnectMessage message , OpenIdConnectMessage tokenEndpointResponse , AuthenticationProperties properties )
1043+ private async Task < TokenResponseReceivedContext > RunTokenResponseReceivedEventAsync (
1044+ OpenIdConnectMessage message ,
1045+ OpenIdConnectMessage tokenEndpointResponse ,
1046+ AuthenticationProperties properties )
10201047 {
10211048 Logger . TokenResponseReceived ( ) ;
10221049 var eventContext = new TokenResponseReceivedContext ( Context , Options , properties )
@@ -1157,5 +1184,27 @@ private string BuildRedirectUriIfRelative(string uri)
11571184
11581185 return BuildRedirectUri ( uri ) ;
11591186 }
1187+
1188+ private OpenIdConnectProtocolException CreateOpenIdConnectProtocolException ( OpenIdConnectMessage message , HttpResponseMessage response )
1189+ {
1190+ var description = message . ErrorDescription ?? "error_description is null" ;
1191+ var errorUri = message . ErrorUri ?? "error_uri is null" ;
1192+
1193+ if ( response != null )
1194+ {
1195+ Logger . ResponseErrorWithStatusCode ( message . Error , description , errorUri , ( int ) response . StatusCode ) ;
1196+ }
1197+ else
1198+ {
1199+ Logger . ResponseError ( message . Error , description , errorUri ) ;
1200+ }
1201+
1202+ return new OpenIdConnectProtocolException ( string . Format (
1203+ CultureInfo . InvariantCulture ,
1204+ Resources . MessageContainsError ,
1205+ message . Error ,
1206+ description ,
1207+ errorUri ) ) ;
1208+ }
11601209 }
11611210}
0 commit comments