I am trying to use Discord Authentication to sign to my app and I want to get the user information.
This my login method:
public static void Login(string clientId, string redirectUri)
{
var url = $"https://discord.com/api/oauth2/authorize?client_id={clientId}&redirect_uri={redirectUri}&response_type=code&scope=identify";
Console.WriteLine($"Redirecting to: {url}");
var ps = new ProcessStartInfo(url)
{
UseShellExecute = true,
Verb = "open"
};
Process.Start(ps);
}
And this is where I get the accesstoken and user information:
public static async Task<string> GetAccessTokenAsync(string clientId, string clientSecret, string code, string redirectUri)
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id", clientId),
new KeyValuePair<string, string>("client_secret", clientSecret),
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("scope", "identify"),
});
var response = await _client.PostAsync("https://discord.com/api/oauth2/token", content);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var accessTokenResponse = JsonSerializer.Deserialize<AccessTokenResponse>(json);
return accessTokenResponse.AccessToken;
}
public static async Task<(string, string)> GetUserInfoAsync(string accessToken)
{
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await _client.GetAsync("https://discord.com/api/users/@me");
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var user = JsonSerializer.Deserialize<User>(json);
return (user.Id, user.Username);
}
This is my json variable:
{
"access_token": "CF2CiBR4wb7VIY8VyDZbhOFeCdYFUw",
"expires_in": 604800,
"refresh_token": "PDV79lSv765ISV77HIAJL8mtJt2JeY",
"scope": "identify",
"token_type": "Bearer"
}
And this is my AccessTokenResponse model:
public class AccessTokenResponse
{
public string AccessToken { get; set; }
public int ExpiresIn { get; set; }
public string RefreshToken { get; set; }
public string Scope { get; set; }
public string TokenType { get; set; }
}
But the accesstoken is returning null. The response status is 200 ok. Where did I do wrong?
CodePudding user response:
Your C# model doesn't match the incoming JSON. Use the JsonPropertyName
attribute to map your properties to their JSON keys.
Note: For those using Newtonsoft.Json, it's the JsonProperty
attribute.
Specifically, take note of access_token
, expires_in
, refresh_token
, and token_type
and how each has an underscore (_
) in its name in the JSON but not your C#
model:
public string AccessToken { get; set; }
public int ExpiresIn { get; set; }
public string RefreshToken { get; set; }
public string TokenType { get; set; }
Adding the JsonPropertyName
attribute to your property resolves the issue while respecting C# naming conventions:
public class AccessTokenResponse
{
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
[JsonPropertyName("scope")] public string Scope { get; set; }
[JsonPropertyName("token_type")] public string TokenType { get; set; }
}