Closed Davenchy closed 1 year ago
Can you provide me more info on how you generate a code? There are a couple options that can affect this. The biggest one is generating a RFC4226 strict otp or a GOogle Authenticator otp code. Google uses non-standard options by default, hence why I have the isGoogle
option.
You can use this site https://totp.danhersam.com/ just copied all the provided options and the output is not the same
The website gives the same output of real world apps e.g. authy when I am using my real secret e.g. github totp secret the site generates the same code I used another dart package called dart_dash_otp
and it generates the same correct code too.
Well my library doesn't do a lot of hand-holding, so you need to take certain things into account, like TimeZone, if its a Google mode authenticator or an RFC6238 authenticator. Google doesn't follow the official RFC spec, and unlike many libraries, I do not default to their standard, but I do support it.
That is why I asked for your code to see what you were doing, not where you were checking it against. Because there are a few nobs that usually need adjusting.
So things you need to do:
DateTime.now()
for Dart is UTC. Javascript (at least in the browser) defaults to your timezone.isGoogle: true
so that the secret is parsed through Base32, thats a google, thing. RFC variant doesn't base32 decode, it uses the string directly.The following code gives me the same code as that site you gave me, adjust for your timezone:
import 'package:otp/otp.dart';
import 'package:timezone/data/latest.dart' as timezone;
import 'package:timezone/timezone.dart' as timezone;
void main() {
final now = DateTime.now();
timezone.initializeTimeZones();
final pacificTimeZone = timezone.getLocation('America/Los_Angeles');
final date = timezone.TZDateTime.from(now, pacificTimeZone);
final code = OTP.generateTOTPCodeString(
'JBSWY3DPEHPK3PXP', date.millisecondsSinceEpoch,
algorithm: Algorithm.SHA1, isGoogle: true);
print(code);
}
OK Bro Thanks, I tried with isGoogle
set to true
and it worked.
Really sorry for the misunderstand.
Well my library doesn't do a lot of hand-holding, so you need to take certain things into account, like TimeZone, if its a Google mode authenticator or an RFC6238 authenticator. Google doesn't follow the official RFC spec, and unlike many libraries, I do not default to their standard, but I do support it.
That is why I asked for your code to see what you were doing, not where you were checking it against. Because there are a few nobs that usually need adjusting.
So things you need to do:
- Make sure your time is adjusted for your timezone, by default
DateTime.now()
for Dart is UTC. Javascript (at least in the browser) defaults to your timezone.- Make sure you are using SHA1 algorithm. The default is SHA256 in modern TOTP, but google is still on SHA1, but does support SHA256, but most apps don't use it.
- You have to pass in
isGoogle: true
so that the secret is parsed through Base32, thats a google, thing. RFC variant doesn't base32 decode, it uses the string directly.The following code gives me the same code as that site you gave me, adjust for your timezone:
import 'package:otp/otp.dart'; import 'package:timezone/data/latest.dart' as timezone; import 'package:timezone/timezone.dart' as timezone; void main() { final now = DateTime.now(); timezone.initializeTimeZones(); final pacificTimeZone = timezone.getLocation('America/Los_Angeles'); final date = timezone.TZDateTime.from(now, pacificTimeZone); final code = OTP.generateTOTPCodeString( 'JBSWY3DPEHPK3PXP', date.millisecondsSinceEpoch, algorithm: Algorithm.SHA1, isGoogle: true); print(code); }
Thank you for this, we required these settings to complete unit tests, maybe add this to the documentation? Was good to mention that isGoogle
does the base32 decode too.
The packages generates invalid codes I used this site https://totp.danhersam.com to validate the codes but the site generated code and the package code are not the same. Also I tried this pub package https://pub.dev/packages/dart_dash_otp and it works will. So if you can fix your package it will be great because it toke a long time to find another working solution as your package is suggested first.