We have included two-factor authentication in one of our applications using Google Authenticator. Something really strange happened in QA. Although I managed to fix it, I'm not quite sure why the fix works.
For our shared secret, we assigned a GUID to the user when they begin to configure TFA. The GUID receives the base-32 encoding and places it in the URL, which is converted into a QR code and verified by the user using the phone:
otpauth:
And everything works well for all the non-ios machines we tried. On ios alone, it throws a really strange error when trying to scan a barcode most of the time:
Invalid barcode
The barcode '[same as above]' is not a valid authentication token barcode.
It complies with Google / RFC 4226 minimum secret requirement (128 bit), Base32 encoded correctly, etc. Why is this failing? A typical reason for this message is a space in the URL, but it is not.
If I add a little seed at the beginning of the tutorial, everything will work fine:
otpauth:
This is essentially the difference between:
secret = enc.Encode32(Encoding.ASCII.GetBytes("iphonesucks" + Guid.NewGuid().ToString()));
secret = enc.Encode(Encoding.ASCII.GetBytes(Guid.NewGuid().ToString()));
newAuthUrl = string.Format("otpauth://totp/myapp_user?secret={0}", secret);
I have two crazy theories about why this might work:
The ios port requires more than 128 bits. My comment / seed is enough to pounce on this limit, no matter what happens ... except that I actually gave it more than 128 bits, since it was a guid-as string.
After decoding Base32, the ios application recognizes the secret string as guid and does something else with it.
, . - ? .