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

Google Token does not match generated token (clock is accurate) #99

Open
Hereward opened this issue Dec 23, 2017 · 15 comments · May be fixed by #107
Open

Google Token does not match generated token (clock is accurate) #99

Hereward opened this issue Dec 23, 2017 · 15 comments · May be fixed by #107

Comments

@Hereward
Copy link

Hereward commented Dec 23, 2017

I am running meteor app on Windows 10 with speakasy installed.
time.is reports:

Your time is exact!The difference from Time.is was -0.039 seconds (±0.013 seconds).

However the tokens do not match - at all.

This is my code:

    verifyToken() {
        var myToken = this.state.authCode.trim()

        let currentValidToken = speakeasy.totp({ secret: this.secretBase32, encoding: 'base32' });
        let verified = speakeasy.time.verify({ 
            secret: this.secretBase32, 
            encoding: 'base32', 
            token: myToken
        })

        console.log(`mySecret = [${this.secretBase32}] CVT = [${currentValidToken}] MYTOKEN = ${myToken} VERIFIED= [${verified}]`);

        if (!verified) {

            return swal({
                title: "Invalid Code",
                text: "You have 2 more attempts.",
                showConfirmButton: true,
                type: "error"
            });
        } else {

            return swal({
                title: "Jackpot!",
                text: "You da man.",
                showConfirmButton: true,
                type: "success"
            });
        }
    }
@markbao
Copy link
Collaborator

markbao commented Dec 23, 2017

Hi there, can you check that the time is accurate both on the device you’re using to get tokens (the device running Google Authenticator), as well as the server running the code? Your code looks right, so that’s the first thing I would look at.

The next thing to check is whether the key you’ve inputted into GA is the same as the key you’re verifying with. If we find that the times on the two devices are correct, then we can try to manually input the key into GA and see if that changes the result.

Finally, I saw you commented on the issue of getting the demo working. If you were able to get the demo working locally, let me know if you see the same issue. That will help troubleshoot.

@Hereward
Copy link
Author

Yes I've confirmed that the time on my Android phone is correct using the time correction feature in Authenticator.

This is the key I'm using:
FRWFINCSNFMGKTDYGAXSIVCKJNOV2I2UF5CWE22BGVAEIMDFKR6Q

I followed your advice and put that key in manually as a separate entry. They are both now generating the same codes (ie. the Auth tokens for the manually entered key and the key generated by the QR code from speakeasy).

But unfortunately the tokens generated by speakeasy.totp using the same key do not match. They are not just out of sync - none of them match. I have stored an array of all values over a long period of time and there are no matches with the Google Authenticator tokens.

@Hereward
Copy link
Author

One possible reason for this is that I'm executing this code on the client in Meteor rather than the server. I would have though the clock would be the same as both client and server are on the same machine - but I'll try executing the function on the server to see if that makes a difference.

Any other suggestions greatly appreciated.

@markbao
Copy link
Collaborator

markbao commented Dec 23, 2017

Thanks for checking those. So the JS code is running on the client? The package doesn’t support (as in, it hasn’t been tested) usage on the client side - it’s exclusively for server side use. Do try to see if it works on the server and let me know what you find.

@Hereward
Copy link
Author

Thanks - I'll see if I can do that although the implementation in Meteor is quite different to your demo app. I'll see if I can get that working too,

@Hereward
Copy link
Author

Hereward commented Dec 27, 2017

I have changed the implementation in Meteor to execute the speakeasy functions on the server.

This did not fix the problem. The package is working, but it generates a different set of tokens to Google Authenticator. I have re-checked that my clock is accurate.

The tokens on Authenticator & my app are synchronised in that they update at exactly the same moment, but they always have different values.

@Hereward
Copy link
Author

Hereward commented Dec 28, 2017

Can I ask how critical is the time synchronisation to the speakeasy function working right. I cannot get my clock correct to less than 0.2 secs. I have sycned the time dozens of times as well as tried time.nist.gov & time.windows.com as well as trying to manually sync the time by watching the clock and setting the time by hand. I have also tried resetting my Windows time service. I've spent many hours on this, but my clock is always either slightly fast or slightly slow.

My clock is currently 0.2 seconds behind.

What degree of accuracy is required?

@markbao
Copy link
Collaborator

markbao commented Dec 28, 2017

I don’t think clock sync is the issue here - usually it is when the clock is significantly out of sync, which it isn’t in this case. Can you try to get the demo application working? That will help us see if it is an implementation issue or something different.

@adrai
Copy link

adrai commented Feb 21, 2018

If you have to support Android devices, make sure you're using algorithm: sha1

@harshjv
Copy link

harshjv commented Mar 14, 2018

@markbao this is because of https://github.com/speakeasyjs/speakeasy/blob/master/index.js#L533

Google Authenticator needs base32 tokens.

You can;

const { base32 } = speakeasy.generateSecret()
const otpAuthUrl = speakeasy.otpauthURL({ secret: base32, label: 'Untitled' })
// use otpAuthUrl to generate QR code

harshjv added a commit to harshjv/speakeasy that referenced this issue Mar 14, 2018
@harshjv harshjv linked a pull request Mar 14, 2018 that will close this issue
@tommilligan
Copy link

The base32 secret shown in your example is not a multiple of 8 in length - therefore this bug may be cased by #135

@MercenaryUSA
Copy link

I am having this same issue. I've verified that the clock is accurate, I'm using base32 for the secret and it's a multiple of 8, but Google Authenticator is still generating a separate code from speakeasy.

Has anyone found a solution for this?

@carvalholeo
Copy link

Hey guys. Unlikely, the developer updated this package to unmaintained. You can have something with otplib (as suggested in #86), Speakeasy from @Levminer (issue #134) or Squeakeasy from @mlogan (#131). Also, maybe you can try some packages from Passport.js.

Good lucky!

@MercenaryUSA
Copy link

I am having this same issue. I've verified that the clock is accurate, I'm using base32 for the secret and it's a multiple of 8, but Google Authenticator is still generating a separate code from speakeasy.

Has anyone found a solution for this?

Never mind, I got it working. It was simply an error in my code that I didn't realize. That's what happens when you stay up for over 12 hours and are coding at 3am.

@MercenaryUSA
Copy link

MercenaryUSA commented Apr 22, 2021

Hey guys. Unlikely, the developer updated this package to unmaintained. You can have something with otplib (as suggested in #86), Speakeasy from @Levminer (issue #134) or Squeakeasy from @mlogan (#131). Also, maybe you can try some packages from Passport.js.

Good lucky!

Typically, I do not trust forks of known packages because you never know what they might contain. While you can just look over the source to figure out if anything is in there, I'd rather not waste my time.

The only time I typically review the source of a package is if something isn't working as intended or I plan on making improvements myself, but I never fork and release my own version if I do make changes.

Nonetheless, version 2.0.0 is working as intended as long as you use the appropriate encoding (base32), secret length (multiples of 8) and your clock is synchronized with the server (or localhost if you're testing).

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

Successfully merging a pull request may close this issue.

7 participants