Skip to content

The Untappd provider sends token request parameters in both the query string and the request form #688

Open
@kevinchalet

Description

@kevinchalet

The Untappd provider uses GET requests and sends the token request parameters in both the query string and the request form using formurl-encoding, which is a strong sign something is not right as GET requests are not expected to have a content attached (.NET Core's HttpClient allows it, but on .NET Framework, the following code would throw an exception:)

protected override async Task<OAuthTokenResponse> ExchangeCodeAsync([NotNull] 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 parameters = new Dictionary<string, string?>
{
["client_id"] = Options.ClientId,
["redirect_uri"] = context.RedirectUri,
["client_secret"] = Options.ClientSecret,
["code"] = context.Code,
};
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, parameters);
using var requestContent = new FormUrlEncodedContent(tokenRequestParameters);
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, address);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = requestContent;
requestMessage.Version = Backchannel.DefaultRequestVersion;
using var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);
if (response.IsSuccessStatusCode)
{
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync(Context.RequestAborted));
return OAuthTokenResponse.Success(payload);
}
else
{
await Log.ExchangeCodeErrorAsync(Logger, response, Context.RequestAborted);
throw new HttpRequestException("An error occurred while exchanging token codes.");
}
}

We should determine whether this monstrosity is 100% required or remove the request form part if it's not.

/cc @martincostello

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions