3using System.Globalization;
6using System.Threading.Tasks;
7using Microsoft.Extensions.Localization;
31 private readonly IStringLocalizer localizer;
34 private DateTime lastAuthenticationTime = DateTime.MinValue;
35 private DateTime savedStartTime = DateTime.MinValue;
36 private bool displayedPasswordPopup =
false;
62 if (!this.tagProfile.HasLocalPassword)
65 return await this.InputPasswordInternalAsync(purpose);
70 this.displayedPasswordPopup =
true;
73 if (!this.tagProfile.HasLocalPassword)
79 CloseOnBackButton =
true,
80 CloseOnBackgroundTap =
true
91 this.displayedPasswordPopup =
false;
101 TaskCompletionSource<bool> Tcs =
new TaskCompletionSource<bool>();
103 MainThread.BeginInvokeOnMainThread(async () =>
105 bool Result = await this.AuthenticateUserOnMainThreadAsync(purpose, force);
107 this.lastAuthenticationTime = DateTime.UtcNow;
108 Tcs.TrySetResult(Result);
113 private async Task<bool> AuthenticateUserOnMainThreadAsync(
AuthenticationPurpose purpose,
bool force =
false)
115 bool needToVerifyPassword = this.IsInactivitySafeIntervalPassed();
116 if (!force && !needToVerifyPassword)
119 switch (this.tagProfile.AuthenticationMethod)
122 if (!this.platformSpecific.SupportsFingerprintAuthentication)
125 if (await this.platformSpecific.AuthenticateUserFingerprint(
132 await this.UserAuthenticationSuccessfulAsync();
138 if (!this.tagProfile.HasLocalPassword)
141 if (this.displayedPasswordPopup)
144 return await this.InputPasswordInternalAsync(purpose) is not
null;
157 if (nextLoginTime.HasValue)
160 if (nextLoginTime == DateTime.MaxValue)
166 DateTime localDateTime = nextLoginTime.Value.ToLocalTime();
167 if (nextLoginTime.Value.ToShortDateString() == DateTime.Today.ToShortDateString())
169 string dateString = localDateTime.ToShortTimeString();
172 else if (nextLoginTime.Value.ToShortDateString() == DateTime.Today.AddDays(1).ToShortDateString())
174 string dateString = localDateTime.ToShortTimeString();
179 string dateString = localDateTime.ToString(
"yyyy-MM-dd, 'at' HH:mm", CultureInfo.InvariantCulture);
185 await this.CloseApplicationAsync();
194 if (password is
null)
197 if (this.tagProfile.ComputePasswordHash(password) ==
this.tagProfile.LocalPasswordHash)
199 await this.UserAuthenticationSuccessfulAsync();
204 await this.UserAuthenticationFailedAsync();
209 private async Task UserAuthenticationSuccessfulAsync()
211 this.SetStartInactivityTime();
212 await this.SetCurrentPasswordCounterAsync(0);
216 private async Task UserAuthenticationFailedAsync()
219 long CurrentCounter = await this.GetCurrentPasswordCounterAsync();
221 await this.SetCurrentPasswordCounterAsync(CurrentCounter);
224 private void SetStartInactivityTime()
226 this.savedStartTime = DateTime.UtcNow;
229 private bool IsInactivitySafeIntervalPassed()
232 if (DateTime.UtcNow <
this.lastAuthenticationTime)
234 return DateTime.Compare(DateTime.UtcNow,
238 public async Task<long> GetCurrentPasswordCounterAsync()
243 private async Task SetCurrentPasswordCounterAsync(
long counter)
248 private async Task CloseApplicationAsync()
252 await this.platformSpecific.CloseApplication();
261 #region IDisposable Implementation
262 private bool isDisposed =
false;
264 public void Dispose()
266 this.Dispose(disposing:
true);
267 GC.SuppressFinalize(
this);
273 protected virtual void Dispose(
bool disposing)
288 await this.loginAuditor.DisposeAsync();
290 this.isDisposed =
true;
const int FirstMaxPasswordAttempts
Maximum password enetring attempts, first interval
const int PossibleInactivityInMinutes
Possible time of inactivity
const string CurrentPasswordAttemptCounter
Key for password attempt counter
const string RemoteEndpoint
Endpoint for LogAuditor
const string LogAuditorObjectID
Log Object ID
const int SecondBlockInHours
Second Block in hours after 3 attempts
const int ThirdBlockInHours
Third Block in hours after 3 attempts
const int FirstBlockInHours
First Block in hours after FirstMaxPasswordAttempts attempts
const string Protocol
Protocol for LogAuditor
const int ThirdMaxPasswordAttempts
Maximum password enetring attempts, third interval
const int SecondMaxPasswordAttempts
Maximum password enetring attempts, second interval
const string Reason
Reason for LogAuditor
A set of never changing property constants and helpful values.
A strongly-typed resource class, for looking up localized strings, etc.
static string PasswordIsInvalidAplicationBlockedTillTomorrow
Looks up a localized string similar to You have exceeded the number of attempts to provide your PIN....
static string FingerprintTitle
Looks up a localized string similar to Authentication Required.
static string Cancel
Looks up a localized string similar to Cancel.
static string PasswordIsInvalidAplicationBlocked
Looks up a localized string similar to You have exceeded the number of attempts to provide your PIN....
static string PasswordIsInvalidAplicationBlockedForever
Looks up a localized string similar to You have exceeded the number of attempts to provide your PIN....
static string FingerprintDescription
Looks up a localized string similar to Scan to authenticate.
static string ErrorTitle
Looks up a localized string similar to An error has occurred.
Task< bool > AuthenticateUserAsync(AuthenticationPurpose purpose, bool force=false)
Main entry point for authentication UI flow (password or biometrics).
async Task< bool > CheckPasswordAndUnblockUserAsync(string password)
Validates password and unblocks user if correct.
virtual async ValueTask DisposeAsync()
IDisposableAsync.Dispose
virtual void Dispose(bool disposing)
IDisposableAsync.Dispose
async Task< string?> InputPasswordAsync(AuthenticationPurpose purpose)
Prompts for password if required by user profile.
async Task CheckUserBlockingAsync()
Checks if user is blocked from authentication and shows UI as needed.
Base class that references services in the app.
static IServiceProvider Provider
The service provider for the app. This is set before the app is started, and will be used to resolve ...
static IReportingStringLocalizer Localizer
Localization service
The TAG Profile is the heart of the digital identity for a specific user/device. Use this instance to...
Class that monitors login events, and help applications determine malicious intent....
Number of failing login attempts possible during given time period.
Handles common runtime settings that need to be persisted during sessions.
The TAG Profile is the heart of the digital identity for a specific user/device. Use this instance to...
Service serializing and managing UI-related tasks.
AuthenticationMethod
How the user authenticates itself with the App.
AuthenticationPurpose
Purpose for requesting the user to authenticate itself.