Two Factor Google Authentication not matching the codes on the server- ASP.Net MVC

2.9k views Asked by At

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

There are 2 answers

0
WonderHeart On BEST ANSWER

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.

0
Rajesh Kumar On

I know this is an old question, but it may help others like me who come looking for an answer. Google Authentication works based on time. API would validate the codes that were generated recently in the past based on time (mark it, it is time, not the time-zone). So, if actual time of your system is not in synch with the device on which you are generating the codes, the issue would occur. Especially, when time of the system is behind the time of the device. If you want to validate my answer, try entering some older codes (based on the tie gap between the system and the device). checkAdjacentIntervals would help you when your system is ahead of the device, but not when it is behind.