oauth2.0 过帐表单URL将正文编码为字符串

8e2ybdfx  于 2023-03-17  发布在  其他
关注(0)|答案(1)|浏览(79)

我正在尝试从Discord的oauth2令牌端点获取访问令牌。我可以使用以下代码在JavaScript中完成此操作:

var bodyString = `client_id=${clientId}&client_secret=${clientSecret}&grant_type=authorization_code&code=${params['code']}&redirect_uri=https://localhost:4200/callback`;

  this.http
    .post('https://discord.com/api/v10/oauth2/token', bodyString, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
      },
    })
    .subscribe((response) => {
      console.log('response from post', response);
    });

值得注意的是,我没有构建参数的对象,而是将其放入字符串中以便端点接受。
现在我想用C#来完成这个任务,我尝试了以下方法:

var body = new Dictionary<string, string>
{
    { "client_id", _discordSettings.ClientId },
    {"client_secret",_discordSettings.ClientSecret},
    {"grant_type","authorization_code"},
    {"code", code},
    {"redirect_uri",redirectUrl}
};
var response = await Post<DiscordAccessTokenResponse>(_discordSettings.TokenAuthEndpoint, body);

其中职位定义如下:

public async Task<T?> Post<T>(string url, Dictionary<string, string> formBody)
{
    var client = _httpClientFactory.CreateClient(_httpClients.ToString());
    var req = new HttpRequestMessage(HttpMethod.Post, url) { Content = new FormUrlEncodedContent(formBody) };
    var apiResponse = await client.SendAsync(req);
    if (!apiResponse.IsSuccessStatusCode)
    {
        return default;
    }
    return await apiResponse.Content.ReadFromJsonAsync<T>();
}

但这会返回:

{
    "error": "unsupported_grant_type"
}

当我必须更改JavaScript方法以字符串形式发送时,也遇到了同样的错误。但是我不知道如何在C#中进行类似的更改。我如何在C#中以字符串形式发送application/x-www-form-urlencoded请求?

new9mtju

new9mtju1#

使用与下面类似的代码发送表单URL编码数据并接收JSON响应中的令牌:

using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Add("accept", "application/json");

    var credential = $"{this.configuration.ClientID}:{this.configuration.ClientSecret}";
    var basicCredential = Convert.ToBase64String(Encoding.UTF8.GetBytes(credential));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", basicCredential);

    var data = new[]
    {
        new KeyValuePair<string, string>("grant_type", "authorization_code"),
        new KeyValuePair<string, string>("redirect_uri", this.configuration.RedirectUri),
        new KeyValuePair<string, string>("code", code)
    };
                
    var response = await client.PostAsync(this.configuration.TokenEndpoint, new FormUrlEncodedContent(data));
    if (!response.IsSuccessStatusCode)
    {
        throw CreateOAuthError(response):
    }

    return await response.Content.ReadFromJsonAsync<TokenResponse>();
}

其中TokenResponse是一个简单的实体,如下所示:

public class TokenResponse
{
    [JsonPropertyName("access_token")]
    public string AccessToken { get; private set; }

    [JsonPropertyName("refresh_token")]
    public string RefreshToken { get; private set; }

    [JsonPropertyName("id_token")]
    public string IdToken { get; private set; }
}

相关问题