113 lines
3.7 KiB
C#
113 lines
3.7 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using AlayaCore.Abstractions.Interfaces;
|
|
using AlayaCore.Abstractions.Interfaces.Services;
|
|
using AlayaCore.Utilities.Enums;
|
|
using CmlLib.Core.Auth;
|
|
using CmlLib.Core.Auth.Microsoft;
|
|
using Microsoft.Identity.Client;
|
|
using XboxAuthNet.Game.Msal;
|
|
using XboxAuthNet.Game.Msal.OAuth;
|
|
|
|
namespace AlayaCore.Services
|
|
{
|
|
public sealed class AuthService : IAuthService
|
|
{
|
|
private readonly IFileStore _fileStore;
|
|
|
|
private MSession? _session;
|
|
private IPublicClientApplication? _clientApp;
|
|
private JELoginHandler? _loginHandler;
|
|
|
|
public AuthService(IFileStore fileStore)
|
|
{
|
|
_fileStore = fileStore ?? throw new ArgumentNullException(nameof(fileStore));
|
|
}
|
|
|
|
public Task<bool> IsAuthenticatedAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
bool authenticated = _session != null && _session.CheckIsValid();
|
|
return Task.FromResult(authenticated);
|
|
}
|
|
|
|
public async Task AuthenticateAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
JELoginHandler loginHandler = await BuildHandlerAsync().ConfigureAwait(false);
|
|
|
|
try
|
|
{
|
|
_session = await loginHandler
|
|
.AuthenticateSilently(cancellationToken: cancellationToken)
|
|
.ConfigureAwait(false);
|
|
}
|
|
catch
|
|
{
|
|
_session = await loginHandler
|
|
.AuthenticateInteractively(cancellationToken: cancellationToken)
|
|
.ConfigureAwait(false);
|
|
}
|
|
|
|
if (_session == null || !_session.CheckIsValid())
|
|
{
|
|
throw new InvalidOperationException("Authentication did not produce a valid Minecraft session.");
|
|
}
|
|
}
|
|
|
|
public async Task SignOutAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
JELoginHandler loginHandler = await BuildHandlerAsync().ConfigureAwait(false);
|
|
|
|
await loginHandler.Signout(cancellationToken).ConfigureAwait(false);
|
|
_session = null;
|
|
}
|
|
|
|
public async Task<MSession> GetSessionAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
if (_session != null && _session.CheckIsValid())
|
|
{
|
|
return _session;
|
|
}
|
|
|
|
await AuthenticateAsync(cancellationToken).ConfigureAwait(false);
|
|
|
|
if (_session == null || !_session.CheckIsValid())
|
|
{
|
|
throw new InvalidOperationException("No valid Minecraft session is available.");
|
|
}
|
|
|
|
return _session;
|
|
}
|
|
|
|
private async Task<JELoginHandler> BuildHandlerAsync()
|
|
{
|
|
if (_loginHandler != null)
|
|
{
|
|
return _loginHandler;
|
|
}
|
|
|
|
string accountDirectory = _fileStore.GetOrCreate(FolderLocation.Data);
|
|
string accountFilePath = Path.Combine(accountDirectory, "accounts.json");
|
|
|
|
_clientApp = await MsalClientHelper
|
|
.BuildApplicationWithCache("d91042d4-3eb5-43e4-b3ed-600e1d0760ff")
|
|
.ConfigureAwait(false);
|
|
|
|
_loginHandler = new JELoginHandlerBuilder()
|
|
.WithOAuthProvider(new MsalCodeFlowProvider(_clientApp))
|
|
.WithAccountManager(accountFilePath)
|
|
.Build();
|
|
|
|
return _loginHandler;
|
|
}
|
|
}
|
|
} |