bellstrand / totp-generator Goto Github PK
View Code? Open in Web Editor NEWGenerate TOTP tokens from key
License: MIT License
Generate TOTP tokens from key
License: MIT License
No matter how many digits I set, it never returns beyond 8-10. Is there a way or an algorithm to support more digits?
const Totp = require('totp-generator')
console.log(
Totp("JBSWY3DPEHPK3PXP", {
digits: 48,
period: 1,
})
)
How to generate authenticator key
when the otp substring results in a string that has zero as the first digit, parseInt will strip it off resulting in a five digit return value.
https://github.com/bellstrand/totp-generator/blob/master/index.js#L17
Heya,
I'd love some function that takes a secret and code as parameters and returns if the code is valid at the current time. I'd really like if this had a window
parameter as well that allowed ±1 intervals, ±2, etc. to be checked to account for the amount of time it takes a user to enter/submit their code.
If this isn't feasible or doesn't fit into your vision for the library, a parameter for an offset (or custom time altogether) would work nicely!
Please add something like this in the documentation:
import getToken from "totp-generator";
getToken("secret")
When I try to use totp, I get an error inside the index file of the totp-generator module in the getToken function
the mistake is JsSHA is not a constructor
'use strict';
let JsSHA = require('jssha');
module.exports = function getToken(key, options) {
options = options || {};
let epoch, time, shaObj, hmac, offset, otp;
options.period = options.period || 30;
options.algorithm = options.algorithm || 'SHA-1';
options.digits = options.digits || 6;
key = base32tohex(key);
epoch = Math.round(Date.now() / 1000.0);
time = leftpad(dec2hex(Math.floor(epoch / options.period)), 16, '0');
shaObj = new JsSHA(options.algorithm, 'HEX'); // IN THIS LINE
shaObj.setHMACKey(key, 'HEX');
shaObj.update(time);
hmac = shaObj.getHMAC('HEX');
offset = hex2dec(hmac.substring(hmac.length - 1));
otp = (hex2dec(hmac.substr(offset * 2, 8)) & hex2dec('7fffffff')) + '';
otp = otp.substr(otp.length - options.digits, options.digits);
return otp;
}
I call it this way
const totp = require("totp-generator");
const token = totp("JBSWY3DPEHPK3PXP");
I am using react, this is the package.json
{
"name": "shop",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"bootstrap": "^4.6.0",
"jssha": "^3.2.0",
"react": "^17.0.2",
"react-bootstrap": "^1.6.0",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"totp-generator": "0.0.9",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/preset-env": "^7.14.2",
"@babel/preset-react": "^7.13.13"
}
}
Hi
Thanks for sharing this library with community!
I am running into an issue though when my key has the equals '=' char. From the docs it says '=' is acceptable:
{ key: 'H73TG4DV24=X=OHQYBWRPTRT5BB4=L7T' }
⨯ Error: Invalid base32 character in key
at TOTP.base32tohex (webpack-internal:///(rsc)/./node_modules/totp-generator/lib/esm/index.js:45:35)
at TOTP.generate (webpack-internal:///(rsc)/./node_modules/totp-generator/lib/esm/index.js:19:32)
at GET (webpack-internal:///(rsc)/./src/app/api/otp/route.ts:28:79)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:63815
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\trace\tracer.js:133:36
at NoopContextManager.with (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:7062)
at ContextAPI.with (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:518)
at NoopTracer.startActiveSpan (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:18093)
at ProxyTracer.startActiveSpan (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:18854)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\trace\tracer.js:122:103
at NoopContextManager.with (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:7062)
at ContextAPI.with (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\@opentelemetry\api\index.js:1:518)
at NextTracerImpl.trace (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\trace\tracer.js:122:28)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:56866
at AsyncLocalStorage.run (node:async_hooks:346:14)
at Object.wrap (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:37102)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:54639
at AsyncLocalStorage.run (node:async_hooks:346:14)
at Object.wrap (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:36351)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:54601
at AsyncLocalStorage.run (node:async_hooks:346:14)
at eU.execute (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:53994)
at eU.handle (C:\stuff\qoutequests.v3\web\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:65073)
at doRender (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:1333:60)
at cacheEntry.responseCache.get.routeKind (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:1555:34)
at ResponseCache.get (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\response-cache\index.js:49:26)
at DevServer.renderToResponseWithComponentsImpl (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:1463:53)
at C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:992:121
at NextTracerImpl.trace (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\trace\tracer.js:104:20)
at DevServer.renderToResponseWithComponents (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:992:41)
at DevServer.renderPageComponent (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:1856:35)
at async DevServer.renderToResponseImpl (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:1894:32)
at async DevServer.pipeImpl (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:911:25)
at async NextNodeServer.handleCatchallRenderRequest (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\next-server.js:271:17)
at async DevServer.handleRequestImpl (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\base-server.js:807:17)
at async C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\dev\next-dev-server.js:331:20
at async Span.traceAsyncFn (C:\stuff\qoutequests.v3\web\node_modules\next\dist\trace\trace.js:151:20)
at async DevServer.handleRequest (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\dev\next-dev-server.js:328:24)
at async invokeRender (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\router-server.js:163:21)
at async handleRequest (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\router-server.js:342:24)
at async requestHandlerImpl (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\router-server.js:366:13)
at async Server.requestListener (C:\stuff\qoutequests.v3\web\node_modules\next\dist\server\lib\start-server.js:140:13)
It doesn't matter the count of the '=', this key also results in the same error: QHQGOSBVK2J=OJYC7LB4UJLG6HF72IEV
After installing this library, i got this error
I tried removing node_modules and installing the project again, resetting the docker container but none of that helped, so i don't think its a problem on my end.
/opt/code/node_modules/totp-generator/index.js:42
base32 = base32.replace(/=+$/, "")
^
TypeError: base32.replace is not a function
at base32tohex (/opt/code/node_modules/totp-generator/index.js:42:18)
at getToken (/opt/code/node_modules/totp-generator/index.js:16:8)
at User.getTotpCodes (/opt/code/models/user.js:16:33)
at User.checkTotp (/opt/code/models/user.js:31:34)
at User.authenticate (/opt/code/models/user.js:54:24)
at async apiLogin (/opt/code/routes/admin.js:12:19)
My code:
const totp = require('totp-generator');
...
let codes = /* recovery codes */;
const period = (30 * 1000);
codes.push(parseInt(totp(totp, { timestamp: Date.now() - period}))); << exception
codes.push(parseInt(totp(totp)));
codes.push(parseInt(totp(totp, { timestamp: Date.now() + period})));
Add object with default properties and merge with input object:
Hello,
Im a Junior Developer and I ran into an issue where Amazon's token for TOTP will not work with this generator.
It took me some time however i've developed a working solution.
Would you be interested in said solution, explanation and code?
As this is my first contribution i'd like to get added to the list.
Thanks
I'd love to be able to generate a TOTP token with a key, but also know how much time is remaining in the current epoch interval (before that key will no longer be valid)
Line 17 in eafbb67
Math.floor
?Would you mind exposing the valid algorithm values as a type rather than an anonymous list of strings. This will make it easier to write code that takes the algorithm type as input. Currently to make our code typesafe we have to copy the valid values from the Options type into the code we are writing.
If the definition of Options was changed to the example below it would be much nicer to work with and would not require any changes if you add/remove algorithms in the future.
type AlgorithmOptions = "SHA-1" | "SHA-224" | "SHA-256" | "SHA-384" | "SHA-512" | "SHA3-224" | "SHA3-256" | "SHA3-384" | "SHA3-512";
type Options = {
digits?: number
algorithm?: AlgorithmOptions
period?: number
timestamp?: number
}
Thanks for this library btw :)
Please, provide setter for change key encoding as generate method options parameter. Now you use HEX, but most popular libraries use ASCII by default.
Maybe you could replace jssha package with the Web Crypto API which is pretty much supported everywhere, and would be way faster since it's natively implemented by the runtimes.
Tried using this package, but unfortunately I would get the error "Invalid base32 character in key" no matter what input key I used. I tried all numbers. I tried all letters. I tried an empty string. Always the same error.
Let me start by saying perhaps I just don't know enough about TOTP!
But it would be really neat to know when the current code expires, perhaps just a callback method that triggers when the key expires, that way I could make a responsive UI that doesn't need to recalculate the value every second just to verify if it's changed.
When I input 9 digits and the specified timestamp, I get a return value of 0.
const Totp = require('totp-generator')
console.log(
Totp("3IS523AYRNFUE===", {
digits: 9,
timestamp: 1634193300000
})
)
How to avoid the totp can be reused many times within the period?
Can we have a custom setting for the totp use one time only?
thanks
Can we please add support other encoding for key like base64, Uint8Array and ArrayBuffer?
If you like the idea, I can submit a PR.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.