mirror of
https://github.com/yawaflua/Discord.Net.git
synced 2025-12-09 03:49:36 +02:00
Refactor OAuth handling and add GetAuthorizationUrl method
This commit is contained in:
@@ -103,10 +103,10 @@ public class DiscordOAuth : IDiscord
|
|||||||
|
|
||||||
var response = await _httpClient.PostAsync("https://discord.com/api/oauth2/token", content);
|
var response = await _httpClient.PostAsync("https://discord.com/api/oauth2/token", content);
|
||||||
var responseString = await response.Content.ReadAsStringAsync();
|
var responseString = await response.Content.ReadAsStringAsync();
|
||||||
var authToken = JsonSerializer.Deserialize<OAuthToken>(responseString);
|
var authToken = JsonSerializer.Deserialize<TokenDto>(responseString);
|
||||||
AccessToken = authToken?.AccessToken;
|
AccessToken = authToken?.AccessToken;
|
||||||
token = authToken;
|
token = OAuthToken.FromDTO(authToken, _httpClient, ClientId, ClientSecret);
|
||||||
return authToken;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISession CreateSession()
|
public ISession CreateSession()
|
||||||
@@ -117,5 +117,26 @@ public class DiscordOAuth : IDiscord
|
|||||||
throw new InvalidOperationException("Token is not set. Please call GetTokenAsync first.");
|
throw new InvalidOperationException("Token is not set. Please call GetTokenAsync first.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetAuthorizationUrl(string state)
|
||||||
|
{
|
||||||
|
|
||||||
|
var uri = new UriBuilder("https://discord.com/api/oauth2/authorize?");
|
||||||
|
|
||||||
|
var queryParameters = HttpUtility.ParseQueryString(uri.Query);
|
||||||
|
|
||||||
|
queryParameters["client_id"] = ClientId.ToString();
|
||||||
|
queryParameters["redirect_uri"] = RedirectUri;
|
||||||
|
queryParameters["response_type"] = "code";
|
||||||
|
queryParameters["scope"] = Scopes.ToString();
|
||||||
|
queryParameters["state"] = state;
|
||||||
|
queryParameters["prompt"] = Prompt ? "consent" : "none";
|
||||||
|
|
||||||
|
return uri + string.Join("&", queryParameters.AllKeys
|
||||||
|
.SelectMany(key => queryParameters.GetValues(key)!
|
||||||
|
.Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))))
|
||||||
|
.ToArray());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -70,28 +70,6 @@ internal class DiscordSession (IToken token, HttpClient httpClient, ScopesBuilde
|
|||||||
return await _req<DiscordConnection>("users/@me/connections");
|
return await _req<DiscordConnection>("users/@me/connections");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetAuthorizationUrl(string state)
|
|
||||||
{
|
|
||||||
|
|
||||||
NameValueCollection query = new()
|
|
||||||
{
|
|
||||||
["client_id"] = clientId.ToString(),
|
|
||||||
["redirect_uri"] = redirectUri,
|
|
||||||
["response_type"] = "code",
|
|
||||||
["scope"] = scopes.ToString(),
|
|
||||||
["state"] = state,
|
|
||||||
["prompt"] = prompt ? "consent" : "none"
|
|
||||||
};
|
|
||||||
|
|
||||||
var uriBuilder = new UriBuilder("https://discord.com/api/oauth2/authorize")
|
|
||||||
{
|
|
||||||
Query = query.ToString()
|
|
||||||
};
|
|
||||||
|
|
||||||
return uriBuilder.ToString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IToken GetToken(CancellationToken cancellationToken = default)
|
public IToken GetToken(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (token.AccessToken is null)
|
if (token.AccessToken is null)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace yawaflua.Discord.Net.Entities;
|
|||||||
internal class DiscordUser : IUser
|
internal class DiscordUser : IUser
|
||||||
{
|
{
|
||||||
[JsonPropertyName("id")]
|
[JsonPropertyName("id")]
|
||||||
public ulong Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("username")]
|
[JsonPropertyName("username")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
|||||||
@@ -7,15 +7,27 @@ namespace yawaflua.Discord.Net.Entities;
|
|||||||
|
|
||||||
internal class OAuthToken (HttpClient client, ulong ClientId, string ClientSecret) : IToken
|
internal class OAuthToken (HttpClient client, ulong ClientId, string ClientSecret) : IToken
|
||||||
{
|
{
|
||||||
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
|
public string AccessToken { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
|
public int ExpiresIn { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
|
public string RefreshToken { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("scope")] public string Scope { get; set; }
|
public string Scope { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("token_type")] public string TokenType { get; set; }
|
public string TokenType { get; set; }
|
||||||
|
|
||||||
|
public static OAuthToken FromDTO(TokenDto dto, HttpClient client, ulong ClientId, string ClientSecret)
|
||||||
|
{
|
||||||
|
return new(client, ClientId, ClientSecret)
|
||||||
|
{
|
||||||
|
AccessToken = dto.AccessToken,
|
||||||
|
ExpiresIn = dto.ExpiresIn,
|
||||||
|
RefreshToken = dto.RefreshToken,
|
||||||
|
Scope = dto.Scope,
|
||||||
|
TokenType = dto.TokenType
|
||||||
|
};
|
||||||
|
}
|
||||||
public Task RevokeAsync(CancellationToken cancellationToken = default)
|
public Task RevokeAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
using var request = new HttpRequestMessage(HttpMethod.Post, "https://discord.com/api/oauth2/token/revoke")
|
using var request = new HttpRequestMessage(HttpMethod.Post, "https://discord.com/api/oauth2/token/revoke")
|
||||||
|
|||||||
16
Entities/TokenDto.cs
Normal file
16
Entities/TokenDto.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace yawaflua.Discord.Net.Entities;
|
||||||
|
|
||||||
|
public class TokenDto
|
||||||
|
{
|
||||||
|
[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; }
|
||||||
|
}
|
||||||
@@ -6,4 +6,5 @@ public interface IDiscord
|
|||||||
{
|
{
|
||||||
Task<IToken?> GetTokenAsync(string code);
|
Task<IToken?> GetTokenAsync(string code);
|
||||||
ISession? CreateSession();
|
ISession? CreateSession();
|
||||||
|
string GetAuthorizationUrl(string state);
|
||||||
}
|
}
|
||||||
@@ -9,8 +9,6 @@ public interface ISession
|
|||||||
|
|
||||||
Task<IConnection?> GetConnectionAsync(CancellationToken cancellationToken = default);
|
Task<IConnection?> GetConnectionAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
|
||||||
string GetAuthorizationUrl(string state);
|
|
||||||
IToken GetToken(CancellationToken cancellationToken = default);
|
IToken GetToken(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ public interface IUser
|
|||||||
/// the user's id
|
/// the user's id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso href="https://discord.com/developers/docs/resources/user#user-object">User-object</seealso>
|
/// <seealso href="https://discord.com/developers/docs/resources/user#user-object">User-object</seealso>
|
||||||
public ulong Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the user's username, not unique across the platform
|
/// the user's username, not unique across the platform
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<RepositoryType>GIT</RepositoryType>
|
<RepositoryType>GIT</RepositoryType>
|
||||||
<PackageTags>Discord-OAuth2;Discord-OAuth-2;Discord-OAuth;DiscordOAuth;Discord;yawaflua;OAuth;OAuth-2;OAuth2</PackageTags>
|
<PackageTags>Discord-OAuth2;Discord-OAuth-2;Discord-OAuth;DiscordOAuth;Discord;yawaflua;OAuth;OAuth-2;OAuth2</PackageTags>
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
<Version>1.0.5</Version>
|
<Version>1.0.6</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user