From 6ab6fb39954d94c035c94bac8e71054174543e13 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Tue, 8 Feb 2022 22:40:46 -0700 Subject: [PATCH] Add LoversLab and VectorPlexus logins --- Wabbajack.App.Blazor/App.xaml.cs | 2 + .../Browser/BrowserTabViewModel.cs | 8 ++ .../Browser/ViewModels/IPSOAuth2Login.cs | 100 ++++++++++++++++++ .../Browser/ViewModels/LoversLab.cs | 15 +++ .../Browser/ViewModels/VectorPlexus.cs | 14 +++ Wabbajack.App.Blazor/Pages/Settings.razor | 11 ++ 6 files changed, 150 insertions(+) create mode 100644 Wabbajack.App.Blazor/Browser/ViewModels/IPSOAuth2Login.cs create mode 100644 Wabbajack.App.Blazor/Browser/ViewModels/LoversLab.cs create mode 100644 Wabbajack.App.Blazor/Browser/ViewModels/VectorPlexus.cs diff --git a/Wabbajack.App.Blazor/App.xaml.cs b/Wabbajack.App.Blazor/App.xaml.cs index 8e33e840..7ed412bb 100644 --- a/Wabbajack.App.Blazor/App.xaml.cs +++ b/Wabbajack.App.Blazor/App.xaml.cs @@ -74,6 +74,8 @@ public partial class App services.AddBlazoredToast(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddSingleton(); return services; diff --git a/Wabbajack.App.Blazor/Browser/BrowserTabViewModel.cs b/Wabbajack.App.Blazor/Browser/BrowserTabViewModel.cs index c9f4aa69..598ecef9 100644 --- a/Wabbajack.App.Blazor/Browser/BrowserTabViewModel.cs +++ b/Wabbajack.App.Blazor/Browser/BrowserTabViewModel.cs @@ -31,6 +31,14 @@ public abstract class BrowserTabViewModel : ViewModel protected abstract Task Run(CancellationToken token); + protected async Task WaitForReady() + { + while (Browser?.Browser.CoreWebView2 == null) + { + await Task.Delay(250); + } + } + public async Task NavigateTo(Uri uri) { var tcs = new TaskCompletionSource(); diff --git a/Wabbajack.App.Blazor/Browser/ViewModels/IPSOAuth2Login.cs b/Wabbajack.App.Blazor/Browser/ViewModels/IPSOAuth2Login.cs new file mode 100644 index 00000000..cceac47e --- /dev/null +++ b/Wabbajack.App.Blazor/Browser/ViewModels/IPSOAuth2Login.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using Microsoft.Extensions.Logging; +using Wabbajack.DTOs.Logins; +using Wabbajack.Services.OSIntegrated; + +namespace Wabbajack.App.Blazor.Browser.ViewModels; + +public abstract class IPSOAuth2Login : BrowserTabViewModel + where TLoginType : OAuth2LoginState, new() +{ + private readonly HttpClient _httpClient; + private readonly EncryptedJsonTokenProvider _tokenProvider; + private readonly ILogger _logger; + + public IPSOAuth2Login(ILogger logger, HttpClient httpClient, + EncryptedJsonTokenProvider tokenProvider) + { + var tlogin = new TLoginType(); + HeaderText = $"{tlogin.SiteName} Login"; + _logger = logger; + _httpClient = httpClient; + _tokenProvider = tokenProvider; + } + + protected override async Task Run(CancellationToken token) + { + var tlogin = new TLoginType(); + + var tcs = new TaskCompletionSource(); + await WaitForReady(); + Browser!.Browser.CoreWebView2.Settings.UserAgent = "Wabbajack"; + Browser!.Browser.NavigationStarting += (sender, args) => + { + var uri = new Uri(args.Uri); + if (uri.Scheme == "wabbajack") + { + tcs.TrySetResult(uri); + } + }; + + Instructions = $"Please log in and allow Wabbajack to access your {tlogin.SiteName} account"; + + var scopes = string.Join(" ", tlogin.Scopes); + var state = Guid.NewGuid().ToString(); + + await NavigateTo(new Uri(tlogin.AuthorizationEndpoint + + $"?response_type=code&client_id={tlogin.ClientID}&state={state}&scope={scopes}")); + + var uri = await tcs.Task.WaitAsync(token); + + var cookies = await GetCookies(tlogin.AuthorizationEndpoint.Host, token); + + var parsed = HttpUtility.ParseQueryString(uri.Query); + if (parsed.Get("state") != state) + { + _logger.LogCritical("Bad OAuth state, this shouldn't happen"); + throw new Exception("Bad OAuth State"); + } + + if (parsed.Get("code") == null) + { + _logger.LogCritical("Bad code result from OAuth"); + throw new Exception("Bad code result from OAuth"); + } + + var authCode = parsed.Get("code"); + + var formData = new KeyValuePair[] + { + new("grant_type", "authorization_code"), + new("code", authCode), + new("client_id", tlogin.ClientID) + }; + + var msg = new HttpRequestMessage(); + msg.Method = HttpMethod.Post; + msg.RequestUri = tlogin.TokenEndpoint; + msg.Headers.Add("User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36"); + msg.Headers.Add("Cookie", string.Join(";", cookies.Select(c => $"{c.Name}={c.Value}"))); + msg.Content = new FormUrlEncodedContent(formData.ToList()); + + using var response = await _httpClient.SendAsync(msg, token); + var data = await response.Content.ReadFromJsonAsync(cancellationToken: token); + + await _tokenProvider.SetToken(new TLoginType + { + Cookies = cookies, + ResultState = data! + }); + + } +} diff --git a/Wabbajack.App.Blazor/Browser/ViewModels/LoversLab.cs b/Wabbajack.App.Blazor/Browser/ViewModels/LoversLab.cs new file mode 100644 index 00000000..2a193b81 --- /dev/null +++ b/Wabbajack.App.Blazor/Browser/ViewModels/LoversLab.cs @@ -0,0 +1,15 @@ +using System.Net.Http; +using Microsoft.Extensions.Logging; +using Wabbajack.DTOs.DownloadStates; +using Wabbajack.DTOs.Logins; +using Wabbajack.Services.OSIntegrated; + +namespace Wabbajack.App.Blazor.Browser.ViewModels; + +public class LoversLab : IPSOAuth2Login +{ + public LoversLab(ILogger logger, HttpClient httpClient, EncryptedJsonTokenProvider tokenProvider) + : base(logger, httpClient, tokenProvider) + { + } +} diff --git a/Wabbajack.App.Blazor/Browser/ViewModels/VectorPlexus.cs b/Wabbajack.App.Blazor/Browser/ViewModels/VectorPlexus.cs new file mode 100644 index 00000000..ce65978f --- /dev/null +++ b/Wabbajack.App.Blazor/Browser/ViewModels/VectorPlexus.cs @@ -0,0 +1,14 @@ +using System.Net.Http; +using Microsoft.Extensions.Logging; +using Wabbajack.DTOs.Logins; +using Wabbajack.Services.OSIntegrated; + +namespace Wabbajack.App.Blazor.Browser.ViewModels; + +public class VectorPlexus : IPSOAuth2Login +{ + public VectorPlexus(ILogger logger, HttpClient httpClient, EncryptedJsonTokenProvider tokenProvider) + : base(logger, httpClient, tokenProvider) + { + } +} diff --git a/Wabbajack.App.Blazor/Pages/Settings.razor b/Wabbajack.App.Blazor/Pages/Settings.razor index 1ee55e52..8fc742d5 100644 --- a/Wabbajack.App.Blazor/Pages/Settings.razor +++ b/Wabbajack.App.Blazor/Pages/Settings.razor @@ -11,6 +11,9 @@
+ + +
@@ -21,4 +24,12 @@ { MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService())); } + public void LoginToLoversLab() + { + MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService())); + } + public void LoginToVectorPlexus() + { + MessageBus.Current.SendMessage(new OpenBrowserTab(_serviceProvider.GetRequiredService())); + } }