I am using the below code in two factor authentication which uses google authenticator. The problem with this validation, is that google authenticator code is validating correctly on my local machine, but not on the server. The server time setting is : (UTC-05:00) Eastern Time (US & Canada) My system time setting is : (UTC-06:00) Central Time (US & Canada)
On server-when i try to hit validate button multiple times, it sometimes validates correctly sometimes not. I am not sure why its doing this.
Anybody can help me giving idea/suggestion to sort this issue
public static class TimeBasedOneTimePassword
{
public static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static MemoryCache _cache;
static TimeBasedOneTimePassword()
{
_cache = new MemoryCache("TimeBasedOneTimePassword");
}
public static string GetPassword(string secret)
{
return GetPassword(secret, GetCurrentCounter());
}
public static string GetPassword(string secret, DateTime epoch, int timeStep)
{
long counter = GetCurrentCounter(DateTime.UtcNow, epoch, timeStep);
return GetPassword(secret, counter);
}
public static string GetPassword(string secret, DateTime now, DateTime epoch, int timeStep, int digits)
{
long counter = GetCurrentCounter(now, epoch, timeStep);
return GetPassword(secret, counter, digits);
}
private static string GetPassword(string secret, long counter, int digits = 6)
{
return HashedOneTimePassword.GeneratePassword(secret, counter, digits);
}
private static long GetCurrentCounter()
{
return GetCurrentCounter(DateTime.UtcNow, UNIX_EPOCH, 30);
}
public static long GetCurrentRemaining()
{
return (long)(DateTime.UtcNow - UNIX_EPOCH).TotalSeconds % 30;
}
private static long GetCurrentCounter(DateTime now, DateTime epoch, int timeStep)
{
return (long)(now - epoch).TotalSeconds / timeStep;
}
public static bool IsValid(string secret, string password, int checkAdjacentIntervals = 1)
{
if (password == GetPassword(secret))
return true;
for (int i = 1; i <= checkAdjacentIntervals; i++)
{
if (password == GetPassword(secret, GetCurrentCounter() + i))
return true;
if (password == GetPassword(secret, GetCurrentCounter() - i))
return true;
}
return false;
}
}
I did try to set checkAdjacentIntervals to 5,i was able to validate the google authenticator code , but as mentioned earlier, it validates the past codes which is not right in my case.
So we have corrected the server's time by synchronizing it correctly using NTP , then it started working as expected.