Skip to content

Commit

Permalink
discord - update authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
diogotr7 committed Apr 11, 2024
1 parent 19944c5 commit ac52b89
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

<ItemGroup>
<PackageReference Include="JsonSubTypes" Version="2.0.1" />
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class DiscordAuthClient : DiscordAuthClientBase
public override string Origin => throw new NotSupportedException("Discord does not support a custom origin");
private readonly string _clientSecret;

public DiscordAuthClient(PluginSettings settings) : base(settings.GetSetting<SavedToken>("DiscordToken"))
public DiscordAuthClient(PluginSettings settings) : base(settings.GetSetting<string>("DiscordAccessToken"))
{
var clientIdSetting = settings.GetSetting<string>("DiscordClientId");
var clientSecretSetting = settings.GetSetting<string>("DiscordClientSecret");
Expand All @@ -26,9 +26,9 @@ public DiscordAuthClient(PluginSettings settings) : base(settings.GetSetting<Sav
_clientSecret = clientSecretSetting.Value!;
}

private bool AreClientIdAndSecretValid(PluginSetting<string> clientId, PluginSetting<string> clientSecret)
private static bool AreClientIdAndSecretValid(PluginSetting<string> clientId, PluginSetting<string> clientSecret)
{
return clientId.Value?.All(c => char.IsDigit(c)) == true && clientSecret.Value?.Length > 0;
return clientId.Value?.All(char.IsDigit) == true && clientSecret.Value?.Length > 0;
}

public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCode)
Expand All @@ -53,27 +53,27 @@ public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCo
return token;
}

public override async Task RefreshAccessTokenAsync()
{
if (!HasToken)
throw new InvalidOperationException("No token to refresh");

Dictionary<string, string> values = new()
{
["grant_type"] = "refresh_token",
["refresh_token"] = Token.Value!.RefreshToken,
["client_id"] = ClientId,
["client_secret"] = _clientSecret
};

using var response = await HttpClient.PostAsync("https://discord.com/api/oauth2/token", new FormUrlEncodedContent(values));
var responseString = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new UnauthorizedAccessException(responseString);
}

var token = JsonConvert.DeserializeObject<TokenResponse>(responseString)!;
SaveToken(token);
}
// public override async Task RefreshAccessTokenAsync()
// {
// if (!HasToken)
// throw new InvalidOperationException("No token to refresh");
//
// Dictionary<string, string> values = new()
// {
// ["grant_type"] = "refresh_token",
// ["refresh_token"] = Token.Value!.RefreshToken,
// ["client_id"] = ClientId,
// ["client_secret"] = _clientSecret
// };
//
// using var response = await HttpClient.PostAsync("https://discord.com/api/oauth2/token", new FormUrlEncodedContent(values));
// var responseString = await response.Content.ReadAsStringAsync();
// if (!response.IsSuccessStatusCode)
// {
// throw new UnauthorizedAccessException(responseString);
// }
//
// var token = JsonConvert.DeserializeObject<TokenResponse>(responseString)!;
// SaveToken(token);
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Artemis.Core;

namespace Artemis.Plugins.Modules.Discord.Authentication;

