Я пытаюсь добавить Discord OAuth в мобильное приложение, используя PKCE . Я могу успешно пройти аутентификацию с помощью DiscordAPI и получаю обратно code
с сервера.
Однако, когда я пытаюсь вызвать конечную точку https://discordapp.com/api/oauth2/token
, я постоянно получаю Bad Request
результат.
Я пробовал несколько подходов к получению моего токена, но все они потерпели неудачу.
Попытка (1) с использованием HttpClient:
var nvc = new List<KeyValuePair<string, string>>();
nvc.Add(new KeyValuePair<string, string>("client_id", Constants.ClientId));
nvc.Add(new KeyValuePair<string, string>("client_secret", Constants.Secret));
nvc.Add(new KeyValuePair<string, string>("code_verifier", codeVerifier)); // method param
nvc.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
nvc.Add(new KeyValuePair<string, string>("code", authCode)); // method param
nvc.Add(new KeyValuePair<string, string>("redirect_uri", Constants.Redirect));
nvc.Add(new KeyValuePair<string, string>("scope", "identify email connections"));
var req = new HttpRequestMessage(HttpMethod.Post, "https://discordapp.com/api/oauth2/token")
{
Content = new FormUrlEncodedContent(nvc)
};
var authTokenResponse = await this.Client.SendAsync(req).ConfigureAwait(false);
// results in BadRequest
Я также пытался использовать StringContent
объект, подобный этому:
var stringContent = new StringContent($"grant_type=authorization_code&client_id={Constants.ClientId}&client_secret={Constants.Secret}&code_verifier={codeVerifier}&code={authCode}&redirect_uri={Constants.Redirect}&scopes=identify%20email%20connections", Encoding.UTF8, "application/x-www-form-urlencoded");
Оба эти результата в Bad Request
Попытка (2) с использованием RestSharp
var client = new RestSharp.RestClient($"{this.Client.BaseAddress}/oauth2/token");
var request = new RestRequest(Method.POST);
request.AddHeader("cache-control", "no-cache");
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddParameter("application/x-www-form-urlencoded", $"grant_type=authorization_code&client_id={Constants.ClientId}&client_secret={Constants.Secret}&code_verifier={code}&code={authCode}&redirect_uri={Constants.Redirect}&scopes=identify%20email%20connections", ParameterType.RequestBody);
var response = await client.ExecuteAsync(request);
Я тщательно проверил все свои значения и удостоверился, что мой Client Id и Secret верны. Я пытался отправить запрос с и без code_verifier
. Без code_verifier
я получаю Unauthorized
.
Вопрос
Как мне изменить мой запрос HttpClient для успешного получения моего токена аутентификации?
Дополнительная информация:
Чтобы соответствовать PKCE, мне нужен code_verifier
. Вот как я генерирую код. (Обратите внимание, я не пытаюсь использовать это как код авторизации.)
Random rng = new Random();
byte[] code = new byte[32];
rng.NextBytes(code);
CodeVerifier = Base64UrlEncoder.Encode(rng.ToString());
Затем я использую алгоритм хэширования, заимствованный из c -sharpcorner.com , который выглядит следующим образом:
using (SHA256 sha256Hash = SHA256.Create())
{
// ComputeHash - returns byte array
var bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
// Convert byte array to a string
var builder = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
builder.Append(bytes[i].ToString("x2"));
}
return builder.ToString();
}
Я передаю результат как code_challenge
, получая свой код авторизации.
Вот где я узнал, что требуется PKCE.
https://github.com/discordapp/discord-api-docs/issues/450
Здесь продолжается обсуждение PKCE:
https://github.com/discordapp/discord-api-docs/issues/1296
Обновление:
Хорошо, поэтому, основываясь на ответе iwokal , я перечитал посты, указанные выше, так что PKCE "требуется" только если вы используете Custom Scheme Redirect
, если вы просто с помощью перенаправления http
просто оставьте code_verifier
, и вы можете go.
При этом рабочий процесс PKCE недокументирован . Поскольку я потратил 500 баллов, я начисляю баллы тому, кто сможет решить рабочий процесс PKCE OAuth.
Вы можете приготовить решение с нуля, и я протестирую его.