Closed subversivo58 closed 6 years ago
Hi! The time window of 30 seconds is not based on the generation time but based on the system clock. So at every 30 seconds of a minute, it will expire.
Thus, if you generate at 13:00:00 hrs, you have 30s left, but if you generate at 13:00:25 hrs, you effectively have 5s left till the code expires.
Connected to #22
Hmmm ... now I understand that time is based on the system clock and in case of using the version for the browser is based on the user's clock.
I do not want to pollute the issue since the answer brought clarification but does that mean that the browser version is not compatible with Google Authenticator?
I tried several times to scan the QRCode within Google Authenticator time but the token is never validated :confused:
Could you please clarify this or should I open another issue for this thought?
Checked it now, works ok with browser. QR code will contain link otpauth://totp/{NAME}?secret={SECRET} to be imported. Also you can use it directly by inserting as href
to <a>
tag. JS redirect not works in my case
Also never use browser to check validity. Only generation by otplib
and sending to server(otplib
don't needed to send) and checking in SERVER.
In another case it can be easily broken, because user data can contain everything
@subversivo58 Maybe this may help. I've checked on my phone. https://codepen.io/anon/pen/KQvReJ Ensure your clocks on both devices (browser and google authenticator) are in sync.
thanks @cyclopentan. Agreed. In most cases, all checks should be done on server side. The browser package was provided in the event that anyone would like to do something different, like given a secret, check for validity via the tokens
Thanks @cyclopentan, @yeojz. I usually go to the SpeakEasy library when I have to apply 2-factor authentication, but I'm just trying something different and so I went to this library.
I am studying a use case in a decentralized network using interconnected WebRTC channels and a database formulated in a blockchain implementation (using IndexedDB).
As the security of this case study is based on "trust" (browser confidence) the user can choose to save their password in localStorage and optionally use 2FA for a proof of authenticity ...
Basically the credentials of the user are his PGP keys and assuming the user wants an extra layer he activates the use of 2FA this forces him to scan a QRCode and take the validation test if the test is successful it will add to the blockchain of the network this secret.
As the network is based on multiple channels connected to each other the login is nothing more than a test of consensus where 50% + 1 of the pairs recognizes that:
When a new channel is identified in the network (by WebSoket / Signaling), the other channels perform this check and wait for the result (positive or negative) to connect to this new channel or not.
The use of 2FA would follow this same flow the difference would be:
Before I found this library I was using SpeakEasy to test ... the peers sent the secret and the token using the method POST
to server for validate (using JSON in the peer response) and thus formulating the network concensus.
But this was only to test and was slow, the actual verification should only happen in pairs, use a server to check tokens flees the proposal of a decentralized network.
I found this library rightly researching about generating a token based on a secret and doing the verification on the front end.
In a "poor" summary the peers do not need to scan the QRCode, they simply use the secret and test the token informed to formulate the consensus.
@yeojz I tested your last example that shows the generation of tokens to compare with Google Authenticator I got to reach a difference of 2 seconds.
I can not say how fast the data exchanges occur in the WebRTC channels ... keeping this difference low locally gets to the concession of the pairs (20) in less than 2 seconds.
With a slightly more critical look it is easy to assume that in a test environment that simulates real conditions different machines will not be synconized which will lead to a negative consensus every time.
I apologize for the lengthy explanation of a specific use case, I will be dedicated to testing conditions in which the peers do not have a synchronized clock (maybe some virtualization)
I have not yet started testing as described at the end of the long comment above but I've been thinking:
Between 2 computers (not synchronized), computer A sends B to test its secret and the token, could also send its timestamp to refactor this difference between the clocks before B checks.
I'll go with #22 to see if a possible solution helps with this thinking.
Thank you for your help, I believe that the main focus of the question has been clarified.
Sorry for offtop
@subversivo58 your project sounds interesting can you provide a link?
HOTP is based on hash function and is symmetric. If you can check token, you can generate it
In case when browser checks user identy by one-time-password(OTP) locally it can be cracked by reading localStorage
You can read more about assymetric cryptography, but remember about brute force :)
Good luck!
Thanks @cyclopentan.
Sorry I do not have a link yet, I'm developing locally to serve as a decentralized login system to use on a GitHub (Static) page where I'm setting up my personal blog.
I have not yet come up with a "usable" prototype I hope to publish soon.
I also ask for forgiveness for extending a comment outside the scope of this library.
@subversivo58 feel free to post your prototype here when you are ready. There may be some interested parties.
Closing this issue for now.
I am testing locally and I noticed that the time of the step that by default should be 30 seconds is not always respected when verifying.
To illustrate I made a simple
setInterval()
to check the token every 1 second.I could not understand why sometimes it indicates invalid after 5 seconds, others after, 19, 24 ... anyway I could not identify a pattern.
Test case: CODEPEN
used in: