Skip to content

Commit

Permalink
Add XboxAuthNet library for oauth login and token generation
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsLogic committed May 31, 2024
1 parent ae77085 commit da2a090
Show file tree
Hide file tree
Showing 71 changed files with 3,199 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .run/Publish Debug.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Publish Debug" type="DotNetFolderPublish" factoryName="Publish to folder">
<riderPublish configuration="Debug" delete_existing_files="true" platform="x64" runtime="Portable" target_folder="$PROJECT_DIR$/XAU/bin/Debug/net8.0-windows/publish" target_framework="net8.0-windows" uuid_high="3467633360020586717" uuid_low="-5402852396017586348" />
<riderPublish configuration="Debug" delete_existing_files="true" include_native_libs_for_self_extract="true" platform="x64" produce_single_file="true" runtime="win-x64" target_folder="$PROJECT_DIR$/XAU/bin/Debug/net8.0-windows/win-x64/publish" target_framework="net8.0-windows" uuid_high="3467633360020586717" uuid_low="-5402852396017586348" />
<method v="2" />
</configuration>
</component>
2 changes: 1 addition & 1 deletion .run/Publish Release.run.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Publish Release" type="DotNetFolderPublish" factoryName="Publish to folder">
<riderPublish configuration="Release" delete_existing_files="true" platform="x64" produce_single_file="true" runtime="win-x64" target_folder="$PROJECT_DIR$/XAU/bin/Release/net8.0-windows/win-x64/publish" target_framework="net8.0-windows" uuid_high="3467633360020586717" uuid_low="-5402852396017586348" />
<riderPublish configuration="Release" delete_existing_files="true" include_native_libs_for_self_extract="true" platform="x64" produce_single_file="true" runtime="win-x64" target_folder="$PROJECT_DIR$/XAU/bin/Release/net8.0-windows/win-x64/publish" target_framework="net8.0-windows" uuid_high="3467633360020586717" uuid_low="-5402852396017586348" />
<method v="2" />
</configuration>
</component>
1 change: 1 addition & 0 deletions XAU/Models/XAUSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ public class XAUSettings
public bool RegionOverride { get; set; }
public bool UseAcrylic { get; set; }
public bool PrivacyMode { get; set; }
public bool OAuthLogin { get; set; }
}
2 changes: 1 addition & 1 deletion XAU/Services/ApplicationHostService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Microsoft.Extensions.Hosting;
using XAU.Views.Pages;
using XAU.Views.Windows;

