{"id":13510243,"url":"https://github.com/hectorm/otpauth","last_synced_at":"2026-10-19T12:44:51.138Z","repository":{"id":15421289,"uuid":"77928713","full_name":"hectorm/otpauth","owner":"hectorm","description":"One Time Password (HOTP/TOTP) library for Node.js, Deno, Bun and browsers.","archived":false,"fork":false,"pushed_at":"2026-10-12T11:02:37.000Z","size":9015,"stargazers_count":1485,"open_issues_count":6,"forks_count":85,"subscribers_count":12,"default_branch":"master","last_synced_at":"2026-10-16T21:15:29.474Z","etag":null,"topics":["auth","authenticator","browser","bun","deno","google-authenticator","hotp","javascript","node","nodejs","otp","otpauth","security","totp","two-factor","two-factor-authentication"],"latest_commit_sha":null,"homepage":"https://hectorm.github.io/otpauth/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hectorm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":"hectorm","custom":"https://hector.molinero.dev/donate"}},"created_at":"2017-01-03T15:24:03.000Z","updated_at":"2026-10-12T01:21:34.000Z","dependencies_parsed_at":"2026-10-09T13:44:59.538Z","dependency_job_id":"53a84684-eedb-45a4-92c4-4a059551546b","html_url":"https://github.com/hectorm/otpauth","commit_stats":{"total_commits":949,"total_committers":6,"mean_commits":"158.16666666666666","dds":0.5216016859852477,"last_synced_commit":"ce9a5c0690eaf79ea57df02d81bedd8e2f7926df"},"previous_names":["zant95/otpauth"],"tags_count":112,"template":false,"template_full_name":null,"purl":"pkg:github/hectorm/otpauth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hectorm%2Fotpauth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hectorm%2Fotpauth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hectorm%2Fotpauth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hectorm%2Fotpauth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hectorm","download_url":"https://codeload.github.com/hectorm/otpauth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hectorm%2Fotpauth/sbom","scorecard":{"id":459434,"data":{"date":"2025-08-11","repo":{"name":"github.com/hectorm/otpauth","commit":"ca3e2005e00ce09461f529b3e4ef3908647ef3c1"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":7.6,"checks":[{"name":"Maintained","score":10,"reason":"17 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 1/14 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:22","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:21","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:97","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:228","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/main.yml:288","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:21","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:65","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:128","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:159","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:191","Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:261","Info: jobLevel 'contents' permission set to 'read': .github/workflows/scorecard.yml:19","Info: jobLevel 'actions' permission set to 'read': .github/workflows/scorecard.yml:18","Info: found token with 'none' permissions: .github/workflows/codeql.yml:1","Info: found token with 'none' permissions: .github/workflows/main.yml:1","Info: found token with 'none' permissions: .github/workflows/scorecard.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:  30 out of  30 GitHub-owned GitHubAction dependencies pinned","Info:   5 out of   5 third-party GitHubAction dependencies pinned","Info:   4 out of   4 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'master'","Warn: branch 'master' does not require approvers","Warn: codeowners review is not required on branch 'master'","Warn: no status checks found to merge onto branch 'master'","Warn: PRs are not required to make changes on branch 'master'; or we don't have data to detect it.If you think it might be the latter, make sure to run Scorecard with a PAT or use Repo Rules (that are always public) instead of Branch Protection settings"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/main.yml:222"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (17) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T10:42:10.069Z","repository_id":15421289,"created_at":"2025-08-19T10:42:10.069Z","updated_at":"2025-08-19T10:42:10.069Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344836268,"owners_count":38332320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-17T02:00:06.547Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["auth","authenticator","browser","bun","deno","google-authenticator","hotp","javascript","node","nodejs","otp","otpauth","security","totp","two-factor","two-factor-authentication"],"created_at":"2024-08-01T02:01:30.325Z","updated_at":"2026-10-19T12:44:51.132Z","avatar_url":"https://github.com/hectorm.png","language":"JavaScript","funding_links":["https://github.com/sponsors/hectorm","https://hector.molinero.dev/donate"],"categories":["JavaScript","Packages","browser"],"sub_categories":[],"readme":"[![Last version](https://img.shields.io/github/v/tag/hectorm/otpauth?label=version)](https://github.com/hectorm/otpauth/tags)\n[![npm downloads](https://img.shields.io/npm/dm/otpauth?label=npm%20downloads)](https://www.npmjs.com/package/otpauth)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"OTPAuth\" src=\"./resources/logo/OTPAuth-Color-Reduced.svg\" height=\"192\" /\u003e\n\u003c/p\u003e\n\n# OTPAuth\n\nOne Time Password library for Node.js, Deno, Bun and browsers.\n\nIt supports the generation and validation of\nHMAC-Based One-Time Passwords (HOTP) as specified in [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226) and\nTime-Based One-Time Passwords (TOTP) as specified in [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238).\nFrequently used in Multi-Factor Authentication (MFA) / Two-Factor Authentication (2FA) systems.\n\n\u003e [!TIP]\n\u003e You can try the library with the demo application available at [otpauth.molinero.dev](https://otpauth.molinero.dev).\n\u003e\n\u003e If you wish to interact with the library in your browser console, the following snippet can be used:\n\u003e\n\u003e ```javascript\n\u003e const OTPAuth = await import(\"otpauth\");\n\u003e ```\n\n## Usage\n\nThis section presents an overview of the most common usage patterns, along with some security recommendations.\n\n### [Node.js / Bun](https://www.npmjs.com/package/otpauth)\n\n```javascript\nimport * as OTPAuth from \"otpauth\";\n// import * as OTPAuth from \"otpauth/slim\"; // Slim build without bundled dependencies.\n// import * as OTPAuth from \"otpauth/bare\"; // Bare build with no bundled crypto (requires providing a custom HMAC function).\n\n// Create a new TOTP object.\nlet totp = new OTPAuth.TOTP({\n  // Provider or service the account is associated with.\n  issuer: \"ACME\",\n  // Account identifier.\n  label: \"Alice\",\n  // Algorithm used for the HMAC function, possible values are:\n  //   \"SHA1\", \"SHA224\", \"SHA256\", \"SHA384\", \"SHA512\",\n  //   \"SHA3-224\", \"SHA3-256\", \"SHA3-384\" and \"SHA3-512\".\n  algorithm: \"SHA1\",\n  // Length of the generated tokens.\n  digits: 6,\n  // Interval of time for which a token is valid, in seconds.\n  period: 30,\n  // Arbitrary key encoded in base32 or `OTPAuth.Secret` instance\n  // (if omitted, a cryptographically secure random secret is generated).\n  secret: \"US3WHSG7X5KAPV27VANWKQHF3SH3HULL\",\n  //   or: `OTPAuth.Secret.fromBase32(\"US3WHSG7X5KAPV27VANWKQHF3SH3HULL\")`\n  //   or: `new OTPAuth.Secret()`\n  // Custom HMAC function (required for bare build, optional otherwise).\n  // hmac: (algorithm, key, message) =\u003e Uint8Array,\n});\n\n// Unless you know what you are doing, it is recommended to use the default\n// values for the algorithm, digits, and period options, as these are the most\n// common values used by most services.\n\n// Generate a cryptographically secure random secret.\n// It is NOT recommended to use less than 128 bits (16 bytes).\nlet secret = new OTPAuth.Secret({ size: 20 });\n\n// Generate a token (returns the current token as a string).\nlet token = totp.generate();\n\n// Validate a token (returns the token delta or null if it is not found in the\n// search window, in which case it should be considered invalid).\n//\n// A search window is useful to account for clock drift between the client and\n// server; however, it should be kept as small as possible to prevent brute\n// force attacks. In most cases, a value of 1 is sufficient. Furthermore, it is\n// essential to implement a throttling mechanism on the server.\n//\n// For further details on the security considerations, it is advised to refer\n// to Section 7 of RFC 4226 and Section 5 of RFC 6238:\n//   https://datatracker.ietf.org/doc/html/rfc4226#section-7\n//   https://datatracker.ietf.org/doc/html/rfc6238#section-5\nlet delta = totp.validate({ token, window: 1 });\n\n// Get the counter value (number of intervals since the Unix epoch).\n// Useful for implementing techniques against token reuse during the validity\n// period.\nlet counter = totp.counter();\n\n// Get the remaining milliseconds until the current token changes.\nlet remaining = totp.remaining();\n\n// Convert to Google Authenticator key URI format.\n// Usually the URI is encoded in a QR code that can be scanned by the user.\n// This functionality is outside the scope of the project, but there are many\n// libraries that can be used for this purpose, such as npmjs.com/package/qr\nlet uri = totp.toString();\n//   or:      `OTPAuth.URI.stringify(totp)`\n//   returns: `otpauth://totp/ACME:Alice?issuer=ACME\u0026secret=US3WHSG7X5KAPV27VANWKQHF3SH3HULL\u0026algorithm=SHA1\u0026digits=6\u0026period=30`\n\n// Convert from Google Authenticator key URI format.\ntotp = OTPAuth.URI.parse(uri);\n```\n\n### [Deno](https://jsr.io/@hectorm/otpauth)\n\n```javascript\nimport * as OTPAuth from \"jsr:@hectorm/otpauth\";\n\n// Same as above.\n```\n\n### [Browsers (ESM)](https://www.jsdelivr.com/package/npm/otpauth)\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": { \"otpauth\": \"https://cdn.jsdelivr.net/npm/otpauth@%VERSION%/dist/otpauth.esm.min.js\" },\n    \"integrity\": { \"https://cdn.jsdelivr.net/npm/otpauth@%VERSION%/dist/otpauth.esm.min.js\": \"%HASH%\" }\n  }\n\u003c/script\u003e\n\u003cscript type=\"module\"\u003e\n  import * as OTPAuth from \"otpauth\";\n\n  // Same as above.\n\u003c/script\u003e\n```\n\n### [Browsers (UMD)](https://www.jsdelivr.com/package/npm/otpauth)\n\n```html\n\u003cscript\n  src=\"https://cdn.jsdelivr.net/npm/otpauth@%VERSION%/dist/otpauth.umd.min.js\"\n  integrity=\"%HASH%\"\n  crossorigin=\"anonymous\"\n  referrerpolicy=\"no-referrer\"\n\u003e\u003c/script\u003e\n\u003cscript\u003e\n  // Same as above.\n\u003c/script\u003e\n```\n\n## Documentation\n\nFor additional information, please refer to the documentation page at [hectorm.github.io/otpauth/](https://hectorm.github.io/otpauth/).\n\n## License\n\n[MIT License](https://github.com/hectorm/otpauth/blob/master/LICENSE.md)\n© [Héctor Molinero Fernández](https://hector.molinero.dev/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhectorm%2Fotpauth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhectorm%2Fotpauth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhectorm%2Fotpauth/lists"}