Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ yarn-error.log*
/WeeklyRotators/bin
/WeeklyRotators/config.toml
/WeeklyRotators/logging
.env
.env
15 changes: 15 additions & 0 deletions Authenticate/Authenticate.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Nett" Version="0.15.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

</Project>
74 changes: 74 additions & 0 deletions Authenticate/GenerateToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Nett;

class Program{
static async Task Main(){

// Gets all the data from TOML File
var table = Toml.ReadFile<Config>("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<string?>(accessToken.Token);

//var config = Toml.ReadFile<Config>("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; }

}
137 changes: 137 additions & 0 deletions Authenticate/Workers/Tokenizer.cs
Original file line number Diff line number Diff line change
@@ -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<string, string>{
{ "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<string, string> 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<string, string>? acessTokenDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(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<string, string> 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<string, string>{
{ "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; }
}
}
6 changes: 6 additions & 0 deletions guardians-central.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WeeklyRotators", "WeeklyRotators\WeeklyRotators.csproj", "{E1DD000A-8F94-43D3-865B-CBBA22180F15}"
EndProject
Global
Expand All @@ -17,6 +19,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
Expand Down