/// <summary> /// Exchanges the authorization code for a authorization token from the remote provider. /// </summary> /// <param name="context">The <see cref="OAuthCodeExchangeContext"/>.</param> /// <returns>The response <see cref="OAuthTokenResponse"/>.</returns> protected virtual async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context) { var tokenRequestParameters = new Dictionary <string, string>() { { "client_id", Options.ClientId }, { "redirect_uri", context.RedirectUri }, { "client_secret", Options.ClientSecret }, { "code", context.Code }, { "grant_type", "authorization_code" }, }; // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier)) { tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier !); context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey); } var requestContent = new FormUrlEncodedContent(tokenRequestParameters !); var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint); requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); requestMessage.Content = requestContent; requestMessage.Version = Backchannel.DefaultRequestVersion; var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted); var body = await response.Content.ReadAsStringAsync(); return(response.IsSuccessStatusCode switch { true => OAuthTokenResponse.Success(JsonDocument.Parse(body)), false => PrepareFailedOAuthTokenReponse(response, body) });
protected virtual async Task <OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri, AuthenticationProperties properties) { var tokenRequestParameters = new Dictionary <string, string>() { { "client_id", Options.ClientId }, { "redirect_uri", redirectUri }, { "client_secret", Options.ClientSecret }, { "code", code }, { "grant_type", "authorization_code" }, }; var exchangeCodeContext = new OAuthExchangeCodeContext(properties, Context, Scheme, Options, tokenRequestParameters); await Events.OnExchangeCode(exchangeCodeContext); var requestContent = new FormUrlEncodedContent(tokenRequestParameters); var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint); requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); requestMessage.Content = requestContent; var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted); if (response.IsSuccessStatusCode) { var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return(OAuthTokenResponse.Success(payload)); } else { var error = "OAuth token endpoint failure: " + await Display(response); return(OAuthTokenResponse.Failed(new Exception(error))); } }
protected virtual async Task <OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context) { var tokenRequestParameters = new Dictionary <string, string>() { { "client_id", Options.ClientId }, { "redirect_uri", context.RedirectUri }, { "client_secret", Options.ClientSecret }, { "code", context.Code }, { "grant_type", "authorization_code" }, }; // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier)) { tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier); context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey); } var requestContent = new FormUrlEncodedContent(tokenRequestParameters); var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint); requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); requestMessage.Content = requestContent; var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted); if (response.IsSuccessStatusCode) { var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); return(OAuthTokenResponse.Success(payload)); } else { var error = "OAuth token endpoint failure: " + await Display(response); return(OAuthTokenResponse.Failed(new Exception(error))); } }