Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOTP window start #46

Open
miloush opened this issue May 1, 2023 · 7 comments
Open

TOTP window start #46

miloush opened this issue May 1, 2023 · 7 comments

Comments

@miloush
Copy link
Contributor

miloush commented May 1, 2023

We have Totp.RemainingSecods() which however does not indicate when the current time window started. There is no way to find out the steps that the Totp was created with (#45) so developers cannot even calculate it manually given an instance of Totp.

How about adding Totp.ElapsedSeconds()?

@nabeel-servcorp
Copy link

We have Totp.RemainingSecods() which however does not indicate when the current time window started. There is no way to find out the steps that the Totp was created with (#45) so developers cannot even calculate it manually given an instance of Totp.

How about adding Totp.ElapsedSeconds()?

Why not use the totp.RemainingSeconds() method to get the remaining seconds and then subtracting it from DateTime.UtcNow to get the elapsed seconds?

@miloush
Copy link
Contributor Author

miloush commented Jul 20, 2023

That doesn't give you any meaningful information, does it? If the remaining seconds is 5 and UtcNow is 12:34:56, then subtracting gives you 12:34:51, regardless of when the window actually started..

@damiarnold
Copy link

The step time (window) should already be known when creating your TOTP object, so you will need a reference to that value to do the calculation.
Maybe this snippet will help point you in the right direction:

var window = 30;
var totp = new OtpNet.Totp(
    step:  window,
    secretKey: xxxxxxx)
...
var dtNow = DateTime.UtcNow;
var remainingSeconds = totp.RemainingSeconds();
Console.WriteLine($"Window:       {window} seconds");
Console.WriteLine($"Remaining:    {remainingSeconds}");
Console.WriteLine($"Now:          {dtNow.ToLocalTime()}");
Console.WriteLine($"Window start: {dtNow.AddSeconds(remainingSeconds - window).ToLocalTime()}");

@miloush
Copy link
Contributor Author

miloush commented Jul 20, 2023

Thank you @damiarnold I understand that, but I cannot do that if I am not the one who created the Totp object. And when I have several Totp objects I created, I have to keep a table of the objects and their windows, while the Totp object already has all the information needed.

@damiarnold
Copy link

Fair enough - I agree that convenience properties would help in many of these cases - especially if you are not the one creating the objects and do not have access to their initial constructor argument values.

Short of submitting a pull request, you could always (as a last resort) use reflection on the private members, but this may be a non-starter for your use case, and is certainly not my go-to solution unless there is no other reasonable choice.

@kspearrin any thoughts on merits of providing public property wrappers for private members such as the Totp members _step, _totpSize, _correctedTime as well as the Otp _hashMode member? There may be a couple in the Hotp class I haven't peeked into yet, but if this seems reasonable, I could possibly work on a pull request in the next week or so for "convenience properties" for reasonable members that are currently private/protected, as the workarounds many of us use now do have some limitations.

@miloush
Copy link
Contributor Author

miloush commented Jul 20, 2023

I did #49. I also looked into ElapsedSeconds() and since RemainingSeconds() returns integral value (as opposed to TimeSpan or double), I don't find enough value in ElapsedSeconds() if #49 is merged since you will have acces to the Step property and can calculate that easily (RemainingSeconds() in practice already calculates Step - ElapsedSeconds()).

For people who are looking for actual elapsed or remaining time (e.g. to update the OTP displayed in UI), it would be more useful to have the window start as DateTime available.

@stromkos
Copy link

so developers cannot even calculate it manually given an instance of Totp

You can calculate the step manually from only RemainingSeconds() , but it would take up to step + 2 seconds to do so.

And when I have several Totp objects I created, I have to keep a table of the objects and their windows, while the Totp object already has all the information needed.

The only reason for a table would be if each object had a unique step value.

The RemainingSeconds() and window start times will be identical for all instances using the same step, time source and time correction offset.

Note: the delay parameter or step is ignored on some authenticator apps and hardcoded to 30 seconds.

The following methods return the start of the window for a given step. The period parameter calculates the start of the next window(s) value can be negative for previous windows.

A period of 1 would give just past the end time of the current window.

DateTimeOffset GetCurrentWindowStart(long step = 30, int period = 0)
{
    return DateTimeOffset.FromUnixTimeSeconds((
                         DateTimeOffset.UtcNow().ToUnixTimeSeconds()
                         / step + period ) * step);
}

Or if you want the value in the local time zone:

DateTimeOffset GetCurrentWindowStartLocal(long step = 30, int period = 0)
{
    return ConvertTime(DateTimeOffset.FromUnixTimeSeconds((
                         DateTimeOffset.UtcNow().ToUnixTimeSeconds()
                         / step + period) * step), TimeZoneInfo.Local);
}

Or just the Time Parameter:

long GetCurrentWindowStart(long step = 30, long period = 0)
{
    return (DateTimeOffset.UtcNow().ToUnixTimeSeconds() / step + period ) * step;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants