From 521153dd1b459c60167255a55607f1ced96be2a4 Mon Sep 17 00:00:00 2001 From: wcartagenaasc Date: Mon, 4 Mar 2024 21:04:12 -0500 Subject: [PATCH 1/2] Updated git ignore file --- .gitignore | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 29622e2..60c1f99 100644 --- a/.gitignore +++ b/.gitignore @@ -22,10 +22,6 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -# Database file -/Sqlite3Destiny2DB.zip -/Extractions/Sqlite3Destiny2DB.sqlite3 - # User-specific files *.rsuser *.suo @@ -36,11 +32,20 @@ yarn-error.log* # Visual Studio /.vs -/database/bin -/database/obj # Rider .idea/ +# Database /guardians-central.sln -/database/config.toml \ No newline at end of file +/database/config.toml +/database/bin +/database/obj +/Sqlite3Destiny2DB.zip +/Extractions/Sqlite3Destiny2DB.sqlite3 + +# Server +/server/node_modules +/server/config.toml + +/config.toml \ No newline at end of file From acee7fbf5aab885e36cdf8f2ed541da8358d4d56 Mon Sep 17 00:00:00 2001 From: Adriel Martinez Date: Tue, 23 Apr 2024 23:08:50 -0400 Subject: [PATCH 2/2] Latest commit for this branch --- .gitignore | 11 ++- Authenticate/Authenticate.csproj | 15 ++++ Authenticate/GenerateToken.cs | 74 ++++++++++++++++ Authenticate/Workers/Tokenizer.cs | 137 ++++++++++++++++++++++++++++++ guardians-central.sln | 6 ++ 5 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 Authenticate/Authenticate.csproj create mode 100644 Authenticate/GenerateToken.cs create mode 100644 Authenticate/Workers/Tokenizer.cs diff --git a/.gitignore b/.gitignore index 60c1f99..d8c4bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,13 @@ yarn-error.log* /server/node_modules /server/config.toml -/config.toml \ No newline at end of file +/config.toml + +# Authenticate +/Authenticate/config.toml +/Authenticate/bin +/Authenticate/obj + +#Requests +/Requests/bin +/Requests/obj \ No newline at end of file diff --git a/Authenticate/Authenticate.csproj b/Authenticate/Authenticate.csproj new file mode 100644 index 0000000..e0d3cd2 --- /dev/null +++ b/Authenticate/Authenticate.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + diff --git a/Authenticate/GenerateToken.cs b/Authenticate/GenerateToken.cs new file mode 100644 index 0000000..2861751 --- /dev/null +++ b/Authenticate/GenerateToken.cs @@ -0,0 +1,74 @@ +using Nett; + +class Program{ + static async Task Main(){ + + // Gets all the data from TOML File + var table = Toml.ReadFile("config.toml"); + + string? ClientID = table.ClientID; + string? ClientSecret = table.ClientSecret; + + try{ + + string? Code = table.Code; + string? AccessToken = table.AccessToken; + // No value for Access token is not in toml file + if (string.IsNullOrEmpty(AccessToken)){ + var (accessToken, refreshToken) = await Tokenizer.GetAccessToken(ClientID, ClientSecret, Code); + + Console.WriteLine("Access Token: " + accessToken.Token); + Console.WriteLine("Refresh Token: " + refreshToken.Token); + // Create a TomlObject with the access token string value + //var accessTokenTomlObject = Toml.Create(accessToken.Token); + + //var config = Toml.ReadFile("config.toml"); + table.AccessToken = accessToken.Token; + table.AccessTokenExpiresAt = accessToken.Expiration; + + table.RefreshToken = refreshToken.Token; + table.RefreshTokenExpiresAt = refreshToken.Expiration; + + // Console.WriteLine(accessTokenTomlObject); + + // Update the AccessToken value in the TOML table + //table["AccessToken"] = accessTokenTomlObject; + //table["AccessToken"] = accessToken.Token; + Toml.WriteFile(table, "config.toml"); + } + else{ + DateTime AccessTokenExpiresAt = table.AccessTokenExpiresAt; + + string? RefreshToken = table.RefreshToken; + + if (Tokenizer.IsTokenValid(AccessTokenExpiresAt) == false){ + var (accessToken, refreshToken) = await Tokenizer.RefreshAccessToken(ClientID, ClientSecret, RefreshToken); + + table.AccessToken = accessToken.Token; + table.AccessTokenExpiresAt = accessToken.Expiration; + + table.RefreshToken = refreshToken.Token; + table.RefreshTokenExpiresAt = refreshToken.Expiration; + + Toml.WriteFile(table, "config.toml"); + } + } + } + catch (Exception ex){ + // Handle exceptions + Console.WriteLine("An error occurred: " + ex.Message); + } + } +} + +class Config{ + public string? APIKey { get; set; } + public string? ClientID { get; set; } + public string? ClientSecret { get; set; } + public string? Code { get; set; } + public string? AccessToken { get; set; } + public DateTime AccessTokenExpiresAt { get; set; } + public string? RefreshToken { get; set; } + public DateTime RefreshTokenExpiresAt { get; set; } + +} \ No newline at end of file diff --git a/Authenticate/Workers/Tokenizer.cs b/Authenticate/Workers/Tokenizer.cs new file mode 100644 index 0000000..d077fe8 --- /dev/null +++ b/Authenticate/Workers/Tokenizer.cs @@ -0,0 +1,137 @@ +using Newtonsoft.Json; + +public class Tokenizer{ + public static async Task<(AccessToken accessToken, RefreshToken refreshToken)> GetAccessToken(string? ClientID, string? ClientSecret, string? code){ + + using (HttpClient httpClient = new HttpClient()){ + try{ + if (ClientID == null || ClientSecret == null || code == null){ + throw new Exception("Failed to parse JSON response."); + } + + var requestContent = new FormUrlEncodedContent(new Dictionary{ + { "grant_type", "authorization_code" }, + { "client_id", ClientID}, + { "client_secret", ClientSecret}, + { "code", code} + }); + + var response = await httpClient.PostAsync("https://www.bungie.net/Platform/App/OAuth/token/", requestContent); + + if (response.IsSuccessStatusCode){ + var responseContent = await response.Content.ReadAsStringAsync(); + var responseContentDictionary = ParseTokenResponse(responseContent); + (AccessToken accessToken, RefreshToken refreshToken) = SetAccessToken(responseContentDictionary); + return (accessToken, refreshToken); + + } + else{ + throw new Exception($"Failed to get access token: {response.StatusCode} - {response.ReasonPhrase}"); + } + } + catch (HttpRequestException ex){ + Console.WriteLine($"Error: {ex.Message}"); + return (new AccessToken(), new RefreshToken()); + } + } + } + + private static Dictionary ParseTokenResponse(string responseContent){ + + // Parse the JSON response to extract the access token, refresh token, and expiration time + // For simplicity, assuming the response is a JSON object with fields "access_token", "refresh_token", and "expires_in" + // You might need to use a JSON parsing library like Newtonsoft.Json for proper parsing + // Example parsing logic (replace with actual parsing) + + // Parse the JSON string into a dictionary + Dictionary? acessTokenDict = JsonConvert.DeserializeObject>(responseContent); + + if (acessTokenDict == null){ + // Throw an exception if JSON parsing fails + throw new Exception("Failed to parse JSON response."); + } + + return acessTokenDict; + } + + private static (AccessToken accessToken, RefreshToken refreshToken) SetAccessToken(Dictionary accessTokenDict){ + AccessToken accessToken = new AccessToken{ + Token = accessTokenDict["access_token"], + TokenType = accessTokenDict["token_type"], + ExpiresIn = int.Parse(accessTokenDict["expires_in"]), + + }; + accessToken.Expiration = DateTime.UtcNow.AddSeconds(accessToken.ExpiresIn); + + + RefreshToken refreshToken = new RefreshToken{ + Token = accessTokenDict["refresh_token"], + TokenType = accessTokenDict["token_type"], + ExpiresIn = int.Parse(accessTokenDict["refresh_expires_in"]), + }; + refreshToken.Expiration = DateTime.UtcNow.AddSeconds(refreshToken.ExpiresIn); + + return (accessToken, refreshToken); + } + + public static bool IsTokenValid(DateTime accessTokenExpiresAt){ + if (DateTime.UtcNow >= accessTokenExpiresAt){ + return false; + } + return true; + } + + public static async Task<(AccessToken accessToken, RefreshToken refreshToken)> RefreshAccessToken(string? ClientID, string? ClientSecret, string? RefreshToken){ + + using (HttpClient httpClient = new HttpClient()){ + try{ + + if (ClientID == null || ClientSecret == null || RefreshToken == null){ + throw new Exception("Failed to parse JSON response."); + } + + var requestContent = new FormUrlEncodedContent(new Dictionary{ + { "grant_type", "refresh_token" }, + { "client_id", ClientID }, + { "client_secret", ClientSecret }, + { "refresh_token", RefreshToken } + + }); + + var response = await httpClient.PostAsync("https://www.bungie.net/Platform/App/OAuth/token/", requestContent); + + if (response.IsSuccessStatusCode){ + var responseContent = await response.Content.ReadAsStringAsync(); + Console.WriteLine(responseContent); + var responseContentDictionary = ParseTokenResponse(responseContent); + (AccessToken accessToken, RefreshToken refreshToken) = SetAccessToken(responseContentDictionary); + return (accessToken, refreshToken); + } + else{ + throw new Exception($"Failed to get access token: {response.StatusCode} - {response.ReasonPhrase}"); + } + } + catch (HttpRequestException ex){ + Console.WriteLine($"Error: {ex.Message}"); + return (new AccessToken(), new RefreshToken()); + } + } + } + + public class AccessToken{ + public string? Token { get; set; } + public string? TokenType { get; set; } + public int ExpiresIn { get; set; } + public string? MembershipId { get; set; } + public DateTime Expiration { get; set; } + + } + + public class RefreshToken{ + public string? Token { get; set; } + public string? TokenType { get; set; } + public int ExpiresIn { get; set; } + public string? MembershipId { get; set; } + public DateTime Expiration { get; set; } + } +} diff --git a/guardians-central.sln b/guardians-central.sln index c0956df..6b3ecb1 100644 --- a/guardians-central.sln +++ b/guardians-central.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "database", "database\database.csproj", "{E1DD000A-8F94-43D3-865B-CBBA22180F15}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Authenticate", "Authenticate\Authenticate.csproj", "{A3F99E5C-9F29-46A8-A474-5226A5FF068C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {E1DD000A-8F94-43D3-865B-CBBA22180F15}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1DD000A-8F94-43D3-865B-CBBA22180F15}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1DD000A-8F94-43D3-865B-CBBA22180F15}.Release|Any CPU.Build.0 = Release|Any CPU + {A3F99E5C-9F29-46A8-A474-5226A5FF068C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3F99E5C-9F29-46A8-A474-5226A5FF068C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3F99E5C-9F29-46A8-A474-5226A5FF068C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3F99E5C-9F29-46A8-A474-5226A5FF068C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE