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

Confused with time #695

Open
softmarshmallow opened this issue Jan 11, 2023 · 2 comments
Open

Confused with time #695

softmarshmallow opened this issue Jan 11, 2023 · 2 comments

Comments

@softmarshmallow
Copy link

softmarshmallow commented Jan 11, 2023

If I set step to 7 days,

  • Will it generate same output for 7 days?
    • Then, why Am i getting new key every (about) 10 minutes?
  • Is the generated key valid for x from the moment generated or until the next step?
    • e.g. while step is 10.. start: 0, generated at 5,
      • Is the key valid until epoch 10?
      • Is the key valid until epoch 5 + 10 = 15?

To Ask the above question otherwise,

If I generate 10 otp with step 10 every 1 second. Will all 10 expire at the same time or each after 10 seconds?

This is very confusing since I have no deep understanding of the algorithm and hard to test (since I have to actually wait for that time)

I'm asking this since I am totp for special use, It is for generating short-lived api key, not authorizing users.
So my application cannot have a second entry (try-again) UX.

Service A - generator
Service B - validator

They only share the secret. and the generated key should be valid for specific time (not with step, time.)

@softmarshmallow softmarshmallow changed the title Confused with time span Confused with time Jan 11, 2023
@softmarshmallow
Copy link
Author

softmarshmallow commented Jan 11, 2023

Self Answering

When you set the step to 7 days (604800 seconds) in the otplib.totp.generate method, it will not generate the same output for 7 days. The TOTP algorithm uses the current time and a shared secret key to generate the one-time password, so the password will change at regular intervals (the "step" interval) based on the current time.

The reason you are getting a new key every 10 minutes or so even though you've set the step to 7 days is likely due to the default step value being used. By default, TOTP uses a step of 30 seconds. If you want the key to be valid for 7 days and not change every 30 sec, you will have to set the step value to be the number of seconds that you want the key to be valid, in this case 604800 sec (7 days).

Regarding the "validity" of the key, The TOTP algorithm uses time-based windows, it generates a new TOTP every step seconds. So once a TOTP is generated, it is valid only for that specific step.
For example, if you generate a TOTP at 5 seconds with a step of 10 seconds, this key will be valid until epoch 5 + 10 = 15 sec.

The reason for that is to increase the security, using a moving window of time instead of an absolute time and a fixed password.

For your use case, it sounds like you want to generate a short-lived API key that is valid for a specific amount of time and you want to avoid the user having to try again.
You could generate a key using TOTP with a long step (the time you want the key to be valid) and then store the timestamp at which the key was generated as well as the step,
On the client side, you could check the current timestamp and compare it with the timestamp of when the key was generated, if it's greater than the timestamp + step, it's considered invalid.

e.g:

const otplib = require('otplib');
const expiresIn = 86400; // 24 hours
const secret = 'JBSWY3DPEHPK3PXP';
const timestamp = Date.now()/1000;
const expirationTime = timestamp + expiresIn;

const token = otplib.totp.generate(secret, {epoch: timestamp, step: expiresIn });
console.log(token);

You could then store the token, timestamp and expiresIn in


If you generate 10 OTPs with a step of 10 seconds and generate each OTP every 1 second, all 10 OTPs will expire at different times.

When you generate an OTP with the otplib.totp.generate(secret, { step: 10 }) method, it will be valid for 10 seconds from the time it was generated.

For example,

If you generate the first OTP at time 0 seconds, it will be valid until time 10 seconds.
If you generate the second OTP at time 1 second, it will be valid until time 11 seconds.
If you generate the third OTP at time 2 seconds, it will be valid until time 12 seconds.
and so on

All OTPs will be valid for 10 seconds from the time they were generated, and they will expire at different times since they are generated at different moments.
This means that you should use the generated OTPs immediately, as they will expire relatively soon.

Keep in mind that TOTP tokens are vulnerable to replay attacks, you should use some kind of secure and reliable way to store the tokens and timestamps and validate them on the client side.
Also, the secret

@Lerado
Copy link

Lerado commented Jul 28, 2023

Self Answering

When you set the step to 7 days (604800 seconds) in the otplib.totp.generate method, it will not generate the same output for 7 days. The TOTP algorithm uses the current time and a shared secret key to generate the one-time password, so the password will change at regular intervals (the "step" interval) based on the current time.

The reason you are getting a new key every 10 minutes or so even though you've set the step to 7 days is likely due to the default step value being used. By default, TOTP uses a step of 30 seconds. If you want the key to be valid for 7 days and not change every 30 sec, you will have to set the step value to be the number of seconds that you want the key to be valid, in this case 604800 sec (7 days).

Regarding the "validity" of the key, The TOTP algorithm uses time-based windows, it generates a new TOTP every step seconds. So once a TOTP is generated, it is valid only for that specific step. For example, if you generate a TOTP at 5 seconds with a step of 10 seconds, this key will be valid until epoch 5 + 10 = 15 sec.

The reason for that is to increase the security, using a moving window of time instead of an absolute time and a fixed password.

For your use case, it sounds like you want to generate a short-lived API key that is valid for a specific amount of time and you want to avoid the user having to try again. You could generate a key using TOTP with a long step (the time you want the key to be valid) and then store the timestamp at which the key was generated as well as the step, On the client side, you could check the current timestamp and compare it with the timestamp of when the key was generated, if it's greater than the timestamp + step, it's considered invalid.

e.g:

const otplib = require('otplib');
const expiresIn = 86400; // 24 hours
const secret = 'JBSWY3DPEHPK3PXP';
const timestamp = Date.now()/1000;
const expirationTime = timestamp + expiresIn;

const token = otplib.totp.generate(secret, {epoch: timestamp, step: expiresIn });
console.log(token);

You could then store the token, timestamp and expiresIn in

If you generate 10 OTPs with a step of 10 seconds and generate each OTP every 1 second, all 10 OTPs will expire at different times.

When you generate an OTP with the otplib.totp.generate(secret, { step: 10 }) method, it will be valid for 10 seconds from the time it was generated.

For example,

If you generate the first OTP at time 0 seconds, it will be valid until time 10 seconds. If you generate the second OTP at time 1 second, it will be valid until time 11 seconds. If you generate the third OTP at time 2 seconds, it will be valid until time 12 seconds. and so on

All OTPs will be valid for 10 seconds from the time they were generated, and they will expire at different times since they are generated at different moments. This means that you should use the generated OTPs immediately, as they will expire relatively soon.

Keep in mind that TOTP tokens are vulnerable to replay attacks, you should use some kind of secure and reliable way to store the tokens and timestamps and validate them on the client side. Also, the secret

I don't think it works as you described. Check here https://datatracker.ietf.org/doc/html/rfc6238
The algorithm considers timesteps of 30s by default. Tokens generated within the same timestep are only valid within that timestep. So if you issue a token at 00:20, it'd only be valid for 10s. The RFC recommends however to be tolerent on network delay so we can consider token valid if they were create during the previous timestep.

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

2 participants