in src/JetBrains.Space.AspNetCore.Authentication/SpaceHandler.cs [104:142]
protected override 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);
}
#pragma warning disable 8620 // new Dictionary<string, string?> -> new FormUrlEncodedContent(tokenRequestParameters)
var requestContent = new FormUrlEncodedContent(tokenRequestParameters);
#pragma warning restore 8620
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint)
.WithClientAndSdkHeaders(SdkInfo.Version);
requestMessage.Headers.Authorization = AuthenticationHeaderValue.Parse(
"Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Options.ClientId}:{Options.ClientSecret}")));
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);
}
var error = "OAuth token endpoint failure: " + await Display(response);
return OAuthTokenResponse.Failed(new Exception(error));
}