public abstract class DiscordAuthClientBase : IDiscordAuthClient
{
protected readonly HttpClient HttpClient = new();
protected readonly PluginSetting<string> Token;
protected DiscordAuthClientBase(PluginSetting<string> token)
{
Token = token;
}

public abstract string ClientId { get; }
public abstract string Origin { get; }
public string? AccessToken => Token.Value;
public abstract Task<TokenResponse> GetAccessTokenAsync(string challengeCode);

protected void SaveToken(TokenResponse newToken)
{
Token.Value = newToken.AccessToken;
Token.Save();
}

public void Dispose()
{
HttpClient.Dispose();
}
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,12 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Artemis.Core;

namespace Artemis.Plugins.Modules.Discord.Authentication;

public interface IDiscordAuthClient : IDisposable
{
string ClientId { get; }
string Origin { get; }
bool HasToken { get; }
string AccessToken { get; }
string? AccessToken { get; }
Task<TokenResponse> GetAccessTokenAsync(string challengeCode);
Task RefreshAccessTokenAsync();
}

public abstract class DiscordAuthClientBase : IDiscordAuthClient
{
protected HttpClient HttpClient = new();
protected readonly PluginSetting<SavedToken> Token;
protected DiscordAuthClientBase(PluginSetting<SavedToken> token)
{
Token = token;
}

public abstract string ClientId { get; }
public abstract string Origin { get; }
public bool HasToken => Token.Value != null;
public string AccessToken => Token.Value?.AccessToken ?? throw new InvalidOperationException("No token available");
public abstract Task<TokenResponse> GetAccessTokenAsync(string challengeCode);
public abstract Task RefreshAccessTokenAsync();
public void Dispose()
{
HttpClient.Dispose();
}

protected void SaveToken(TokenResponse newToken)
{
Token.Value = new SavedToken
{
AccessToken = newToken.AccessToken,
RefreshToken = newToken.RefreshToken,
ExpirationDate = DateTime.UtcNow.AddSeconds(newToken.ExpiresIn)
};
Token.Save();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class LogitechAuthClient : DiscordAuthClientBase
{
private const string TokenEndpoint = "https://ymj1tb3arf.execute-api.us-east-1.amazonaws.com/prod/create_discord_access_token";

public LogitechAuthClient(PluginSettings token) : base(token.GetSetting<SavedToken>("DiscordTokenLogitech"))
public LogitechAuthClient(PluginSettings token) : base(token.GetSetting<string>("DiscordAccessTokenLogitech"))
{
}

Expand All @@ -33,17 +33,17 @@ public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCo
return token;
}

public override async Task RefreshAccessTokenAsync()
{
var values = new Dictionary<string, string>
{
["refresh_token"] = Token.Value.RefreshToken
};

using var httpContent = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
using var response = await HttpClient.PostAsync(TokenEndpoint, httpContent);
var responseString = await response.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<TokenResponse>(responseString);
SaveToken(token);
}
// public override async Task RefreshAccessTokenAsync()
// {
// var values = new Dictionary<string, string>
// {
// ["refresh_token"] = Token.Value.RefreshToken
// };
//
// using var httpContent = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
// using var response = await HttpClient.PostAsync(TokenEndpoint, httpContent);
// var responseString = await response.Content.ReadAsStringAsync();
// var token = JsonConvert.DeserializeObject<TokenResponse>(responseString);
// SaveToken(token);
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class RazerAuthClient : DiscordAuthClientBase
private const string GrantEndpoint = "https://chroma.razer.com/discord/grant.php";
private const string RedirectUri = "http://chroma.razer.com/discord/";

public RazerAuthClient(PluginSettings token) : base(token.GetSetting<SavedToken>("DiscordTokenRazer"))
public RazerAuthClient(PluginSettings token) : base(token.GetSetting<string>("DiscordAccessTokenRazer"))
{
}

Expand All @@ -35,20 +35,20 @@ public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCo
SaveToken(token);
return token;
}

public override async Task RefreshAccessTokenAsync()
{
var values = new Dictionary<string, string>
{
["client_id"] = ClientId,
["grant_type"] = "refresh_token",
["refresh_token"] = Token.Value.RefreshToken,
["redirect_uri"] = RedirectUri
};

using var response = await HttpClient.PostAsync(RefreshEndpoint, new FormUrlEncodedContent(values));
var responseString = await response.Content.ReadAsStringAsync();
var tkn = JsonConvert.DeserializeObject<TokenResponse>(responseString);
SaveToken(tkn);
}
// public override async Task RefreshAccessTokenAsync()
// {
// var values = new Dictionary<string, string>
// {
// ["client_id"] = ClientId,
// ["grant_type"] = "refresh_token",
// ["refresh_token"] = Token.Value.RefreshToken,
// ["redirect_uri"] = RedirectUri
// };
//
// using var response = await HttpClient.PostAsync(RefreshEndpoint, new FormUrlEncodedContent(values));
// var responseString = await response.Content.ReadAsStringAsync();
// var tkn = JsonConvert.DeserializeObject<TokenResponse>(responseString);
// SaveToken(tkn);
// }
}
19 changes: 0 additions & 19 deletions src/Artemis.Plugins.Modules.Discord/Authentication/SavedToken.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class SteelseriesAuthClient : DiscordAuthClientBase
{
private const string TokenEndpoint = "https://id.steelseries.com/discord/auth";

public SteelseriesAuthClient(PluginSettings token) : base(token.GetSetting<SavedToken>("DiscordTokenSteelseries"))
public SteelseriesAuthClient(PluginSettings token) : base(token.GetSetting<string>("DiscordAccessTokenSteelseries"))
{
}

Expand All @@ -33,18 +33,18 @@ public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCo
return token;
}

public override async Task RefreshAccessTokenAsync()
{
var values = new Dictionary<string, string>
{
["client_id"] = ClientId,
["grant_type"] = "refresh_token",
["refresh_token"] = Token.Value.RefreshToken
};

using var response = await HttpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(values));
var responseString = await response.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<TokenResponse>(responseString);
SaveToken(token);
}
// public override async Task RefreshAccessTokenAsync()
// {
// var values = new Dictionary<string, string>
// {
// ["client_id"] = ClientId,
// ["grant_type"] = "refresh_token",
// ["refresh_token"] = Token.Value.RefreshToken
// };
//
// using var response = await HttpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(values));
// var responseString = await response.Content.ReadAsStringAsync();
// var token = JsonConvert.DeserializeObject<TokenResponse>(responseString);
// SaveToken(token);
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ namespace Artemis.Plugins.Modules.Discord.Authentication;

public class StreamKitAuthClient : DiscordAuthClientBase
{

public StreamKitAuthClient(PluginSettings token) : base(token.GetSetting<SavedToken>("DiscordTokenStreamKit"))
public StreamKitAuthClient(PluginSettings token) : base(token.GetSetting<string>("DiscordAccessTokenStreamKit"))
{
}

Expand All @@ -37,9 +36,9 @@ public override async Task<TokenResponse> GetAccessTokenAsync(string challengeCo
return token;
}

public override Task RefreshAccessTokenAsync()
{
// Streamkit tokens don't support refreshing, or at least I can't find anything about it
return Task.CompletedTask;
}
// public override Task RefreshAccessTokenAsync()
// {
// // Streamkit tokens don't support refreshing, or at least I can't find anything about it
// return Task.CompletedTask;
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Artemis.Plugins.Modules.Discord.DiscordPackets.CommandData;

public record Error(int Code, string Message);
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ public sealed class DiscordAuthorizeResponse : DiscordResponse<Authorize> { }
public sealed class DiscordAuthenticateResponse : DiscordResponse<Authenticate> { }
public sealed class DiscordGetVoiceSettingsResponse : DiscordResponse<VoiceSettings> { }
public sealed class DiscordSubscribeResponse : DiscordResponse<Subscription> { }
public sealed class DiscordGetSelectedVoiceChannelResponse : DiscordResponse<SelectedVoiceChannel> { }
public sealed class DiscordGetSelectedVoiceChannelResponse : DiscordResponse<SelectedVoiceChannel> { }
public sealed class DiscordErrorResponse : DiscordResponse<Error> { }
Loading

0 comments on commit ac52b89

Please sign in to comment.