using Application = System.Windows.Application;
namespace XAU.Services
{
/// <summary>
Expand Down
7 changes: 7 additions & 0 deletions XAU/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@
global using System;
global using System.Windows;
global using Wpf.Ui;
//fix these to override winforms imports
global using Clipboard = System.Windows.Clipboard;
global using Brush = System.Windows.Media.Brush;
global using HtmlDocument = HtmlAgilityPack.HtmlDocument;
global using KeyEventArgs = System.Windows.Input.KeyEventArgs;
global using ButtonBase = System.Windows.Controls.Primitives.ButtonBase;
global using ListBox = System.Windows.Controls.ListBox;
258 changes: 258 additions & 0 deletions XAU/Util/XboxAuthNet/Base64UrlHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/9895855ac4fcf52893fbc2b06ee20ea3eda1549a/src/client/Microsoft.Identity.Client/Utils/Base64UrlHelpers.cs
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Diagnostics;
using System.Globalization;
using System.Text;

namespace XboxAuthNet
{
// Based on https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/pull/1698/files
internal static class Base64UrlHelper
{
private const char base64PadCharacter = '=';
#if NET45
private const string doubleBase64PadCharacter = "==";
#endif
private const char base64Character62 = '+';
private const char base64Character63 = '/';
private const char base64UrlCharacter62 = '-';
private const char base64UrlCharacter63 = '_';

/// <summary>
/// Encoding table
/// </summary>
internal static readonly char[] s_base64Table =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9',
base64UrlCharacter62,
base64UrlCharacter63
};

/// <summary>
/// The following functions perform base64url encoding which differs from regular base64 encoding as follows
/// * padding is skipped so the pad character '=' doesn't have to be percent encoded
/// * the 62nd and 63rd regular base64 encoding characters ('+' and '/') are replace with ('-' and '_')
/// The changes make the encoding alphabet file and URL safe.
/// </summary>
/// <param name="arg">string to encode.</param>
/// <returns>Base64Url encoding of the UTF8 bytes.</returns>
public static string Encode(string arg)
{
return Encode(Encoding.UTF8.GetBytes(arg));
}

/// <summary>
/// Converts a subset of an array of 8-bit unsigned integers to its equivalent string representation that is encoded with base-64-url digits. Parameters specify
/// the subset as an offset in the input array, and the number of elements in the array to convert.
/// </summary>
/// <param name="inArray">An array of 8-bit unsigned integers.</param>
/// <param name="length">An offset in inArray.</param>
/// <param name="offset">The number of elements of inArray to convert.</param>
/// <returns>The string representation in base 64 url encoding of length elements of inArray, starting at position offset.</returns>
/// <exception cref="ArgumentNullException">'inArray' is null.</exception>
/// <exception cref="ArgumentOutOfRangeException">offset or length is negative OR offset plus length is greater than the length of inArray.</exception>
private static string Encode(byte[] inArray, int offset, int length)
{
_ = inArray ?? throw new ArgumentNullException(nameof(inArray));

if (length == 0)
return string.Empty;

if (length < 0)
throw new ArgumentOutOfRangeException(nameof(length));

if (offset < 0 || inArray.Length < offset)
throw new ArgumentOutOfRangeException(nameof(offset));

if (inArray.Length < offset + length)
throw new ArgumentOutOfRangeException(nameof(length));

int lengthmod3 = length % 3;
int limit = offset + (length - lengthmod3);
char[] output = new char[(length + 2) / 3 * 4];
char[] table = s_base64Table;
int i, j = 0;

// takes 3 bytes from inArray and insert 4 bytes into output
for (i = offset; i < limit; i += 3)
{
byte d0 = inArray[i];
byte d1 = inArray[i + 1];
byte d2 = inArray[i + 2];

output[j + 0] = table[d0 >> 2];
output[j + 1] = table[((d0 & 0x03) << 4) | (d1 >> 4)];
output[j + 2] = table[((d1 & 0x0f) << 2) | (d2 >> 6)];
output[j + 3] = table[d2 & 0x3f];
j += 4;
}

//Where we left off before
i = limit;

switch (lengthmod3)
{
case 2:
{
byte d0 = inArray[i];
byte d1 = inArray[i + 1];

output[j + 0] = table[d0 >> 2];
output[j + 1] = table[((d0 & 0x03) << 4) | (d1 >> 4)];
output[j + 2] = table[(d1 & 0x0f) << 2];
j += 3;
}
break;

case 1:
{
byte d0 = inArray[i];

output[j + 0] = table[d0 >> 2];
output[j + 1] = table[(d0 & 0x03) << 4];
j += 2;
}
break;

//default or case 0: no further operations are needed.
}

return new string(output, 0, j);
}

/// <summary>
/// Converts a subset of an array of 8-bit unsigned integers to its equivalent string representation that is encoded with base-64-url digits. Parameters specify
/// the subset as an offset in the input array, and the number of elements in the array to convert.
/// </summary>
/// <param name="inArray">An array of 8-bit unsigned integers.</param>
/// <returns>The string representation in base 64 url encoding of length elements of inArray, starting at position offset.</returns>
/// <exception cref="ArgumentNullException">'inArray' is null.</exception>
/// <exception cref="ArgumentOutOfRangeException">offset or length is negative OR offset plus length is greater than the length of inArray.</exception>
public static string Encode(byte[] inArray)
{
return Encode(inArray, 0, inArray.Length);
}

internal static string EncodeString(string str)
{
return Encode(Encoding.UTF8.GetBytes(str));
}

/// <summary>
/// Converts the specified string, which encodes binary data as base-64-url digits, to an equivalent 8-bit unsigned integer array.</summary>
/// <param name="str">base64Url encoded string.</param>
/// <returns>UTF8 bytes.</returns>
public static byte[] DecodeBytes(string str)
{
#if NET45
// 62nd char of encoding
str = str.Replace(base64UrlCharacter62, base64Character62);

// 63rd char of encoding
str = str.Replace(base64UrlCharacter63, base64Character63);

// check for padding
switch (str.Length % 4)
{
case 0:
// No pad chars in this case
break;
case 2:
// Two pad chars
str += doubleBase64PadCharacter;
break;
case 3:
// One pad char
str += base64PadCharacter;
break;
default:
throw new FormatException($"Unable to decode: {str} as Base64url encoded string.");
}

return Convert.FromBase64String(str);
#else
return UnsafeDecode(str);
#endif
}

#if !NET45
private unsafe static byte[] UnsafeDecode(string str)
{
int mod = str.Length % 4;
if (mod == 1)
throw new FormatException($"Unable to decode: {str} as Base64url encoded string.");

bool needReplace = false;
int decodedLength = str.Length + (4 - mod) % 4;

for (int i = 0; i < str.Length; i++)
{
if (str[i] == base64UrlCharacter62 || str[i] == base64UrlCharacter63)
{
needReplace = true;
break;
}
}

if (needReplace)
{
string decodedString = new string(char.MinValue, decodedLength);
fixed (char* dest = decodedString)
{
int i = 0;
for (; i < str.Length; i++)
{
if (str[i] == base64UrlCharacter62)
dest[i] = base64Character62;
else if (str[i] == base64UrlCharacter63)
dest[i] = base64Character63;
else
dest[i] = str[i];
}

for (; i < decodedLength; i++)
dest[i] = base64PadCharacter;
}

return Convert.FromBase64String(decodedString);
}
else
{
if (decodedLength == str.Length)
{
return Convert.FromBase64String(str);
}
else
{
string decodedString = new string(char.MinValue, decodedLength);
fixed (char* src = str)
fixed (char* dest = decodedString)
{
Buffer.MemoryCopy(src, dest, str.Length * 2, str.Length * 2);
dest[str.Length] = base64PadCharacter;
if (str.Length + 2 == decodedLength)
dest[str.Length + 1] = base64PadCharacter;
}

return Convert.FromBase64String(decodedString);
}
}
}
#endif

/// <summary>
/// Decodes the string from Base64UrlEncoded to UTF8.
/// </summary>
/// <param name="arg">string to decode.</param>
/// <returns>UTF8 string.</returns>
public static string Decode(string arg)
{
return Encoding.UTF8.GetString(DecodeBytes(arg));
}
}
}
Loading

0 comments on commit da2a090

Please sign in to comment.