Added automatic login using auth tokens IO-403
This commit is contained in:
@@ -57,6 +57,12 @@
|
||||
<setting name="QuickBooksFilePath" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="AuthToken" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
<setting name="RefreshToken" serializeAs="String">
|
||||
<value />
|
||||
</setting>
|
||||
</BodyshopPartner.Properties.Settings>
|
||||
</userSettings>
|
||||
</configuration>
|
||||
|
||||
26
BodyshopUploader/Properties/Settings.Designer.cs
generated
26
BodyshopUploader/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace BodyshopPartner.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.7.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -104,5 +104,29 @@ namespace BodyshopPartner.Properties {
|
||||
this["QuickBooksFilePath"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string AuthToken {
|
||||
get {
|
||||
return ((string)(this["AuthToken"]));
|
||||
}
|
||||
set {
|
||||
this["AuthToken"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("")]
|
||||
public string RefreshToken {
|
||||
get {
|
||||
return ((string)(this["RefreshToken"]));
|
||||
}
|
||||
set {
|
||||
this["RefreshToken"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,11 @@
|
||||
<Setting Name="QuickBooksFilePath" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="AuthToken" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
<Setting Name="RefreshToken" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)" />
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -12,15 +12,57 @@ namespace BodyshopPartner.Utils
|
||||
{
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
public static FirebaseAuthLink authlink;
|
||||
static FirebaseAuthProvider ap = new FirebaseAuthProvider(new FirebaseConfig(Utils.AppMetaData.FirebaseAPIKey));
|
||||
static FirebaseAuthProvider ap = new FirebaseAuthProvider(new FirebaseConfig(Utils.AppMetaData.FirebaseAPIKey));
|
||||
private static Timer tokenTimer = new Timer();
|
||||
private static string U;
|
||||
private static string P;
|
||||
|
||||
|
||||
|
||||
public async static Task AuthTest()
|
||||
{
|
||||
await ap.RefreshAuthAsync( new FirebaseAuth() { });
|
||||
await ap.RefreshAuthAsync(new FirebaseAuth() { });
|
||||
}
|
||||
|
||||
public async static Task<(bool, string)> AutoLogin(string AuthToken, string RefreshToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
authlink = await new FirebaseAuthLink(ap, new FirebaseAuth() { FirebaseToken = AuthToken, RefreshToken = RefreshToken, }).GetFreshAuthAsync();
|
||||
await authlink.RefreshUserDetails();
|
||||
authlink.FirebaseAuthRefreshed += Authlink_FirebaseAuthRefreshed;
|
||||
|
||||
logger.Trace("Firebase Auth Token {0}.", authlink.FirebaseToken);
|
||||
logger.Trace("Firebase Auth Token expires in {0} seconds.", authlink.ExpiresIn);
|
||||
tokenTimer.Interval = (authlink.ExpiresIn - 600) * 1000; //Set the token to refresh 10 minutes before it has to.
|
||||
logger.Trace("Refresh timer interval set to {0}ms", (authlink.ExpiresIn - 600) * 1000);
|
||||
tokenTimer.Elapsed += TokenTimer_Tick;
|
||||
tokenTimer.Start();
|
||||
return (true, null);
|
||||
}
|
||||
catch (FirebaseAuthException Ex)
|
||||
{
|
||||
switch (Ex.Reason)
|
||||
{
|
||||
case AuthErrorReason.WrongPassword:
|
||||
logger.Error("Incorrect password provided for user.");
|
||||
return (false, Properties.Resources.Error_Login);
|
||||
|
||||
case AuthErrorReason.UnknownEmailAddress:
|
||||
logger.Error("User does not exist.");
|
||||
return (false, Properties.Resources.Error_Login);
|
||||
case AuthErrorReason.TooManyAttemptsTryLater:
|
||||
logger.Error("Too many attempts logging in.");
|
||||
return (false, Properties.Resources.Error_Login_Attempts);
|
||||
default:
|
||||
logger.Error(Ex, "Unknown error occured while logging in. {0}", Ex.Reason);
|
||||
return (false, Properties.Resources.Error_Login_Unknown);
|
||||
}
|
||||
}
|
||||
catch (Exception Ex)
|
||||
{
|
||||
logger.Error(Ex, "Unknown error encountered while obtaining auth token.");
|
||||
return (false, Properties.Resources.Error_Generic);
|
||||
}
|
||||
}
|
||||
|
||||
public async static Task<(bool, string)> LoginAsync(string Username, string Password)
|
||||
@@ -31,8 +73,12 @@ namespace BodyshopPartner.Utils
|
||||
{
|
||||
authlink = await ap.SignInWithEmailAndPasswordAsync(Username, Password);
|
||||
authlink.FirebaseAuthRefreshed += Authlink_FirebaseAuthRefreshed;
|
||||
|
||||
|
||||
|
||||
Properties.Settings.Default.AuthToken = authlink.FirebaseToken;
|
||||
Properties.Settings.Default.RefreshToken = authlink.RefreshToken;
|
||||
Properties.Settings.Default.Save();
|
||||
|
||||
|
||||
|
||||
logger.Trace("Firebase Auth Token {0}.", authlink.FirebaseToken);
|
||||
logger.Trace("Firebase Auth Token expires in {0} seconds.", authlink.ExpiresIn);
|
||||
@@ -73,7 +119,7 @@ namespace BodyshopPartner.Utils
|
||||
{
|
||||
logger.Trace("Old Token {0}", authlink.RefreshToken);
|
||||
await authlink.GetFreshAuthAsync();
|
||||
|
||||
|
||||
authlink = await ap.RefreshAuthAsync(authlink);
|
||||
logger.Trace("new Token {0}", authlink.FirebaseToken);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace BodyshopPartner.Utils
|
||||
public static class GraphQL
|
||||
{
|
||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
||||
public static GraphQLHttpClient CreateGQLClient()
|
||||
{
|
||||
var graphQLClient = new GraphQLHttpClient(AppMetaData.graphQlEndpoint, new NewtonsoftJsonSerializer());
|
||||
@@ -31,7 +31,7 @@ namespace BodyshopPartner.Utils
|
||||
var graphQLResponse = await g.SendQueryAsync<dynamic>(r);
|
||||
if (graphQLResponse.Errors == null)
|
||||
{
|
||||
|
||||
|
||||
//logger.Trace("GQL Response: {0}", graphQLResponse.Data);
|
||||
return graphQLResponse.Data;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace BodyshopPartner.Utils
|
||||
logger.Error("Error executing query.");
|
||||
Array.ForEach(graphQLResponse.Errors, x =>
|
||||
{
|
||||
logger.Error(x.Message);
|
||||
logger.Error("Graphql Error: " + x.Message);
|
||||
if (x.Message.Contains("JWTExpired"))
|
||||
{
|
||||
jwtExpired = true;
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace BodyshopPartner.Utils
|
||||
|
||||
catch (Exception Ex)
|
||||
{
|
||||
logger.Error("Job insert failed. Show notification");
|
||||
logger.Error("Job insert failed. Show notification " + Ex.ToString());
|
||||
//Succesful upsert
|
||||
App.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
|
||||
@@ -25,6 +25,20 @@ namespace BodyshopPartner.Utils
|
||||
}
|
||||
}
|
||||
|
||||
public class InvertBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return !((bool)value);
|
||||
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return ((bool)value);
|
||||
}
|
||||
}
|
||||
|
||||
public class NullVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
|
||||
namespace BodyshopPartner.ViewModels
|
||||
{
|
||||
public partial class LoginViewModel : BaseViewModel
|
||||
@@ -15,6 +16,34 @@ namespace BodyshopPartner.ViewModels
|
||||
public LoginViewModel()
|
||||
{
|
||||
logger.Trace("Login VM Created.");
|
||||
|
||||
AutoLogin();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private async Task AutoLogin()
|
||||
{
|
||||
Loading = true;
|
||||
string AuthToken = Properties.Settings.Default.AuthToken;
|
||||
string RefreshToken = Properties.Settings.Default.RefreshToken;
|
||||
|
||||
|
||||
if (!String.IsNullOrEmpty(AuthToken) && !String.IsNullOrEmpty(RefreshToken))
|
||||
{
|
||||
//Attempt auto login.
|
||||
logger.Debug("Good to attempt auto login.");
|
||||
(Error, ErrorMsg) = await Utils.Auth.AutoLogin(AuthToken, RefreshToken);
|
||||
if (ErrorMsg == null)
|
||||
{
|
||||
App.Current.MainWindow.Hide();
|
||||
Views.Main m = new Views.Main();
|
||||
m.Show();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading = false;
|
||||
}
|
||||
|
||||
private async Task LoginAsync(Window W)
|
||||
@@ -25,7 +54,7 @@ namespace BodyshopPartner.ViewModels
|
||||
|
||||
logger.Trace("Attempting to login as user: {0}", UserName);
|
||||
(Error, ErrorMsg) = await Utils.Auth.LoginAsync(UserName, Utils.LoginHelpers.DecodePassword(UserPassword));
|
||||
if(ErrorMsg ==null)
|
||||
if (ErrorMsg == null)
|
||||
{
|
||||
Views.Main m = new Views.Main();
|
||||
m.Show();
|
||||
|
||||
@@ -148,6 +148,7 @@ namespace BodyshopPartner.ViewModels
|
||||
async p =>
|
||||
{
|
||||
await InstallUpdates();
|
||||
UpdateAvailable = false;
|
||||
});
|
||||
}
|
||||
return _installUpdatesCommand;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</Window.DataContext>
|
||||
<Window.Resources>
|
||||
<util:NullVisibilityConverter x:Key="NullVisibilityConverter" />
|
||||
|
||||
<util:InvertBoolConverter x:Key="InvertBoolConverter" />
|
||||
<Style TargetType="StackPanel">
|
||||
<Setter Property="Margin"
|
||||
Value="8" />
|
||||
@@ -74,6 +74,7 @@
|
||||
<PasswordBox materialDesign:HintAssist.Hint="{x:Static p:Resources.Password}"
|
||||
KeyDown="PasswordBox_KeyDown"
|
||||
PasswordChanged="PasswordBox_PasswordChanged"
|
||||
IsEnabled="{Binding Loading, Converter={StaticResource InvertBoolConverter}}"
|
||||
Width="300" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
@@ -67,10 +67,5 @@ namespace BodyshopPartner.Views
|
||||
{
|
||||
Application.Current.Shutdown(0);
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Utils.Auth.AuthTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user