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

RFE: Validate method for additional security #34

Open
ralscha opened this issue Apr 17, 2020 · 6 comments
Open

RFE: Validate method for additional security #34

ralscha opened this issue Apr 17, 2020 · 6 comments

Comments

@ralscha
Copy link
Contributor

ralscha commented Apr 17, 2020

For a secure TOTP I need a method to check the validity of 3 TOTP codes.
In my example I check 24 hours ahead and behind. The 3 codes must exist in this period
and they must be consecutive.

The method must accept the secret and 3 TOTP codes and returns two results.

  • boolean valid: true = the 3 codes are valid and they are consecutive.
  • int shift: how many periods the codes are behind or ahead

Here an idea how this could look like:

    TimeProvider timeProvider = new SystemTimeProvider();
    CodeGenerator codeGenerator = new DefaultCodeGenerator();
    DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
    long periods = TimeUnit.HOURS.toSeconds(24) / 30; 
    //would be nice if I could use verifier.getTimePeriod(), instead of the hardcoded 30
    //or there is a method to set the discrepancy in seconds and the library calculates the periods
    
    verifier.setAllowedTimePeriodDiscrepancy((int)periods); 
    // setAllowedTimePeriodDiscrepancy does not accept long
  
    VerificationResult result = verifier.areCodesValid(secret, code1, code2, code3);
    //result should contain a boolean, if the codes are valid and consecutive
    //and it should return a time shift number (int). How many periods the codes are behind or ahead

For my example TOTP application I had to write my own TOTP verifier based on the now archived aerogear project. Would be nice if I could switch to your library.

See also this issue for more details why this method is needed.

@samdjstevens
Copy link
Owner

Hey,

Thanks for the RFE - I think this should be fairly trivial to implement and can see it being useful.

I'm not so sure about the return value needing to expose both validity, and time shift data - is allowing such a huge window of 24 hours really necessary?

When asking the user for 3 consecutive codes, would a period of say 5 minutes before/after not be enough for them to gather their 3 codes (as they generate every 30 seconds)?

@ralscha
Copy link
Contributor Author

ralscha commented Apr 19, 2020

I'm not the expert, but I think a window of at least 1 hour because of summer/winter time makes sense. Maybe 24 hours is also a good idea when somebody changes the system clock (instead of the timezone) when he travels around. And according to the author of the issue there is no harm in checking such a large window.

I guess this window should be configurable anyway. A project can decide what makes sense and what not.

@samdjstevens
Copy link
Owner

I've started work on this here: #35

Returning the time period as well as the true/false of code(s) being valid does make the API a bit more verbose - and I don't think the time period differential will be used a great deal - but I think it's still acceptable, and I have done so in a backwards compatiple way.

With the PR, your solution would look something like this:

TimeProvider timeProvider = new SystemTimeProvider();
CodeGenerator codeGenerator = new DefaultCodeGenerator();
DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);
verifier.setAllowedTimePeriodDuration(Duration.ofHours(24));

VerifyResult result = verifier.verifyConsecutiveCodes(secret, code1, code2, code3);
boolean isValid = result.isValid();
int timePeriodDifference = result.getTimePeriodDifference();

@ralscha
Copy link
Contributor Author

ralscha commented Apr 22, 2020

Hi. That looks great.

@samdjstevens
Copy link
Owner

Just an update on this - whilst looking into the required code changes for this request I stumbled across a few areas where I think the internal design/external API isn't quite right currently and should be improved.

Alongside implementing the above I have refactored the API in a non backwards compatible way, so shall be releasing this feature as part of the upcoming 2.0.0 release of the library.

The above example of the new feature will be slightly different now:

TimeProvider timeProvider = new SystemTimeProvider();
CodeGenerator codeGenerator = new DefaultCodeGenerator();
DefaultCodeVerifier verifier = new DefaultCodeVerifier(codeGenerator, timeProvider);

List<String> codes = ...

// Verify that the list of codes are valid, allowing for a time drift of +/- 24 hours
VerifyResult result = verifier.verifyConsecutiveCodes(secret, codes, Duration.ofHours(24));
boolean isValid = result.isValid();
Duration timeDrift = result.getTimeDrift();
// "Your clock is " + timeDrift.getSeconds() + " seconds out from the server."

@digvijaydl
Copy link

Hi, Thanks for wonderful library.
When do you plan to release upcoming 2.0.0 library and what are new features?
Also, want to know if this library complies with RFC4226 / RFC6238 standards?

Thanks in advance.

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

3 participants