Files
AlayaCore/AlayaCore/Services/AuthService.cs

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;
}
}
}